mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
[3.12] GH-106330: Fix matching of empty path in pathlib.PurePath.match()
(GH-106331) (GH-106372)
We match paths using the `_lines` attribute, which is derived from the
path's string representation. The bug arises because an empty path's string
representation is `'.'` (not `''`), which is matched by the `'*'` wildcard.
(cherry picked from commit b4efdf8cda
)
This commit is contained in:
parent
930df7b07e
commit
d5ed72b696
3 changed files with 25 additions and 8 deletions
|
@ -127,12 +127,19 @@ def _compile_pattern_lines(pattern_lines, case_sensitive):
|
|||
# Match the start of the path, or just after a path separator
|
||||
parts = ['^']
|
||||
for part in pattern_lines.splitlines(keepends=True):
|
||||
# We slice off the common prefix and suffix added by translate() to
|
||||
# ensure that re.DOTALL is not set, and the end of the string not
|
||||
# matched, respectively. With DOTALL not set, '*' wildcards will not
|
||||
# match path separators, because the '.' characters in the pattern
|
||||
# will not match newlines.
|
||||
parts.append(fnmatch.translate(part)[_FNMATCH_SLICE])
|
||||
if part == '*\n':
|
||||
part = r'.+\n'
|
||||
elif part == '*':
|
||||
part = r'.+'
|
||||
else:
|
||||
# Any other component: pass to fnmatch.translate(). We slice off
|
||||
# the common prefix and suffix added by translate() to ensure that
|
||||
# re.DOTALL is not set, and the end of the string not matched,
|
||||
# respectively. With DOTALL not set, '*' wildcards will not match
|
||||
# path separators, because the '.' characters in the pattern will
|
||||
# not match newlines.
|
||||
part = fnmatch.translate(part)[_FNMATCH_SLICE]
|
||||
parts.append(part)
|
||||
# Match the end of the path, always.
|
||||
parts.append(r'\Z')
|
||||
flags = re.MULTILINE
|
||||
|
@ -501,8 +508,12 @@ class PurePath(object):
|
|||
try:
|
||||
return self._lines_cached
|
||||
except AttributeError:
|
||||
trans = _SWAP_SEP_AND_NEWLINE[self._flavour.sep]
|
||||
self._lines_cached = str(self).translate(trans)
|
||||
path_str = str(self)
|
||||
if path_str == '.':
|
||||
self._lines_cached = ''
|
||||
else:
|
||||
trans = _SWAP_SEP_AND_NEWLINE[self._flavour.sep]
|
||||
self._lines_cached = path_str.translate(trans)
|
||||
return self._lines_cached
|
||||
|
||||
def __eq__(self, other):
|
||||
|
|
|
@ -317,6 +317,10 @@ class _BasePurePathTest(object):
|
|||
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))
|
||||
# Matching against empty path
|
||||
self.assertFalse(P().match('*'))
|
||||
self.assertTrue(P().match('**'))
|
||||
self.assertFalse(P().match('**/*'))
|
||||
|
||||
def test_ordering_common(self):
|
||||
# Ordering is tuple-alike.
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Fix incorrect matching of empty paths in :meth:`pathlib.PurePath.match`.
|
||||
This bug was introduced in Python 3.12.0 beta 1.
|
Loading…
Add table
Add a link
Reference in a new issue