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

Calvin Spealman ironfroggy at gmail.com
Sat Oct 6 20:42:22 CEST 2012


On Sat, Oct 6, 2012 at 1:08 PM, Antoine Pitrou <solipsis at pitrou.net> wrote:
> On Sat, 6 Oct 2012 12:14:40 -0400
> Calvin Spealman <ironfroggy at gmail.com>
> wrote:
>>
>> It feels like this proposal is "make it object oriented, because
>> object oriented is good" without any actual justification or obvious
>> problem this solves. The API looks clunky and redundant, and does not
>> appear to actually improve anything over the facilities in the os.path
>> module.
>
> Personally, I cringe everytime I have to type
> `os.path.dirname(os.path.dirname(os.path.dirname(...)))` to go two
> directories upwards of a given path. Compare, with, say:
>
>>>> p = Path('/a/b/c/d')
>>>> p.parent(2)
> PosixPath('/a/b')

I would never do the first version in the first place. I would just
join(my_path, "../..")

Note that we really need to get out of the habit of "import os"
instead of "from os.path import join, etc..." We are making our code
uglier and arbitrarily creating many of your concerns by making the
use of os.path harder than it should be.

> Really, I don't think os.path is the prettiest or most convenient
> "battery" in the stdlib.
>
>> This takes a lot of things we can already do with paths and
>> files and remixes them into a not-so intuitive API for the sake of
>> change, not for the sake of solving a real problem.
>
> Ironing out difficulties such as platform-specific case-sensitivity
> rules or the various path separators is a real problem that is not
> solved by a os.path-like API, because you can't muck with str and give
> it the required semantics for a filesystem path. So people end up
> sprinkling their code with calls to os.path.normpath() and/or
> os.path.normcase() in the hope that it will appease the Gods of
> Portability (which will also lose casing information).

I agree this stuff is difficult, but I think normalizing is a lot more
predictable than lots of platform specific paths (both FS and code
paths)

>> Not inheriting from str means that we can't directly path these path
>> objects to existing code that just expects a string, so we have a
>> really hard boundary around the edges of this new API. It does not
>> lend itself well to incrementally transitioning to it from existing
>> code.
>
> As discussed in the PEP, I consider inheriting from str to be a mistake
> when your intent is to provide different semantics from str.
>
> Why should indexing or iterating over a path produce individual
> characters?
> Why should Path.split() split over whitespace by default?
> Why should "c:\\" be considered unequal to "C:\\" under Windows?
> Why should startswith() work character by character, rather than path
> component by path component?

Good points, but I'm not convinced that subclasses from string means
you can't change these in your subclass.

> These are all standard str behaviours that are unhelpful when applied
> to filesystem paths.

We agree there.

> As for the transition, you just have to call str() on the path object.
> Since str() also works on plain str objects (and is a no-op), it seems
> rather painless to me.

But then I loose all the helpful path information. Something further
down the call chain, path aware, might be able to make use of it.

> (Of course, you are not forced to transition. The PEP doesn't call for
> deprecation of os.path.)

If we are only adding something redundant and intend to leave both
forever, it only feels like bloat. We should be shrinking the stdlib,
not growing it with redundant APIs.

>> The stat operations and other file-facilities tacked on feel out of
>> place, and limited. Why does it make sense to add these facilities to
>> path and not other file operations? Why not give me a read method on
>> paths? or maybe a copy?
>
> There is always room to improve and complete the API without breaking
> compatibility. To quote the PEP: “More operations could be provided,
> for example some of the functionality of the shutil module”.

What I meant is that I can't extend it in third party code without
being second class. I can add another library that does file
operations os.path or stat() don't provide, and they sit side by side.

> The focus of the PEP is not to enumerate every possible file operation,
> but to propose the semantic and syntactic foundations (such as how to
> join paths, how to divide them into their individual components, etc.).
>
>> Putting lots of file facilities on a path
>> object feels wrong because you can't extend it easily. This is one
>> place that function(thing) works better than thing.function()
>
> But you can still define a function() taking a Path as an argument, if
> you need to.
> Similarly, you can define a function() taking a datetime object if the
> datetime object's API lacks some useful functionality for you.
>
> Regards
>
> Antoine.
>
>
> --
> Software development and contracting: http://pro.pitrou.net
>
>
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> http://mail.python.org/mailman/listinfo/python-ideas



-- 
Read my blog! I depend on your acceptance of my opinion! I am interesting!
http://techblog.ironfroggy.com/
Follow me if you're into that sort of thing: http://www.twitter.com/ironfroggy



More information about the Python-ideas mailing list