diff options
author | Tim Peters <tim.peters@gmail.com> | 2020-05-12 02:19:20 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-12 02:19:20 (GMT) |
commit | b1b4c790e7d3b5f4244450aefe3d8f01710c13f7 (patch) | |
tree | d0f03bf47219bdec01e64b56aed96df96ab427b1 /Lib/fnmatch.py | |
parent | d0919f0d6bb757b6bcfd7b2e15656d318c9d5cd9 (diff) | |
download | cpython-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.py | 17 |
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) |