Skip to content

gh-139580: Clarify pathlib full_match recursive pattern docs - #151479

Merged
terryjreedy merged 4 commits into
python:mainfrom
harjothkhara:codex/gh-139580-pathlib-full-match-docs
Oct 20, 2026
Merged

terryjreedy merged 4 commits into
python:mainfrom
harjothkhara:codex/gh-139580-pathlib-full-match-docs

Conversation

@harjothkhara

@harjothkhara harjothkhara commented Jun 14, 2026 •

Copy link
Copy Markdown
Contributor

Documents how PurePath.full_match() handles a pattern ending in /**: /a/** matches /a/b but not /a, because the separator before ** must be present in the path and PurePath drops trailing slashes. Adds two doctest examples under full_match() and a note at the ** entry of the pattern language list contrasting it with Path.glob().

Docs-only; matches existing behavior.

Disclosure: AI-assisted wording; reviewed by me.

@read-the-docs-community

read-the-docs-community Bot commented Jun 14, 2026 •

Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #33135752 | 📁 Comparing 303854b against main (a700732)

  🔍 Preview build  

1 file changed
± library/pathlib.html

@harjothkhara
harjothkhara force-pushed the codex/gh-139580-pathlib-full-match-docs branch from 753a0d3 to 54f4826 Compare June 14, 2026 19:11
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@harjothkhara
harjothkhara force-pushed the codex/gh-139580-pathlib-full-match-docs branch from 54f4826 to 303854b Compare June 14, 2026 19:18
@harjothkhara
harjothkhara marked this pull request as ready for review June 14, 2026 19:18
@harjothkhara
harjothkhara requested a review from barneygale as a code owner June 14, 2026 19:18
@harjothkhara

Copy link
Copy Markdown
Contributor Author

@barneygale this is the docs clarification you suggested on gh-139580 — it adds a worked full_match('/a/**') example and a note on trailing-slash normalization, following your explanation on the issue. Would you mind reviewing?

@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown

This PR is stale because it has been open for 90 days with no activity.

@github-actions github-actions Bot added the stale Stale PR or inactive for long period of time. label Oct 5, 2026
@terryjreedy
terryjreedy requested a review from picnixz October 15, 2026 02:26
@terryjreedy

terryjreedy commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

@picnixz On a previous issue, you said "I don't know how the docs could be improved though." This PR attempts an improvement. Merge? Modify (condense) and merge? I verified the new examples. The prose looks fine; maybe longer than needed, but I don't know what to cut. I do understand the 0-1 segment confusion and agree that it should be explained.

@macmarrum You posted the confusion this PR tries to solve. What do you think?

PS 'macmar', if you get a ping, my mistake for clicking too soon.

Comment thread Doc/library/pathlib.rst Outdated
Comment thread Doc/library/pathlib.rst Outdated
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@harjothkhara

Copy link
Copy Markdown
Contributor Author

Thanks for the review. I have reworded the note at the ** entry so the difference is visible there: PurePath('a').full_match('a/**') is False, while Path.glob('a/**') yields a. I did not use "one or more", because ** still matches zero segments elsewhere in full_match(): PurePath('a/b').full_match('a/**/b') and PurePath('a.py').full_match('**/*.py') are both True. Only a trailing /** differs. I have also shortened the paragraph under full_match(), as Terry suggested.

@macmarrum

Copy link
Copy Markdown

Looks good 👍

Comment thread Doc/library/pathlib.rst Outdated
Comment thread Doc/library/pathlib.rst Outdated
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@harjothkhara

Copy link
Copy Markdown
Contributor Author

Applied both suggestions in 6e95bef. Thanks picnixz and macmarrum.

@picnixz picnixz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unfortunate that this behavior is like that but we can't change the implementation so I think this is the best we can do.

@terryjreedy Do you think it's good enough for nonfamiliar people?

@github-actions github-actions Bot removed the stale Stale PR or inactive for long period of time. label Oct 17, 2026
Comment thread Doc/library/pathlib.rst Outdated
Comment on lines +578 to +586
A pattern ending in "``/**``" needs the separator before it to be present
in the path, even though "``**``" can match zero segments. For instance,
"``/a/**``" matches "``/a/b``" but not "``/a``", and since :class:`PurePath`
drops trailing slashes, it does not match "``/a/``" either::

>>> PurePath('/a/b').full_match('/a/**')
True
>>> PurePath('/a').full_match('/a/**')
False

@terryjreedy terryjreedy Oct 20, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block of text and example discusses how a specific type of full-match pattern (a path pattern passed to full_ match) acts in a way people might not expect. With the last two examples reversed as requested in my other comment, this block immediately follows a normal use of the example '/a/**' of this type: PurePath('/a/b/c.py').full_match('/a/**').
I think the "/a/b" example is redundant with "/a/a/c.py" and distracting. On the other hand, I think we need an introductory 'bridge' sentence. I suggest simplifying the text to ...

Suggested change
A pattern ending in "``/**``" needs the separator before it to be present
in the path, even though "``**``" can match zero segments. For instance,
"``/a/**``" matches "``/a/b``" but not "``/a``", and since :class:`PurePath`
drops trailing slashes, it does not match "``/a/``" either::
>>> PurePath('/a/b').full_match('/a/**')
True
>>> PurePath('/a').full_match('/a/**')
False
Patterns ending in "``/**``", as in the example above, may surprise when passed to ``full_match``.
Even though "``**``" can match 0 segments, "``.../**``" requires a separator to match.
Hence "``/a/**``" does not match path "``/a``". Since :class:`PurePath` drops trailing slashes,
this pattern also does not match "``/a/``".
>>> PurePath('/a').full_match('/a/**')
False
>>> PurePath('/a/').full_match('/a/**')
False

With the previous examples switched, I would be happy with this.

@terryjreedy

Copy link
Copy Markdown
Member

@macmarrum Thank you for adding your review and approvals. With 3 people in agreement, I am starting my re-review with the current text.

@harjothkhara Please reverse the two examples on lines 573-6, so they read

      >>> PurePath('/a/b/c.py').full_match('**/*.py')
      True
      >>> PurePath('/a/b/c.py').full_match('/a/**')
      True

