Sugesstion: pushd()

65 views
Skip to first unread message

Steve Howe

unread,
Sep 12, 2008, 3:09:34 AM9/12/08
to paver
Hello all,

Here is a tip of something I've been using on quite a lot of my pavements: a
pushd context manager that runs a block of statements into another directory:

##
from __future__ import with_statement
from contextlib import contextmanager

@contextmanager
def pushd(dir):
''' A context manager for pushing into a dir and automatically coming back
to the previous one '''
old_dir = os.getcwd()
runtime.info('cd %s' % dir)
os.chdir(dir)
yield
runtime.info('cd %s' % old_dir)
os.chdir(old_dir)

# Usage:
import os
print "Running from dir", os.getcwd()
with pushd(os.pardir):
print "Now running from parent dir:", os.getcwd()
print "Back to the previous dir:", os.getcwd()

##

It can also be easily adapted to be a path object attribute. Feel free to use
the code anywhere you like.

The only regard is that it will not work with older Python versions due to the
context managers dependency.
--
Best Regards,
Steve Howe

Matt Kangas

unread,
Sep 12, 2008, 4:01:58 PM9/12/08
to paver
Cool! I am personally stuck using Python 2.4 for now (at least until I
can make our build process more systematic, and push through an
upgrade to 2.5!). But this seems like a handy shortcut.

Kevin Dangoor

unread,
Sep 15, 2008, 9:41:33 AM9/15/08
to pa...@googlegroups.com
I like it, and it should be possible to make a 2.4-compatible version
as well.

This will likely belong in paver/path.py (though not on the path
object itself, of course). For 2.4, there would likely just be a
dirstack object or something of that sort that lets you push and pop.
The context manager is an elegant way to handle this, though.

I'd monkey with this myself, but I am completely swamped right now.

Kevin

--
Kevin Dangoor
Product Manager
SitePen, Inc.
Web development experts:
development, support, training

ke...@sitepen.com

jhermann

unread,
Sep 16, 2008, 6:47:08 AM9/16/08
to paver
The thing should probably yield the OLD cwd, since you can get the new
one easily with os.getcwd(), but not the previous (stacked) one,
unless you remember it yourself, which can be done easier like so ==>

with pushd(target) as oldcwd:
shutil.copytree(oldcwd, ".") # just an example
...

And btw, your implementation needs a try/finally.

Steve Howe

unread,
Sep 16, 2008, 12:48:27 PM9/16/08
to pa...@googlegroups.com
Hello all,

> The thing should probably yield the OLD cwd, since you can get the new
> one easily with os.getcwd(), but not the previous (stacked) one,
> unless you remember it yourself, which can be done easier like so ==>
>
> with pushd(target) as oldcwd:
> shutil.copytree(oldcwd, ".") # just an example
> ...
I didn't need it, so I didn't implement, but I guess that would be welcome.

> And btw, your implementation needs a try/finally.

No it doesn't. I wanted it to raise an error if something went wrong.

jhermann

unread,
Sep 17, 2008, 6:24:32 AM9/17/08
to paver
> > And btw, your implementation needs a try/finally.
>
> No it doesn't. I wanted it to raise an error if something went wrong.

You have to change back to the original cwd no matter what happens,
else you break the contract of the context. Note I didn't say try/
except, the finally just ensures that the setcwd(old_cwd) happens no
matter whether the context body raised an exception or not.

Kevin Dangoor

unread,
Mar 6, 2009, 11:07:38 AM3/6/09
to pa...@googlegroups.com
On Fri, Sep 12, 2008 at 2:09 AM, Steve Howe <howe...@gmail.com> wrote:
> Here is a tip of something I've been using on quite a lot of my pavements: a
> pushd context manager that runs a block of statements into another directory:

FYI, this is finally in Paver 1.0a3. I had to go out of my way a bit
to ensure that Paver will still work with Python 2.4, but it should
(you don't get pushd, then).

Kevin


--
Kevin Dangoor

work: http://labs.mozilla.com/
email: k...@blazingthings.com
blog: http://www.BlueSkyOnMars.com

Reply all
Reply to author
Forward
0 new messages