
Thoughts? Regards, --- Giampaolo http://code.google.com/p/pyftpdlib/ http://code.google.com/p/psutil/

Why provide two functions instead of just something like innested and allow the user to switch the arguments? Brendan Moloney Senior Research Assistant / Programmer Advanced Imaging Research Center Oregon Health Science University ________________________________________ From: python-ideas-bounces+moloney=ohsu.edu@python.org [python-ideas-bounces+moloney=ohsu.edu@python.org] On Behalf Of John O'Connor [jxo6948@rit.edu] Sent: Thursday, July 07, 2011 4:24 PM To: Giampaolo Rodolà Cc: python-ideas@python.org Subject: Re: [Python-ideas] os.path.isparent and os.path.ischild On Thu, Jul 7, 2011 at 4:08 PM, Giampaolo Rodolà <g.rodola@gmail.com<mailto:g.rodola@gmail.com>> wrote:
What about is{ancestor, descendant}() ?

On Thu, Jul 7, 2011 at 4:45 PM, Brendan Moloney <moloney@ohsu.edu> wrote:
Why provide two functions instead of just something like innested and allow the user to switch the arguments?
The former would likely be more readable. One implementation would be expressed in terms of the other.

There are a small number of operators which can be used on a large number of types. There is also a long standing tradition of having distinct symbols for reciprocal operations in mathematics. Should we provide reciprocal functions whenever possible? Should there be a 'issuperclass' function to compliment the 'issubclass' function? At some point you have to ask if the increased clutter in the API is worth the improved readability. In this case I am not sure that it does. Brendan ________________________________________ From: chris@rebertia.com [chris@rebertia.com] On Behalf Of Chris Rebert [pyideas@rebertia.com] Sent: Thursday, July 07, 2011 5:30 PM To: Brendan Moloney Cc: John O'Connor; Giampaolo Rodolà; python-ideas@python.org Subject: Re: [Python-ideas] os.path.isparent and os.path.ischild
<satire> Why provide pairs of comparison operators [(>, <), (>=, <=)] instead of just one from each pair? The user can always switch the arguments themself. </satire> Cheers, Chris

2011/7/8 Brendan Moloney <moloney@ohsu.edu>:
Why provide two functions instead of just something like innested and allow the user to switch the arguments?
I'm not sure I'm following you. Could you please provide an example? Regards, --- Giampaolo http://code.google.com/p/pyftpdlib/ http://code.google.com/p/psutil/

Giampaolo Rodolà wrote:
isparent('/a', '/a/b') True
I'm not sure that this is so common and useful that it needs to be included in os.path. You can always just add it to your own library, or even write them in-line: the implementation is just a one-liner. def isparent(path1, path2): "Returns True if path1 is a parent of path2." return os.path.commonprefix([path1, path2]) == path1 def ischild(path1, path2): "Returns True if path1 is a child of path2." return os.path.commonprefix([path1, path2]) == path2 -- Steven

Andrew Bennetts wrote:
I would call that a bug in commonprefix.
os.path.commonprefix(['/dir/pics/file', '/dir/pictures/file']) '/dir/pic'
commonprefix is documented as returning the longest common path component, not leading substring:
help(os.path.commonprefix)
commonprefix(m) Given a list of pathnames, returns the longest common leading component -- Steven