Not only is this more logical (to me), it puts the trailing /** example we further explicate directly above our new explanation.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@harjothkhara

Copy link
Copy Markdown
Contributor Author

Done in c622943, thanks Terry.

@terryjreedy terryjreedy added needs backport to 3.14 bugs and security fixes needs backport to 3.15 bugs and security fixes labels Oct 20, 2026
@terryjreedy
terryjreedy merged commit 2648604 into python:main Oct 20, 2026
34 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in Docs PRs Oct 20, 2026
@miss-islington-app

Copy link
Copy Markdown

Thanks @harjothkhara for the PR, and @terryjreedy for merging it 🌮🎉.. I'm working now to backport this PR to: 3.14, 3.15.
🐍🍒⛏🤖

@bedevere-app

bedevere-app Bot commented Oct 20, 2026

Copy link
Copy Markdown

GH-159955 is a backport of this pull request to the 3.15 branch.

@bedevere-app bedevere-app Bot removed the needs backport to 3.15 bugs and security fixes label Oct 20, 2026
@bedevere-app

bedevere-app Bot commented Oct 20, 2026

Copy link
Copy Markdown

GH-159956 is a backport of this pull request to the 3.14 branch.

@bedevere-app bedevere-app Bot removed the needs backport to 3.14 bugs and security fixes label Oct 20, 2026
terryjreedy added a commit that referenced this pull request Oct 20, 2026
…H-151479) (#159955)

gh-139580: Clarify pathlib full_match recursive pattern docs (GH-151479)

Documents how PurePath.full_match() handles a pattern ending in /**: /a/** matches /a/b but not /a, because the separator before ** must be present in the path and PurePath drops trailing slashes. Adds two doctest examples under full_match() and a note at the ** entry of the pattern language list contrasting it with Path.glob().
---------
(cherry picked from commit 2648604)

Co-authored-by: Harjoth Khara <harjoth.khara@gmail.com>
Co-authored-by: Terry J Reedy <tjreedy@udel.edu>
terryjreedy added a commit that referenced this pull request Oct 20, 2026
…H-151479) (#159956)

gh-139580: Clarify pathlib full_match recursive pattern docs (GH-151479)

Documents how PurePath.full_match() handles a pattern ending in /**: /a/** matches /a/b but not /a, because the separator before ** must be present in the path and PurePath drops trailing slashes. Adds two doctest examples under full_match() and a note at the ** entry of the pattern language list contrasting it with Path.glob().
---------
(cherry picked from commit 2648604)

Co-authored-by: Harjoth Khara <harjoth.khara@gmail.com>
Co-authored-by: Terry J Reedy <tjreedy@udel.edu>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation in the Doc dir skip news

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants