Skip to content

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

Open
harjothkhara wants to merge 3 commits into
python:mainfrom
harjothkhara:codex/gh-139580-pathlib-full-match-docs
Open

harjothkhara wants to merge 3 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

``**`` (entire segment)
Matches any number of file or directory segments, including zero.
Matches any number of file or directory segments, including zero. Note that

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

When I imagine I don't know anything about the issue, reading the docs I'd first want to know what ** means when I use it, and only later the reason for the different interpretations.

Suggested change
Matches any number of file or directory segments, including zero. Note that
In :meth:`~Path.glob` and :meth:`~Path.rglob`, matches any number of file or
directory segments, including zero.
In :meth:`~PurePath.full_match`, matches one or more such segments. See that
method's documentation for examples and the reasoning behind its different
interpretation.

Comment thread Doc/library/pathlib.rst Outdated
Comment on lines +578 to +584
A pattern ending with "``/**``" matches any path that begins with the
pattern's prefix followed by a separator. For example "``/a/**``" matches
"``/a/b``" and "``/a/b/c``", but not "``/a``", because "``/a``" does not
begin with "``/a/``". The recursive wildcard "``**``" can match zero
segments, but the separator before it must still be present in the path,
and :class:`PurePath` objects do not preserve trailing slashes (so
"``/a/``" is normalized to "``/a``")::

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Here's my take on it. I'm not sure about the formatting, though.

Suggested change
A pattern ending with "``/**``" matches any path that begins with the
pattern's prefix followed by a separator. For example "``/a/**``" matches
"``/a/b``" and "``/a/b/c``", but not "``/a``", because "``/a``" does not
begin with "``/a/``". The recursive wildcard "``**``" can match zero
segments, but the separator before it must still be present in the path,
and :class:`PurePath` objects do not preserve trailing slashes (so
"``/a/``" is normalized to "``/a``")::
Note that in :meth:`~Path.glob` and :meth:`~Path.rglob`, "``**``" matches zero
or more segments, whereas in :meth:`~PurePath.full_match` it matches one or
more. Although "``**``" can match zero segments, the internal logic, to
recognize a segment, requires a trailing separator, but :class:`PurePath`
objects do not preserve them (so "``/a/``" is normalized to "``/a``")::

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 on lines +578 to +581
A pattern ending in "``/**``" needs the separator before it to be present
in the path, even though "``**``" can match zero segments. So "``/a/**``"
matches "``/a/b``" but not "``/a``", and :class:`PurePath` drops trailing
slashes, so it does not match "``/a/``" either::

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.

Suggested change
A pattern ending in "``/**``" needs the separator before it to be present
in the path, even though "``**``" can match zero segments. So "``/a/**``"
matches "``/a/b``" but not "``/a``", and :class:`PurePath` drops trailing
slashes, so it does not match "``/a/``" either::
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::

Comment thread Doc/library/pathlib.rst Outdated
Comment on lines +1808 to +1810
Matches any number of file or directory segments, including zero. But in
:meth:`~PurePath.full_match`, "``a/**``" does not match "``a``", although
:meth:`~Path.glob` yields "``a``" for that pattern.

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.

Suggested change
Matches any number of file or directory segments, including zero. But in
:meth:`~PurePath.full_match`, "``a/**``" does not match "``a``", although
:meth:`~Path.glob` yields "``a``" for that pattern.
Matches any number of file or directory segments, including zero.
Note that in :meth:`~PurePath.full_match`, "``a/**``" does not match
"``a``", whereas :meth:`~Path.glob` yields "``a``" for that pattern.

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting merge docs Documentation in the Doc dir skip news stale Stale PR or inactive for long period of time.

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

4 participants