Steven D'Aprano wrote: I would call that a bug in commonprefix.
The documentation on the website correctly describes this behavior (http://docs.python.org/library/os.path.html) while the docstring does not. Someone tried to make the behavior more sane some time ago (http://bugs.python.org/issue400788) but this was reverted since it was backwards incompatible and the documentation correctly described the behavior. There is currently an open issue (http://bugs.python.org/issue10395) to add a function that does what commonprefix should have done to start with. Once this function is present I see no need for an is{parent|child} function. Brendan

Oleg Broytman wrote:
Why is that an oops? On my Linux system, I can create a file "C:\\Program Files" which is very different from the path "C:/Program Files/Python" (two directories and a file). Other operating systems may do things differently, but for me, they have no path in common:
If you want to normalise the paths first, normalise them. That's what normpath and normcase are for. The other path manipulation functions, like os.path.split(), don't normalise paths before operating on them. Why should isparent and ischild? -- Steven

On 8 July 2011 00:08, Giampaolo Rodolà <g.rodola@gmail.com> wrote:
Underspecified. Are these simply string operations? If not, how would symlinks be handled? What about case sensitivity (given that detecting case sensitivity per filesystem is not possible, in practical terms)? What about os.sep and os.altsep (\ and / on Windows)? By the time you've answered all of these questions, you may as well code the operations. Then let's see if people use them before putting them into the standard library. If you're only looking at small utility wrappers round os.path.commonprefix, then I don't see the point (such a wrapper is easy enough to write if you need it in your own code). In reality, os.path is a compromise providing "simplistic but good enough" path handling. If I assume you intend these operations also to be "simplistic but good enough", then I see little benefit that I can't get with os.path.commonprefix (and maybe a couple of lines of wrapper, if I use the idiom a lot). Personally, I don't expect I'd ever use something like this. Also, if isparent(x,y) and ischild(y,x) are intended to be equivalent, then I don't see the value in having both (comments about comparison operators notwithstanding). And if there's a subtle difference I've missed, you haven't explained it well enough :-) Having said all this, I support the idea of having a better set of path handling functions in the stdlib. But it's far from a simple problem to do it right in a sufficiently cross-platform way. And just adding functions to os.path probably isn't the right way to start. Paul.

On Thu, Jul 7, 2011 at 8:08 PM, Giampaolo Rodolà <g.rodola@gmail.com> wrote:
See the append of the path separator for the third case later. ischild() would be very similar. Regards, -- . Facundo Blog: http://www.taniquetil.com.ar/plog/ PyAr: http://www.python.org/ar/

On Fri, Jul 08, 2011 at 10:18:15AM -0300, Facundo Batista wrote:
Look at a slightly better implementation shutil.destinsrc. Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

Paul Colomiets <paul@colomiets.name> writes:
I think this behaviour is also part of the expectation:: >>> path = '/a/b/c/d' >>> isparent('/a', path) True >>> isparent('/a/b', path) True >>> isparent('/a/b/z', path) False >>> ischild(path, '/a') True >>> ischild(path, '/a/b') True >>> ischild(path, '/a/b/z') False >>> '/a' == dirname(path) False >>> '/a/b' == dirname(path) False >>> '/a/b/z' == dirname(path) False -- \ “See, in my line of work you gotta keep repeating things over | `\ and over and over again, for the truth to sink in; to kinda | _o__) catapult the propaganda.” —George W. Bush, 2005-05 | Ben Finney

On Thu, Jul 14, 2011 at 05:51:49AM -0400, Eric V. Smith wrote:
Then isparent() seems like a bad name. isancestor(), maybe? Not that I think it needs to be added to the stdlib.
It's already in the stdlib, called shutil.destinsrc ("destination in source"). Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

Oleg Broytman <phd@phdru.name> writes:
It's already in the stdlib, called shutil.destinsrc ("destination in source").
Not according to <URL:http://docs.python.org/library/shutil.html> nor <URL:http://docs.python.org/py3k/library/shutil.html>; no mention of a ‘destinsrc’. Which documentation should we be looking at to find that? -- \ “The best is the enemy of the good.” —Voltaire, _Dictionnaire | `\ Philosophique_ | _o__) | Ben Finney

On Thu, Jul 14, 2011 at 08:45:06PM +1000, Ben Finney wrote:
In py3k it was renamed to _destinsrc. It never was documented. So to "add" it to the stdlib just rename it back and document it. Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

Oleg Broytman <phd@phdru.name> writes:
In py3k it was renamed to _destinsrc. It never was documented.
Both of which strongly indicate the intent that it shouldn't be used as part of the library API. So it is disingenuous to suggest that it's already in the standard library; it's nice that there's an implementation there, but it's clearly being moved further from intended use. Who made that change? Presumably their opinion on this matter is opposite to the proponents of the functionality in this thread. Can someone ask them to comment in this thread as to their rationale? -- \ “Beware of bugs in the above code; I have only proved it | `\ correct, not tried it.” —Donald Knuth, 1977-03-29 | _o__) | Ben Finney

On 14 July 2011 14:10, Ben Finney <ben+python@benfinney.id.au> wrote:
It's easy to find out who made the change: http://hg.python.org/cpython/rev/0ab36796dd79 -- Arnaud

