1 import itertools
2 import operator
3 import re
4
5
6 # By default, don't filter tests
7 _test_matchers = ()
8 _test_patterns = ()
9
10
11 def match_test(test):
12 # Function used by support.run_unittest() and regrtest --list-cases
13 result = False
14 for matcher, result in reversed(_test_matchers):
15 if matcher(test.id()):
16 return result
17 return not result
18
19
20 def _is_full_match_test(pattern):
21 # If a pattern contains at least one dot, it's considered
22 # as a full test identifier.
23 # Example: 'test.test_os.FileTests.test_access'.
24 #
25 # ignore patterns which contain fnmatch patterns: '*', '?', '[...]'
26 # or '[!...]'. For example, ignore 'test_access*'.
27 return ('.' in pattern) and (not re.search(r'[?*\[\]]', pattern))
28
29
30 def set_match_tests(patterns):
31 global _test_matchers, _test_patterns
32
33 if not patterns:
34 _test_matchers = ()
35 _test_patterns = ()
36 else:
37 itemgetter = operator.itemgetter
38 patterns = tuple(patterns)
39 if patterns != _test_patterns:
40 _test_matchers = [
41 (_compile_match_function(map(itemgetter(0), it)), result)
42 for result, it in itertools.groupby(patterns, itemgetter(1))
43 ]
44 _test_patterns = patterns
45
46
47 def _compile_match_function(patterns):
48 patterns = list(patterns)
49
50 if all(map(_is_full_match_test, patterns)):
51 # Simple case: all patterns are full test identifier.
52 # The test.bisect_cmd utility only uses such full test identifiers.
53 return set(patterns).__contains__
54 else:
55 import fnmatch
56 regex = '|'.join(map(fnmatch.translate, patterns))
57 # The search *is* case sensitive on purpose:
58 # don't use flags=re.IGNORECASE
59 regex_match = re.compile(regex).match
60
61 def match_test_regex(test_id, regex_match=regex_match):
62 if regex_match(test_id):
63 # The regex matches the whole identifier, for example
64 # 'test.test_os.FileTests.test_access'.
65 return True
66 else:
67 # Try to match parts of the test identifier.
68 # For example, split 'test.test_os.FileTests.test_access'
69 # into: 'test', 'test_os', 'FileTests' and 'test_access'.
70 return any(map(regex_match, test_id.split(".")))
71
72 return match_test_regex