PEP on path module for standard library

Mike Orr mso at oz.net
Fri Jul 29 16:43:05 EDT 2005


Michael Hoffman wrote:
> I use path in more of my modules and scripts than any other third-party
> module, and I know it will be very helpful when I no longer have to
> worry about deploying it.

Same here.  An object-oriented path module is extremely useful, and
makes one's code much less cluttered.  I've written an enhpath module
that I used in my projects, with several convenience methods and some
magic behavior.  It's too
ambitious for the standard library, but I'd like if people could at
least look at the docstring and see whether some features might be
useful in Path.  I'd also like to see Path made subclass-friendly so I
could implement this as a subclass, and others could make other
subclasses.  The docstring itself could also be ported to Path.  The
source and test suite (py.test) are here:
    http://cafepy.com/quixote_extras/rex/path/enhpath.py
    http://cafepy.com/quixote_extras/rex/path/enhpath_test.py
append "?download=1" for download-friendly format.
I sent an earlier version to Jason Orendorff and he liked some of the
changes and had some ideas of his own, but said he was too busy to do
much implementation work, and then my further letters never got a
reply.

The main changes I'd like to see in Path (some of these have been made
in Python CVS at nondist/sandbox/path/path.py) are:

- When methods create path objects, use self.__class__() instead of
Path().
  This makes it possible to subclass Path.  Otherwise you
  have to rewrite the whole thing due to the hardcoded name.

- Path.cwd() should be a class method instead of a static method, for
the same
  reason.

- The constructor behavior in CVS is good.  Path(''), Path.cwd(),
  Path() => Path.cwd().

- Need .chdir() method, otherwise you have to import os for it.

- Some way to pretty-print paths embedded in lists/dicts as strings.  I
have a
  .repr_as_str class attribute that toggles this.

- .ancestor(3) is the same as .parent.parent.parent, but more concise.

- I saw in a thread that .name and .parent were removed.  I use them
very
  frequently, along with .ext and .namebase.  I don't want to call
methods for
  these.

- '/' vs .joinpath(), no big deal.  I've been using '/' because it's
there.
  .joinpath must take multiple *args, to prevent .joinpath().joinpath()
.

- .joinancestor(N, *components) is a combination of .ancestor and
.joinpath.
  If curdir is /home/joe/Webware/www, Path.cwd().joinancestor(1, 'lib')
is
  /home/joe/Webware/lib.

- Keep .lisdir() as in CVS; it acts like os.listdir().  This is useful
even
  with paths, when you're just going to use the string basename anyway.

- Who needs .open()?  open(myPath) is fine.  But it can stay for
backward
  compatibility.



Less important but non-controversial:

- Path.tempfile(), Path.tempdir():
  Create a temporary file using tempfile.mkstemp, tempfile.mkdtemp

- Path.tempfileobject():
  Create a temporary file object using tempfile.TemporaryFile.
  (Static method.)

Controversial:

- Delete methods and mkdir should succeed silently if the operation is
  already done.  Otherwise you always have to put them in an if:
  'if foo.exists(): foo.remove()'.

- .delete_dammit() recursively deletes it, whatever it is, without you
  having to do the if file/if directory dance.  I suppose it would need
a
  politically correct name.
  which you really have to do every time you delete.

- All .dirs*, .files*, .walk* methods have a symlinks flag, default
True.
  If false, don't yield symlinks.  Add .symlinks and .walksymlinks
methods.
  This eliminates an 'if' for programs that want to treat symlinks
specially.

- I have a .move method that combines .rename, .renames, and .move; and
a .copy
  method that combines .copy, .copy2, and .copytree .

I'd appreciate a Cc on replies if your newsreader allows it.

-- Mike Orr <mso at oz.net>




More information about the Python-list mailing list