equivalent of Ruby's Pathname?

P

Phlip

Pythonistas:

Yes, calling os.path.walk() and os.path.join() all the time on raw
strings is fun, but I seem to recall from my Ruby days a class called
Pathname, which presented an object that behaved like a string at
need, and like a filesystem path at need. path + 'folder' would
call .join() and insert the / correctly, for example.

What's the best equivalent in Python-land?
 
A

alex23

Yes, calling os.path.walk() and os.path.join() all the time on raw
strings is fun, but I seem to recall from my Ruby days a class called
Pathname, which presented an object that behaved like a string at
need, and like a filesystem path at need. path + 'folder' would
call .join() and insert the / correctly, for example.

What's the best equivalent in Python-land?

It's no longer supported, but the 3rd party 'path' module used to be
the go-to module for this:
C:\Python26\lib\site-packages\path.py:32: DeprecationWarning: the md5
module is deprecated; use hashlib instead
import sys, warnings, os, fnmatch, glob, shutil, codecs, md5
c = path('C:\\')
c.listdir() [path(u'C:\\AUTOEXEC.BAT'), path(u'C:\\boot.ini'), ...]
(c + 'python26').listdir()
[path(u'C:\\python26\\circuits.pth_disabled_for_egg'), path(u'C:\
\python26\\DLLs'), ...][path(u'C:\\python26\\circuits.pth_disabled_for_egg'), path(u'C:\
\python26\\DLLs'), ...]

I've hand edited the results for brevity...

The module could do with some TLC to bring it up to date, but warning
aside it still seems to work fine under 2.6.

(From memory, I think the original author gave up when it became clear
it would never be integrated into the standard lib[1], which is a
shame, I think there's scope for a pathtools addition to the lib that
provides this level of convenience...)

There was also a PEP with another possible implementation:
http://www.python.org/dev/peps/pep-0355/

Hope this helps.
 
S

Sean DiZazzo

Yes, calling os.path.walk() and os.path.join() all the time on raw
strings is fun, but I seem to recall from my Ruby days a class called
Pathname, which presented an object that behaved like a string at
need, and like a filesystem path at need. path + 'folder' would
call .join() and insert the / correctly, for example.
What's the best equivalent in Python-land?

It's no longer supported, but the 3rd party 'path' module used to be
the go-to module for this:

C:\Python26\lib\site-packages\path.py:32: DeprecationWarning: the md5
module is deprecated; use hashlib instead
  import sys, warnings, os, fnmatch, glob, shutil, codecs, md5>>> c = path('C:\\')
[path(u'C:\\AUTOEXEC.BAT'), path(u'C:\\boot.ini'), ...]>>> (c + 'python26').listdir()

[path(u'C:\\python26\\circuits.pth_disabled_for_egg'), path(u'C:\
\python26\\DLLs'), ...]>>> (c / 'python26').listdir()

[path(u'C:\\python26\\circuits.pth_disabled_for_egg'), path(u'C:\
\python26\\DLLs'), ...]

I've hand edited the results for brevity...

The module could do with some TLC to bring it up to date, but warning
aside it still seems to work fine under 2.6.

(From memory, I think the original author gave up when it became clear
it would never be integrated into the standard lib[1], which is a
shame, I think there's scope for a pathtools addition to the lib that
provides this level of convenience...)

There was also a PEP with another possible implementation:http://www.python.org/dev/peps/pep-0355/

Hope this helps.

It's too bad that something like this can't be agreed to. I used a
homegrown module like this for a couple of years in my early days with
python. It was great, but I didn't know enough at the time to make it
really useful.

Why did Path() get rejected? Is it the idea itself, or just the
approach that was used? What are the complaints?

~Sean
 
A

Aahz

Why did Path() get rejected? Is it the idea itself, or just the
approach that was used? What are the complaints?

You should search for the discussiona around it.
 
P

Phlip

C

Carl Banks

It's no longer supported, but the 3rd party 'path' module used to be
the go-to module for this:
C:\Python26\lib\site-packages\path.py:32: DeprecationWarning: the md5
module is deprecated; use hashlib instead
  import sys, warnings, os, fnmatch, glob, shutil, codecs, md5>>> c = path('C:\\')