Arnaud Delobelle <arnodel@gmail.com> writes:
I'm glad you found it easy, and thank you for doing so.
Made by Benjamin Peterson on 2009-02-07, with the commit message “make destinsrc private”. Benjamin, what was the rationale for making ‘shutil.destinsrc’ no longer part of the public API? I'm asking in the context of a thread that suggests adding that exact functionality to the standard library, before we were aware of this code being there. -- \ “I am too firm in my consciousness of the marvelous to be ever | `\ fascinated by the mere supernatural …” —Joseph Conrad, _The | _o__) Shadow-Line_ | Ben Finney

Ben Finney <ben+python@...> writes:
Benjamin, what was the rationale for making ‘shutil.destinsrc’ no longer part of the public API?
Please see http://bugs.python.org/issue2047

Benjamin Peterson <benjamin@python.org> writes:
Thank you. (Has the Python development team considered a policy of noting bug report URLs in the commits that address those bug reports? That would have made the forensic work easier.) So AFAICT the strongest justification for the change has its origin in <URL:http://bugs.python.org/issue2047#msg63157> by Raghuram Devarakonda: destinsrc() is an internal function used only in shutil.move(). But I don't see an argument made against Joseph Armbruster's suggestion <URL:http://bugs.python.org/issue2047#msg63156>: I would have expected to find a function like this in os.path, not shutil. -- \ “Come on Milhouse, there’s no such thing as a soul! It’s just | `\ something they made up to scare kids, like the Boogie Man or | _o__) Michael Jackson.” —Bart, _The Simpsons_ | Ben Finney

On 7/14/2011 6:59 PM, Ben Finney wrote:
This is now standard. If 'issue #xxxx' appears in the commit message, a message reporting the commit is auto-generated and sent to the tracker. Since this saves developer effort, it usually is done. -- Terry Jan Reedy

Ben Finney <ben+python@...> writes:
They generally do when they remember. :)
Sounds more like an observation than a suggestion. I personally don't care whether/where this functionality is exposed, so by all means file an issue if you want.

Why provide two functions instead of just something like innested and allow the user to switch the arguments? Brendan Moloney Senior Research Assistant / Programmer Advanced Imaging Research Center Oregon Health Science University ________________________________________ From: python-ideas-bounces+moloney=ohsu.edu@python.org [python-ideas-bounces+moloney=ohsu.edu@python.org] On Behalf Of John O'Connor [jxo6948@rit.edu] Sent: Thursday, July 07, 2011 4:24 PM To: Giampaolo Rodolà Cc: python-ideas@python.org Subject: Re: [Python-ideas] os.path.isparent and os.path.ischild On Thu, Jul 7, 2011 at 4:08 PM, Giampaolo Rodolà <g.rodola@gmail.com<mailto:g.rodola@gmail.com>> wrote:
What about is{ancestor, descendant}() ?

On Thu, Jul 7, 2011 at 4:45 PM, Brendan Moloney <moloney@ohsu.edu> wrote:
Why provide two functions instead of just something like innested and allow the user to switch the arguments?
The former would likely be more readable. One implementation would be expressed in terms of the other.

There are a small number of operators which can be used on a large number of types. There is also a long standing tradition of having distinct symbols for reciprocal operations in mathematics. Should we provide reciprocal functions whenever possible? Should there be a 'issuperclass' function to compliment the 'issubclass' function? At some point you have to ask if the increased clutter in the API is worth the improved readability. In this case I am not sure that it does. Brendan ________________________________________ From: chris@rebertia.com [chris@rebertia.com] On Behalf Of Chris Rebert [pyideas@rebertia.com] Sent: Thursday, July 07, 2011 5:30 PM To: Brendan Moloney Cc: John O'Connor; Giampaolo Rodolà; python-ideas@python.org Subject: Re: [Python-ideas] os.path.isparent and os.path.ischild
<satire> Why provide pairs of comparison operators [(>, <), (>=, <=)] instead of just one from each pair? The user can always switch the arguments themself. </satire> Cheers, Chris

2011/7/8 Brendan Moloney <moloney@ohsu.edu>:
Why provide two functions instead of just something like innested and allow the user to switch the arguments?
I'm not sure I'm following you. Could you please provide an example? Regards, --- Giampaolo http://code.google.com/p/pyftpdlib/ http://code.google.com/p/psutil/

Giampaolo Rodolà wrote:
isparent('/a', '/a/b') True
I'm not sure that this is so common and useful that it needs to be included in os.path. You can always just add it to your own library, or even write them in-line: the implementation is just a one-liner. def isparent(path1, path2): "Returns True if path1 is a parent of path2." return os.path.commonprefix([path1, path2]) == path1 def ischild(path1, path2): "Returns True if path1 is a child of path2." return os.path.commonprefix([path1, path2]) == path2 -- Steven

Andrew Bennetts wrote:
I would call that a bug in commonprefix.
os.path.commonprefix(['/dir/pics/file', '/dir/pictures/file']) '/dir/pic'
commonprefix is documented as returning the longest common path component, not leading substring:
help(os.path.commonprefix)
commonprefix(m) Given a list of pathnames, returns the longest common leading component -- Steven

Steven D'Aprano wrote: I would call that a bug in commonprefix.
The documentation on the website correctly describes this behavior (http://docs.python.org/library/os.path.html) while the docstring does not. Someone tried to make the behavior more sane some time ago (http://bugs.python.org/issue400788) but this was reverted since it was backwards incompatible and the documentation correctly described the behavior. There is currently an open issue (http://bugs.python.org/issue10395) to add a function that does what commonprefix should have done to start with. Once this function is present I see no need for an is{parent|child} function. Brendan

Oleg Broytman wrote:
Why is that an oops? On my Linux system, I can create a file "C:\\Program Files" which is very different from the path "C:/Program Files/Python" (two directories and a file). Other operating systems may do things differently, but for me, they have no path in common:
If you want to normalise the paths first, normalise them. That's what normpath and normcase are for. The other path manipulation functions, like os.path.split(), don't normalise paths before operating on them. Why should isparent and ischild? -- Steven

On 8 July 2011 00:08, Giampaolo Rodolà <g.rodola@gmail.com> wrote:
Underspecified. Are these simply string operations? If not, how would symlinks be handled? What about case sensitivity (given that detecting case sensitivity per filesystem is not possible, in practical terms)? What about os.sep and os.altsep (\ and / on Windows)? By the time you've answered all of these questions, you may as well code the operations. Then let's see if people use them before putting them into the standard library. If you're only looking at small utility wrappers round os.path.commonprefix, then I don't see the point (such a wrapper is easy enough to write if you need it in your own code). In reality, os.path is a compromise providing "simplistic but good enough" path handling. If I assume you intend these operations also to be "simplistic but good enough", then I see little benefit that I can't get with os.path.commonprefix (and maybe a couple of lines of wrapper, if I use the idiom a lot). Personally, I don't expect I'd ever use something like this. Also, if isparent(x,y) and ischild(y,x) are intended to be equivalent, then I don't see the value in having both (comments about comparison operators notwithstanding). And if there's a subtle difference I've missed, you haven't explained it well enough :-) Having said all this, I support the idea of having a better set of path handling functions in the stdlib. But it's far from a simple problem to do it right in a sufficiently cross-platform way. And just adding functions to os.path probably isn't the right way to start. Paul.

On Thu, Jul 7, 2011 at 8:08 PM, Giampaolo Rodolà <g.rodola@gmail.com> wrote:
See the append of the path separator for the third case later. ischild() would be very similar. Regards, -- . Facundo Blog: http://www.taniquetil.com.ar/plog/ PyAr: http://www.python.org/ar/

On Fri, Jul 08, 2011 at 10:18:15AM -0300, Facundo Batista wrote:
Look at a slightly better implementation shutil.destinsrc. Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

Paul Colomiets <paul@colomiets.name> writes:
I think this behaviour is also part of the expectation:: >>> path = '/a/b/c/d' >>> isparent('/a', path) True >>> isparent('/a/b', path) True >>> isparent('/a/b/z', path) False >>> ischild(path, '/a') True >>> ischild(path, '/a/b') True >>> ischild(path, '/a/b/z') False >>> '/a' == dirname(path) False >>> '/a/b' == dirname(path) False >>> '/a/b/z' == dirname(path) False -- \ “See, in my line of work you gotta keep repeating things over | `\ and over and over again, for the truth to sink in; to kinda | _o__) catapult the propaganda.” —George W. Bush, 2005-05 | Ben Finney

On Thu, Jul 14, 2011 at 05:51:49AM -0400, Eric V. Smith wrote:
Then isparent() seems like a bad name. isancestor(), maybe? Not that I think it needs to be added to the stdlib.
It's already in the stdlib, called shutil.destinsrc ("destination in source"). Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

Oleg Broytman <phd@phdru.name> writes:
It's already in the stdlib, called shutil.destinsrc ("destination in source").
Not according to <URL:http://docs.python.org/library/shutil.html> nor <URL:http://docs.python.org/py3k/library/shutil.html>; no mention of a ‘destinsrc’. Which documentation should we be looking at to find that? -- \ “The best is the enemy of the good.” —Voltaire, _Dictionnaire | `\ Philosophique_ | _o__) | Ben Finney

On Thu, Jul 14, 2011 at 08:45:06PM +1000, Ben Finney wrote:
In py3k it was renamed to _destinsrc. It never was documented. So to "add" it to the stdlib just rename it back and document it. Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

Oleg Broytman <phd@phdru.name> writes:
In py3k it was renamed to _destinsrc. It never was documented.
Both of which strongly indicate the intent that it shouldn't be used as part of the library API. So it is disingenuous to suggest that it's already in the standard library; it's nice that there's an implementation there, but it's clearly being moved further from intended use. Who made that change? Presumably their opinion on this matter is opposite to the proponents of the functionality in this thread. Can someone ask them to comment in this thread as to their rationale? -- \ “Beware of bugs in the above code; I have only proved it | `\ correct, not tried it.” —Donald Knuth, 1977-03-29 | _o__) | Ben Finney

On 14 July 2011 14:10, Ben Finney <ben+python@benfinney.id.au> wrote:
It's easy to find out who made the change: http://hg.python.org/cpython/rev/0ab36796dd79 -- Arnaud

Arnaud Delobelle <arnodel@gmail.com> writes:
I'm glad you found it easy, and thank you for doing so.
Made by Benjamin Peterson on 2009-02-07, with the commit message “make destinsrc private”. Benjamin, what was the rationale for making ‘shutil.destinsrc’ no longer part of the public API? I'm asking in the context of a thread that suggests adding that exact functionality to the standard library, before we were aware of this code being there. -- \ “I am too firm in my consciousness of the marvelous to be ever | `\ fascinated by the mere supernatural …” —Joseph Conrad, _The | _o__) Shadow-Line_ | Ben Finney

Ben Finney <ben+python@...> writes:
Benjamin, what was the rationale for making ‘shutil.destinsrc’ no longer part of the public API?
Please see http://bugs.python.org/issue2047

Benjamin Peterson <benjamin@python.org> writes:
Thank you. (Has the Python development team considered a policy of noting bug report URLs in the commits that address those bug reports? That would have made the forensic work easier.) So AFAICT the strongest justification for the change has its origin in <URL:http://bugs.python.org/issue2047#msg63157> by Raghuram Devarakonda: destinsrc() is an internal function used only in shutil.move(). But I don't see an argument made against Joseph Armbruster's suggestion <URL:http://bugs.python.org/issue2047#msg63156>: I would have expected to find a function like this in os.path, not shutil. -- \ “Come on Milhouse, there’s no such thing as a soul! It’s just | `\ something they made up to scare kids, like the Boogie Man or | _o__) Michael Jackson.” —Bart, _The Simpsons_ | Ben Finney

On 7/14/2011 6:59 PM, Ben Finney wrote:
This is now standard. If 'issue #xxxx' appears in the commit message, a message reporting the commit is auto-generated and sent to the tracker. Since this saves developer effort, it usually is done. -- Terry Jan Reedy

Ben Finney <ben+python@...> writes:
They generally do when they remember. :)
Sounds more like an observation than a suggestion. I personally don't care whether/where this functionality is exposed, so by all means file an issue if you want.
participants (16)
-
Andrew Bennetts
-
Arnaud Delobelle
-
Ben Finney
-
Benjamin Peterson
-
Brendan Moloney
-
Chris Rebert
-
Eric V. Smith
-
Facundo Batista
-
Giampaolo Rodolà
-
Greg Ewing
-
John O'Connor
-
Oleg Broytman
-
Paul Colomiets
-
Paul Moore
-
Steven D'Aprano
-
Terry Reedy