ยปCore Development>Code coverage>Lib/fnmatch.py

Python code coverage for Lib/fnmatch.py

#countcontent
1n/a"""Filename matching with shell patterns.
2n/a
3n/afnmatch(FILENAME, PATTERN) matches according to the local convention.
4n/afnmatchcase(FILENAME, PATTERN) always takes case in account.
5n/a
6n/aThe functions operate by translating the pattern into a regular
7n/aexpression. They cache the compiled regular expressions for speed.
8n/a
9n/aThe function translate(PATTERN) returns a regular expression
10n/acorresponding to PATTERN. (It does not compile it.)
11n/a"""
12n/aimport os
13n/aimport posixpath
14n/aimport re
15n/aimport functools
16n/a
17n/a__all__ = ["filter", "fnmatch", "fnmatchcase", "translate"]
18n/a
19n/adef fnmatch(name, pat):
20n/a """Test whether FILENAME matches PATTERN.
21n/a
22n/a Patterns are Unix shell style:
23n/a
24n/a * matches everything
25n/a ? matches any single character
26n/a [seq] matches any character in seq
27n/a [!seq] matches any char not in seq
28n/a
29n/a An initial period in FILENAME is not special.
30n/a Both FILENAME and PATTERN are first case-normalized
31n/a if the operating system requires it.
32n/a If you don't want this, use fnmatchcase(FILENAME, PATTERN).
33n/a """
34n/a name = os.path.normcase(name)
35n/a pat = os.path.normcase(pat)
36n/a return fnmatchcase(name, pat)
37n/a
38n/a@functools.lru_cache(maxsize=256, typed=True)
39n/adef _compile_pattern(pat):
40n/a if isinstance(pat, bytes):
41n/a pat_str = str(pat, 'ISO-8859-1')
42n/a res_str = translate(pat_str)
43n/a res = bytes(res_str, 'ISO-8859-1')
44n/a else:
45n/a res = translate(pat)
46n/a return re.compile(res).match
47n/a
48n/adef filter(names, pat):
49n/a """Return the subset of the list NAMES that match PAT."""
50n/a result = []
51n/a pat = os.path.normcase(pat)
52n/a match = _compile_pattern(pat)
53n/a if os.path is posixpath:
54n/a # normcase on posix is NOP. Optimize it away from the loop.
55n/a for name in names:
56n/a if match(name):
57n/a result.append(name)
58n/a else:
59n/a for name in names:
60n/a if match(os.path.normcase(name)):
61n/a result.append(name)
62n/a return result
63n/a
64n/adef fnmatchcase(name, pat):
65n/a """Test whether FILENAME matches PATTERN, including case.
66n/a
67n/a This is a version of fnmatch() which doesn't case-normalize
68n/a its arguments.
69n/a """
70n/a match = _compile_pattern(pat)
71n/a return match(name) is not None
72n/a
73n/a
74n/adef translate(pat):
75n/a """Translate a shell PATTERN to a regular expression.
76n/a
77n/a There is no way to quote meta-characters.
78n/a """
79n/a
80n/a i, n = 0, len(pat)
81n/a res = ''
82n/a while i < n:
83n/a c = pat[i]
84n/a i = i+1
85n/a if c == '*':
86n/a res = res + '.*'
87n/a elif c == '?':
88n/a res = res + '.'
89n/a elif c == '[':
90n/a j = i
91n/a if j < n and pat[j] == '!':
92n/a j = j+1
93n/a if j < n and pat[j] == ']':
94n/a j = j+1
95n/a while j < n and pat[j] != ']':
96n/a j = j+1
97n/a if j >= n:
98n/a res = res + '\\['
99n/a else:
100n/a stuff = pat[i:j].replace('\\','\\\\')
101n/a i = j+1
102n/a if stuff[0] == '!':
103n/a stuff = '^' + stuff[1:]
104n/a elif stuff[0] == '^':
105n/a stuff = '\\' + stuff
106n/a res = '%s[%s]' % (res, stuff)
107n/a else:
108n/a res = res + re.escape(c)
109n/a return r'(?s:%s)\Z' % res