[Python-ideas] PEP 428 - object-oriented filesystem paths

Antoine Pitrou solipsis at pitrou.net
Sat Oct 13 18:28:30 CEST 2012


Le dimanche 14 octobre 2012 à 01:37 +1000, Nick Coghlan a écrit :
> On Sat, Oct 13, 2012 at 8:06 PM, Antoine Pitrou <solipsis at pitrou.net> wrote:
> > The question is: why do you want to do that?
> > I know there are a limited bunch of special cases where Posix filesystem
> > paths may be case-insensitive, but nobody really cares about them today,
> > and I don't expect many people to bother tomorrow. Playing with
> > individual parameters of path semantics sounds like a theoretical bother
> > more than a practical one.
> 
> It's a useful trick for writing genuinely cross-platform code: when
> I'm writing cross-platform code on *nix, I want my paths to behave
> like posix paths in every respect *except* I want them to complain
> somehow if any of my names only differ by case.

But that's not cross-platform. Under Windows you must also care about
reserved files (CON, NUL, etc.). Also, you can create Posix filenames
with backslashes in them, but under Windows they will be treated as
directory separators. Mercurial learnt this the hard way:
http://selenic.com/repo/hg-stable/file/605fe310691f/mercurial/store.py#l124

> On the Windows side, it would be nice to be able to request the use of
> "/" as the directory separator when converting to a string. Using "\"
> has the potential to cause interoperability problems (e.g. with
> regular expressions).

The PEP mentions the .as_posix() method, which does exactly that.
(use of regular expressions on whole paths sounds like a weird idea, but
hey :-))

> If you don't like the implicit nature of contexts (a perfectly
> reasonable complaint), then I suggest going for an explicit strategy
> pattern with flavours rather than requiring classes.
> With this approach, the flavour would be specified on a *per-instance*
> basis (with the default behaviour being determined by the OS).

If you s/would/could/, I have nothing against it, but I certainly don't
understand why you dislike the approach of providing dedicated classes
*by default*.

IMO, having separate classes is simpler to use, easier to type, more
discoverable (using pydoc or help() or tab-completion at the prompt),
and it has an educational value that a keyword-only "flavour" argument
doesn't have.

> The main classes would then *delegate* the flavour dependent
> operations like parsing, conversion to a string and equality
> comparisons to the flavour objects.

Which they already do :) Here is the code:

class PurePosixPath(PurePath):
    _flavour = _posix_flavour
    __slots__ = ()

class PureNTPath(PurePath):
    _flavour = _nt_flavour
    __slots__ = ()

(https://bitbucket.org/pitrou/pathlib/src/f6df458aaa89/pathlib.py?at=default#cl-990)

> The decimal-style thread-based dynamic contexts
> are more useful when you want to change the behaviour *without* either
> copying or mutating objects, which I agree is overkill for path
> manipulation.

Not only overkill, but incorrect and dangerous!

> You can add as many new flavours as you want, and it's only one class
> per flavour rather than up to 3 (the flavour itself, the pure variant
> and the concrete variant).

Yes, you can. That doesn't preclude offering separate classes by
default, though :-)

> This class hierarchy is also more amenable to the introduction of
> MutablePath as a second subclass of PurePath - a path variant with
> mutable properties still sounds potentially attractive to me (over a
> wide variety of return-a-modified-copy methods for various cases).

I'm very cold on offering both mutable on non-mutable paths. That's just
complicated and confusing. Since an immutable type is very desireable
for use in associative containers, I think immutability is the right
choice.

Regards

Antoine.


-- 
Software development and contracting: http://pro.pitrou.net





More information about the Python-ideas mailing list