summaryrefslogtreecommitdiffstats
path: root/Lib/fnmatch.py
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2020-05-12 02:19:20 (GMT)
committerGitHub <noreply@github.com>2020-05-12 02:19:20 (GMT)
commitb1b4c790e7d3b5f4244450aefe3d8f01710c13f7 (patch)
treed0f03bf47219bdec01e64b56aed96df96ab427b1 /Lib/fnmatch.py
parentd0919f0d6bb757b6bcfd7b2e15656d318c9d5cd9 (diff)
downloadcpython-b1b4c790e7d3b5f4244450aefe3d8f01710c13f7.zip
cpython-b1b4c790e7d3b5f4244450aefe3d8f01710c13f7.tar.gz
cpython-b1b4c790e7d3b5f4244450aefe3d8f01710c13f7.tar.bz2
bpo-40480: restore ability to join fnmatch.translate() results (GH-20049)
In translate(), generate unique group names across calls. The restores the undocumented ability to get a valid regexp by joining multiple translate() results via `|`.
Diffstat (limited to 'Lib/fnmatch.py')
-rw-r--r--Lib/fnmatch.py17
1 files changed, 13 insertions, 4 deletions
diff --git a/Lib/fnmatch.py b/Lib/fnmatch.py
index d7d915d..0eb1802 100644
--- a/Lib/fnmatch.py
+++ b/Lib/fnmatch.py
@@ -16,6 +16,12 @@ import functools
__all__ = ["filter", "fnmatch", "fnmatchcase", "translate"]
+# Build a thread-safe incrementing counter to help create unique regexp group
+# names across calls.
+from itertools import count
+_nextgroupnum = count().__next__
+del count
+
def fnmatch(name, pat):
"""Test whether FILENAME matches PATTERN.
@@ -148,9 +154,12 @@ def translate(pat):
# in a lookahead assertion, save the matched part in a group, then
# consume that group via a backreference. If the overall match fails,
# the lookahead assertion won't try alternatives. So the translation is:
- # (?=(P<name>.*?fixed))(?P=name)
- # Group names are created as needed: g1, g2, g3, ...
- groupnum = 0
+ # (?=(?P<name>.*?fixed))(?P=name)
+ # Group names are created as needed: g0, g1, g2, ...
+ # The numbers are obtained from _nextgroupnum() to ensure they're unique
+ # across calls and across threads. This is because people rely on the
+ # undocumented ability to join multiple translate() results together via
+ # "|" to build large regexps matching "one of many" shell patterns.
while i < n:
assert inp[i] is STAR
i += 1
@@ -167,7 +176,7 @@ def translate(pat):
add(".*")
add(fixed)
else:
- groupnum += 1
+ groupnum = _nextgroupnum()
add(f"(?=(?P<g{groupnum}>.*?{fixed}))(?P=g{groupnum})")
assert i == n
res = "".join(res)