Uh oh!
There was an error while loading. Please reload this page.
GH-77609: Add follow_symlinks argument to pathlib.Path.glob() - #102616
Conversation
Add a keyword-only *follow_symlinks* parameter to `pathlib.Path.glob()` and `rglob()`, defaulting to false. When set to true, symlinks to directories are followed as if they were directories. Previously these methods followed symlinks except when evaluating "`**`" wildcards; on Windows they returned paths in filesystem casing except when evaluating non-wildcard tokens. Both these problems are solved here. This will allow us to address pythonGH-102613 and pythonGH-81079 in future commits.
Table showing whether symlinks to directories are followed:
Table showing whether filesystem case is returned:
|
zooba
commented
Mar 14, 2023
I wrote a fairly long post about my concerns on the changed behaviour, but then I realised that my main question is whether the symlink following changes applies to the entire path or only the bit in pattern? If symlinks in the base path are going to be followed regardless of the option, I'm far less concerned. However, I'd like to be able to figure this out from the documentation :) So there's a change required there to clarify (and maybe I'll be more concerned if it clarifies the wrong way) |
barneygale
commented
Mar 14, 2023
Symlinks in the base path (the p in |
barneygale
commented
Mar 14, 2023
Thanks for the feedback btw! I'm also nervous about changing behaviour. I could revise this to make |
zooba
commented
Mar 14, 2023
I don't want to add I think the behaviour of path parts before any wildcard are easily assumed to be equivalent of being part of the base path. That is: Everything from the first wildcard becomes a match pattern. We need to recurse deep enough to create paths with the same number of segments, and then match all the candidates against the pattern. Since we're now recursing, choosing not to follow symlinks by default is justifiable. Given the current behaviour is to follow I'm pretty much leaning towards needing a deprecation period though. I think that'll be safest, and probably necessary, so the best way to do that is to support |
barneygale
commented
Mar 14, 2023
Right! I think I agree that leading literals should always be followed. What about trailing literals, e.g. ... but that optimization only works if the |
barneygale
commented
Mar 14, 2023
Also agree on the need to preserve existing behaviour and emit deprecation warnings before we change defaults. I'd argue the default should become true, not false, in future. It's the more useful behaviour. |
barneygale
commented
Mar 14, 2023
I've switched the default to Passing
I mention this only because the names "glob" and "rglob" are a bit opaque unless you've done shell scripting before. The suggested names align with |
zooba
commented
Mar 14, 2023
Passing
Yeah, and so if we have Maybe we can optimise the case where the |
👍 sounds good. As things stand with this PR, This PR still breaks backwards compat in two (minor?) ways:
|
zooba
commented
Mar 14, 2023
Matching filesystem case is an improvement, IMHO, even for back-compat. On the I also don't have any real feeling for whether we should |
Pathlib uniformly avoids collapsing I've fixed handling of An updated table showing whether symlinks are followed:
Note that, for the moment, literals are handled exactly the same whether they appear before or after recursive wildcards. |
zooba
commented
Mar 14, 2023
Looks good. We should still add the deprecation warning for |
Done. But honestly I don't feel great about |
barneygale
commented
Mar 14, 2023
Oh right, I also need to update the docs examples to pass |
barneygale
commented
May 4, 2023
Alternative PR that adds support for a |
barneygale
commented
May 8, 2023
Closing this PR as I believe #104176 is the right way forward. |
barneygale
commented
May 10, 2023
@zooba I'd be much more comfortable with this PR if we delayed deprecating |
zooba
commented
May 10, 2023
We can document it as deprecated with no planned removal date (or planned change of default, in this case). Or just strongly recommend the use of If we think (or people start saying) that the default is harmful/a trap, we can deprecate properly at that point (and wait two releases before changing it). |
barneygale
commented
May 17, 2023
I'll pick this up again once #104512 lands. |
barneygale
commented
May 23, 2023
In fact, it doesn't really matter whether #104512 lands first. Marking as ready for review! |
barneygale
commented
May 23, 2023
On |
Interesting. I think if you can clearly explain the different behaviour ("following symlinks matched by |
barneygale
commented
May 29, 2023
I think we're in agreement, then! The docs in this PR say: By default, or when the *follow_symlinks* keyword-only argument is set to
``None``, this method follows symlinks except when expanding "``**``"
wildcards. Set *follow_symlinks* to ``True`` to always follow symlinks, or
``False`` to treat all symlinks as files.Does that sound OK to you? |
zooba
commented
May 29, 2023
Sounds good to me |
barneygale
commented
May 29, 2023
Mega, thank you. Would you be up for reviewing the PR as a whole, if you have the time? No worries if not, and no urgency from my side. The patch is somewhat repetitive due to the way globbing is currently implemented. If you find it offensive, we might want to simplify things first via #104512 |
barneygale
commented
May 29, 2023
Woot! Thank you Steve! |
Add a keyword-only follow_symlinks parameter to
pathlib.Path.glob()andrglob().When follow_symlinks is
None(the default), these methods follow symlinks except when evaluating "**" wildcards. When set to true or false, symlinks are always or never followed, respectively.This allows us to address GH-102613 in future.