[path(u'C:\\AUTOEXEC.BAT'), path(u'C:\\boot.ini'), ...]>>> (c + 'python26').listdir()
[path(u'C:\\python26\\circuits.pth_disabled_for_egg'), path(u'C:\
\python26\\DLLs'), ...]>>> (c / 'python26').listdir()
[path(u'C:\\python26\\circuits.pth_disabled_for_egg'), path(u'C:\
\python26\\DLLs'), ...]
I've hand edited the results for brevity...
The module could do with some TLC to bring it up to date, but warning
aside it still seems to work fine under 2.6.
(From memory, I think the original author gave up when it became clear
it would never be integrated into the standard lib[1], which is a
shame, I think there's scope for a pathtools addition to the lib that
provides this level of convenience...)
There was also a PEP with another possible implementation:http://www.python.org/dev/peps/pep-0355/
Hope this helps.

It's too bad that something like this can't be agreed to.  I used a
homegrown module like this for a couple of years in my early days with
python.  It was great, but I didn't know enough at the time to make it
really useful.

Why did Path() get rejected?  Is it the idea itself, or just the
approach that was used?  What are the complaints?

I don't know if it was the reason it was rejected, but a seriously
divisive question is whether the path should be a subset of string.

Under ordinary circumstances it would be a poor choice for inheritance
(only a few string methods would be useful fot a pathname), but some
people were fiercely adamant that paths should be passable to open()
as-in (without having to explicity convert to string). IIRC, the guy
who maintained path wavered between subclassing and not subclassing
str. I don't remember if the idea of modifying open to accept path
objects came up.


Carl Banks
 
P

Phlip

Carl said:
I don't know if it was the reason it was rejected, but a seriously
divisive question is whether the path should be a subset of string.

OMG that's nothing but the OO "circle vs ellipse" non-question. Glad
to see the Committee derailed a perfectly good library over such
sophistry.
Under ordinary circumstances it would be a poor choice for inheritance
(only a few string methods would be useful fot a pathname), but some
people were fiercely adamant that paths should be passable to open()
as-in (without having to explicity convert to string).

That's just silly. To be object-based, you should say path.open('r').
fopen() and its ilk are too 1960s...

My 5th Grade science teacher, one Eunice Feight, once expressed
chagrin for submitting a proposal to Readers' Digest, and getting it
accepted. She sold them the following sloka:

Don't be clever don't be witty
Or you'll wind up BEING the Committee!
 
G

Gregory Ewing

Carl said:
I don't remember if the idea of modifying open to accept path
objects came up.

It wouldn't just be open() that people would want modified --
it would be every other function that takes a pathname as
well.

I seem to recall another point of contention was whether
path objects should have methods for accessing the file
system (opening files, renaming them, etc.) or whether it
should confine itself to representing and manipulating
pathnames.

In any case, introducing any kind of path object at this
late stage of the language's development would result in
More Than One Way to represent pathnames, with neither of
them being the obvious choice.
 
S

Steve Holden

Phlip said:
OMG that's nothing but the OO "circle vs ellipse" non-question. Glad
to see the Committee derailed a perfectly good library over such
sophistry.
That's nothing but the most arrant nonsense, as you would discover if
you took the trouble to read the discussion on python-dev instead of
jumping to conclusions.
That's just silly. To be object-based, you should say path.open('r').
fopen() and its ilk are too 1960s...
What? Are you arguing for "myfile.txt".open('r') to be a valid Python
construct? If not then surely you can see that paths would require
different treatment from strings, which was the main thrust of the
discussion on the dev list.

I find it really irritating when the clueless come along and criticize
decisions made by the developers after thorough discussion. Not only do
decisions have to be made about how code is going to work (and work for
the next twenty years or so), but someone has to commit to maintaining
the code before it goes in (otherwise Python will be full of bit-rot).

To call your criticism ill-informed would be flattering it.
My 5th Grade science teacher, one Eunice Feight, once expressed
chagrin for submitting a proposal to Readers' Digest, and getting it
accepted. She sold them the following sloka:

Don't be clever don't be witty
Or you'll wind up BEING the Committee!
Criticism isn't pretty
Specially when your logic's shitty.

regards
Steve
 
C

Chris Rebert

That's nothing but the most arrant nonsense, as you would discover if
you took the trouble to read the discussion on python-dev instead of
jumping to conclusions.

What? Are you arguing for "myfile.txt".open('r') to be a valid Python
construct? If not then surely you can see that paths would require
different treatment from strings, which was the main thrust of the
discussion on the dev list.

Based on the context, I'm /pretty/ sure he was (implicitly) talking
about e.g. Path("myfile.txt").open('r').

Cheers,
Chris
 
P

Phlip

Gregory said:
It wouldn't just be open() that people would want modified --
it would be every other function that takes a pathname as
well.

Then refer to the same argument against implicit type conversions in C+
+.

A ::std::string must call .c_str() to turn into a lowly char*, before
passing into a C function. Advocating for 8 characters of convenience
opens the risk of silent bugs at refactor time.
I seem to recall another point of contention was whether
path objects should have methods for accessing the file
system (opening files, renaming them, etc.) or whether it
should confine itself to representing and manipulating
pathnames.

In that case, the package I picked seems to have "erred" on the side
of programmer convenience.

Because the basic file operations (exist, stat, move/rename, copy,
open, chmod, unlink) come as a complete and whole kit, a class should
simply present that kit, insulating against filesystem differences.
In any case, introducing any kind of path object at this
late stage of the language's development would result in
More Than One Way to represent pathnames, with neither of
them being the obvious choice.

Ah, now we get down to the root of the problem. Because Python is so
stuck on the "one best way to do it" mentality, language bigotry
prevented the Committee from picking from among several equally valid
but non-best options. And after 20 years of growth, Python still has
no Pathname class. What a mature community! C-:
 
B

Bruno Desthuilliers

Phlip a écrit :
Ah, now we get down to the root of the problem. Because Python is so
stuck on the "one best way to do it"
mentality, language bigotry
prevented the Committee from picking from among several equally valid
but non-best options.

You failed to actually _read_ what you're answering to. Try again. Using
your brain, this time.
 
C

Chris Rebert

Ah, now we get down to the root of the problem. Because Python is so
stuck on the "one best way to do it" mentality, language bigotry
prevented the Committee from picking from among several equally valid
but non-best options. And after 20 years of growth, Python still has
no Pathname class. What a mature community! C-:

Committee? I think you have us confused with C++...

*wink*,
Chris
 
S

Sean DiZazzo

You should search for the discussiona around it.

I read the discussion, and there was definitely some going back and
forth on whether it should be sub-classed from string, but the
conversation just seemed to stop abruptly with no decision one way of
the other. Maybe I missed a thread.

I guess being dropped without a final go-ahead is just as good as a
formal no anyway.
 
A

Aahz

I read the discussion, and there was definitely some going back and
forth on whether it should be sub-classed from string, but the
conversation just seemed to stop abruptly with no decision one way of
the other. Maybe I missed a thread.

I guess being dropped without a final go-ahead is just as good as a
formal no anyway.

Not quite: because it was not rejected, someone who wants to shepherd the
process forward would likely be welcomed (even if it ends up with formal
rejection). I suggest starting by writing your own summary of the
previous discussion and see if the people involved agree that your
summary is reasonably accurate. Also check to see if the original PEP
writer wants to be involved or whether zie is willing to have you take
over.

Another good (and related) starting point would be to create a reasoning
favoring one side or the other that was not brought up in previous
discussion.
 
M

Mike Orr

I just saw this thread on the Python-URL.


