Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-104484: Add parameter @case_sensitive to pathlib.PurePath.match() function #104565

Merged
merged 11 commits into from
May 18, 2023
10 changes: 9 additions & 1 deletion Doc/library/pathlib.rst
Original file line number Diff line number Diff line change
@@ -546,7 +546,7 @@ Pure paths provide the following methods and properties:
PureWindowsPath('c:/Program Files')


.. method:: PurePath.match(pattern)
.. method:: PurePath.match(pattern, *, case_sensitive=None)

Match this path against the provided glob-style pattern. Return ``True``
if matching is successful, ``False`` otherwise.
@@ -576,6 +576,14 @@ Pure paths provide the following methods and properties:
>>> PureWindowsPath('b.py').match('*.PY')
True

By default, or when the *case_sensitive* keyword-only argument is set to
thirumurugan-git marked this conversation as resolved.
Show resolved Hide resolved
``None``, this method matches paths using platform-specific casing rules:
typically, case-sensitive on POSIX, and case-insensitive on Windows.
Set *case_sensitive* to ``True`` or ``False`` to override this behaviour.
thirumurugan-git marked this conversation as resolved.
Show resolved Hide resolved

.. versionadded:: 3.12
The *case_sensitive* argument.


.. method:: PurePath.relative_to(other, walk_up=False)

18 changes: 14 additions & 4 deletions Lib/pathlib.py
Original file line number Diff line number Diff line change
@@ -86,6 +86,12 @@ def _make_selector(pattern_parts, flavour, case_sensitive):
return cls(pat, child_parts, flavour, case_sensitive)


@functools.lru_cache(maxsize=256, typed=True)
thirumurugan-git marked this conversation as resolved.
Show resolved Hide resolved
def _compile_pattern(pat, flags):
re_pat = fnmatch.translate(pat)
thirumurugan-git marked this conversation as resolved.
Show resolved Hide resolved
return re.compile(re_pat, flags).match


class _Selector:
"""A selector matches a specific glob pattern part against the children
of a given path."""
@@ -680,22 +686,26 @@ def is_reserved(self):
name = self._tail[-1].partition('.')[0].partition(':')[0].rstrip(' ')
return name.upper() in _WIN_RESERVED_NAMES

def match(self, path_pattern):
def match(self, path_pattern, *, case_sensitive=None):
"""
Return True if this path matches the given pattern.
"""
if case_sensitive is None:
case_sensitive = _is_case_sensitive(self._flavour)
flags = re.NOFLAG if case_sensitive else re.IGNORECASE
thirumurugan-git marked this conversation as resolved.
Show resolved Hide resolved
pat = self.with_segments(path_pattern)
if not pat.parts:
raise ValueError("empty pattern")
pat_parts = pat._parts_normcase
parts = self._parts_normcase
pat_parts = pat.parts
parts = self.parts
if pat.drive or pat.root:
if len(pat_parts) != len(parts):
return False
elif len(pat_parts) > len(parts):
return False
for part, pat in zip(reversed(parts), reversed(pat_parts)):
if not fnmatch.fnmatchcase(part, pat):
match = _compile_pattern(pat, flags)
if not match(part):
return False
return True

5 changes: 5 additions & 0 deletions Lib/test/test_pathlib.py
Original file line number Diff line number Diff line change
@@ -312,6 +312,11 @@ def test_match_common(self):
# Multi-part glob-style pattern.
self.assertFalse(P('/a/b/c.py').match('/**/*.py'))
self.assertTrue(P('/a/b/c.py').match('/a/**/*.py'))
# Case-sensitive flag
self.assertFalse(P('A.py').match('a.PY', case_sensitive=True))
self.assertTrue(P('A.py').match('a.PY', case_sensitive=False))
self.assertFalse(P('c:/a/B.Py').match('C:/A/*.pY', case_sensitive=True))
self.assertTrue(P('/a/b/c.py').match('/A/*/*.Py', case_sensitive=False))
thirumurugan-git marked this conversation as resolved.
Show resolved Hide resolved

def test_ordering_common(self):
# Ordering is tuple-alike.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added case_sensitive argument to pathlib.PurePath.match()
thirumurugan-git marked this conversation as resolved.
Show resolved Hide resolved