You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
os.path.realpath (and possibly others) ignore the special POSIX-meaning of absolute pathnames that start with exactly two /? #138139
POSIX defines that absolute pathnames that start with exactly (and only) two / are special:
If a pathname begins with two successive characters, the first component following the leading characters may be interpreted in an implementation-defined manner, although more than two leading characters shall be treated as a single character.
That is /foo, ///foo, ////foo, etc. are (normalised) all the same as /foo, but //foo is not necessarily (it's implementation-defined whether or not, so it actually may be and e.g. Linux indeed seems to consider it also the same, though I haven't verified whether it really is in all cases).
At least os.path.realpath seems to ignore that however:
I'm kinda tempted to say that os.path.realpath("//foo") should yield //foo.
Now to me, POSIX is not 100% clear (one should perhaps ask for confirmation at the Austin Group before making any incompatible changes):
I, personally, would interpret the above wording of the standard, that //foo/bar/baz merely indicates that foo (and foo alone) is special (e.g. like what we know from Windows with \\hostname\path) but any further components are not.
This could(would) in turn man that normalisation of any later components does happen as usual, and thus e.g. //foo/bar//baz should be normalised to //foo/bar/baz.
The leading // need of course be retained to indicate that foo is still special.
There is of course some "risk" in changing the current behaviour.
One could e.g. simply make it platform dependent, and e.g. on Linux leave things as is, and only change it for platforms (if any exist) that truly handle //foo special. One should do so only, if e.g. the POSIX/C realpath() would do so, too (on that platform).
But even then, other parts of Python do already handle // special... so in order to keep things homogeneous and compatible, one should perhaps anyway adapt os.path.realpath (and possibly others like .normpath().
AFAICT, the meaning of // is implementation-defined. So we can interpret it however we want it.
I don't think so. Implementation-defined here means obviously what the OS does, not what the Python implementation chooses.
I'm not necessarily saying that // definitely needs to be handled specially... but:
whatever is done should be properly documented
it should be homogeneous in the Python standard library (which means if we "ignore" // here, pathlib.Path should do so, too.
ideally the API would be so that it could be extended to support a special //. Consider e.g. a parameter like treat_dobule_leading_slahs_special=False, but of course, adding such to any function that takes a pathname would be ugly
One user (Cygwin in this case) is not sufficient, especially if this specific user is not the largest one (and not officially supported by PEP-11). Practicality beats purity in this case IMO.
it should be homogeneous in the Python standard library (which means if we "ignore" // here, pathlib.Path should do so, too.
cc @barneygale for this; I think pathlib here makes the choice of not choosing something, to let downstream users implement the behavior they want, while os makes a choice (and can do so). So I'm not entirely sure it should really by that homogeneous.
I would at least argue, that if either of the "two sides" would change to match the other (and there'd be anyway some backwards compatibility issues, then one should probably do it the right way.
The problem with inhomogeneity is IMO that it could easily lead to problems (in the use case that I have myself, it would likely even be a security issue):
Imagine you get a noramlised or realpathed path from two different sources and want to check whether they're equal or not.
If now one source returns the // while the other returns the folded /, the program could wrongly assume the paths to be different.
That's a similar kind of hole like the ones that lead to directory traversal.
Activity
brianschubert commentedon Aug 25, 2025
Possibly duplicate of #117201?
picnixz commentedon Aug 25, 2025
//is implementation-defined. So we can interpret it however we want it.The Linux behavior endowed by major distributions, both glibc and coreutils, should be preferred, namely
realpath("//tmp") == "/tmp".Relevant comments: #117201 (comment) and following.
calestyo commentedon Aug 25, 2025
I don't think so. Implementation-defined here means obviously what the OS does, not what the Python implementation chooses.
I'm not necessarily saying that
//definitely needs to be handled specially... but://here,pathlib.Pathshould do so, too.//. Consider e.g. a parameter liketreat_dobule_leading_slahs_special=False, but of course, adding such to any function that takes a pathname would be uglycalestyo commentedon Aug 25, 2025
The follow-up comment shows already that there is probably in fact a user of special
//.picnixz commentedon Aug 25, 2025
One user (Cygwin in this case) is not sufficient, especially if this specific user is not the largest one (and not officially supported by PEP-11). Practicality beats purity in this case IMO.
picnixz commentedon Aug 25, 2025
That I can agree with.
cc @barneygale for this; I think pathlib here makes the choice of not choosing something, to let downstream users implement the behavior they want, while
osmakes a choice (and can do so). So I'm not entirely sure it should really by that homogeneous.calestyo commentedon Aug 25, 2025
I would at least argue, that if either of the "two sides" would change to match the other (and there'd be anyway some backwards compatibility issues, then one should probably do it the right way.
The problem with inhomogeneity is IMO that it could easily lead to problems (in the use case that I have myself, it would likely even be a security issue):
Imagine you get a noramlised or
realpathed path from two different sources and want to check whether they're equal or not.If now one source returns the
//while the other returns the folded/, the program could wrongly assume the paths to be different.That's a similar kind of hole like the ones that lead to directory traversal.