It has a habit of being discussed and dropped repeatedly. The main
issue is that Guido doesn't see an OO approach as necessarily better
than the existing functions, so it has a high bar for acceptance. One
issue is that some people see a need to separate filesystem-
independent functionality (joining paths and extracting components)
from filesystem-dependent functionality (listing directories, removing
files, etc). ``path.py`` and PEP 355 were rejected mainly because of
this. There was support for a small filesystem-independent class that
could be put into the stdlib, and some modest moving/renaming of the
filesystem functions (which are scattered across os, os.path, shutil,
glob, etc). We were hoping to get this done for Python 3 but didn't
make it. I wrote a ``Unipath`` package that tried to be a compromise
between what everybody wanted, with a FS-independent class and a FS-
dependent subclass, but could not get any feedback on it. Somebody
else was going to write a PEP for the renamings, but I never saw it.

Since then, path.py has been included in a couple packages and seems
to have the most widespread use. I gave up on the stdlib and
reconfigured Unipath as a pure 3rd-party library. (The FS-independent
AbstractPath class is still there if anybody wants to use it for a
PEP.) The other people who made their own implementations seemed to be
happy with theirs, and that was that.

The string vs non-string argument has pretty much been decided in
favor of strings (i.e., a string subclass). Not ``"a.txt".open()`` but
``open(Path("a.txt"))``. Too many standard and 3rd-party modules
expect string paths: you'd have to convert your path to a string every
time you pass it as an argument. The main problem with string paths
is that .join() means something else, but that's usually solved by
using a different method name: "joinpath", "child", "/", etc.

Other proposals have been a tuple subclass, so that ``Path("a/b/c.txt")
[-1] == Path("c.txt")``, and a library that can do non-native paths
(Windows style on Unix systems and vice-versa). These don't seem to be
in vogue anymore.

What has become more common is virtual paths; i.e., the same interface
for filesystems, FTP, zip files, etc. That was discussed during the
last go-around but there were no implementations. Now there are a few
projects active on this, such as http://groups.google.com/group/stdpyfs
.. This is probably the future of any path object, so it would make
sense to define a path now that can work with all these backends.

--Mike
 
M

Martin P. Hellwig

On 02/09/10 14:00, Phlip wrote:
Ah, now we get down to the root of the problem. Because Python is so
stuck on the "one best way to do it" mentality, language bigotry
prevented the Committee from picking from among several equally valid
but non-best options. And after 20 years of growth, Python still has
no Pathname class. What a mature community! C-:
<cut>
Well even if this statement would be true, I personally think that not
proclaiming something a 'standard' if you are sure that you are not sure
about it, is a virtue.
 
P

Phlip

Martin said:
Well even if this statement would be true, I personally think that not
proclaiming something a 'standard' if you are sure that you are not sure
about it, is a virtue.

In terms of trying too hard to achieve perfection, am I missing a
Python repository similar to the C++ Boost project? All the nice-to-
have classes that extend the core of C++ get to live in Boost before
the C++ Committee pulls the best ideas off the top and add them to the
Standard Library...
 
C

Chris Rebert

In terms of trying too hard to achieve perfection, am I missing a
Python repository similar to the C++ Boost project? All the nice-to-
have classes that extend the core of C++ get to live in Boost before
the C++ Committee pulls the best ideas off the top and add them to the
Standard Library...

The next closest thing would probably be the Python Cookbook:
http://code.activestate.com/recipes/langs/python/

However, such stuff can also be found as third-party modules.

Cheers,
Chris
 
P

Phlip

Chris said:
The next closest thing would probably be the Python Cookbook:http://code.activestate.com/recipes/langs/python/

One thing I really like about ... my hacked version of path.py ... is
path.cd( lambda: ... ). It works great inside fabfile.py to
temporarily switch to a different folder:

sample_project = path('sample_project').abspath()

def run():
sample_project.cd( lambda:
_sh('python manage.py runserver 0.0.0.0:8000 --
settings=test_settings') )

After the lambda runs, we exception-safely return to the home folder.

(BTW I'm aware that a fabfile.py command with only one statement will
return to its shell and remain in the correct folder. It's just ...
the thought!)

This be .cd():

class path:

def cd(self, block=None):
previous = path(os.path.curdir).abspath()
self.chdir()

if block:
try: block()
finally: previous.chdir()

That's based on Jason Orendoff's work at http://www.jorendorff.com/articles/python/path
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top