test_fnmatch.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. """Test cases for the fnmatch module."""
  2. import unittest
  3. import os
  4. import string
  5. import warnings
  6. from fnmatch import fnmatch, fnmatchcase, translate, filter
  7. class FnmatchTestCase(unittest.TestCase):
  8. def check_match(self, filename, pattern, should_match=True, fn=fnmatch):
  9. if should_match:
  10. self.assertTrue(fn(filename, pattern),
  11. "expected %r to match pattern %r"
  12. % (filename, pattern))
  13. else:
  14. self.assertFalse(fn(filename, pattern),
  15. "expected %r not to match pattern %r"
  16. % (filename, pattern))
  17. def test_fnmatch(self):
  18. check = self.check_match
  19. check('abc', 'abc')
  20. check('abc', '?*?')
  21. check('abc', '???*')
  22. check('abc', '*???')
  23. check('abc', '???')
  24. check('abc', '*')
  25. check('abc', 'ab[cd]')
  26. check('abc', 'ab[!de]')
  27. check('abc', 'ab[de]', False)
  28. check('a', '??', False)
  29. check('a', 'b', False)
  30. # these test that '\' is handled correctly in character sets;
  31. # see SF bug #409651
  32. check('\\', r'[\]')
  33. check('a', r'[!\]')
  34. check('\\', r'[!\]', False)
  35. # test that filenames with newlines in them are handled correctly.
  36. # http://bugs.python.org/issue6665
  37. check('foo\nbar', 'foo*')
  38. check('foo\nbar\n', 'foo*')
  39. check('\nfoo', 'foo*', False)
  40. check('\n', '*')
  41. def test_slow_fnmatch(self):
  42. check = self.check_match
  43. check('a' * 50, '*a*a*a*a*a*a*a*a*a*a')
  44. # The next "takes forever" if the regexp translation is
  45. # straightforward. See bpo-40480.
  46. check('a' * 50 + 'b', '*a*a*a*a*a*a*a*a*a*a', False)
  47. def test_mix_bytes_str(self):
  48. self.assertRaises(TypeError, fnmatch, 'test', b'*')
  49. self.assertRaises(TypeError, fnmatch, b'test', '*')
  50. self.assertRaises(TypeError, fnmatchcase, 'test', b'*')
  51. self.assertRaises(TypeError, fnmatchcase, b'test', '*')
  52. def test_fnmatchcase(self):
  53. check = self.check_match
  54. check('abc', 'abc', True, fnmatchcase)
  55. check('AbC', 'abc', False, fnmatchcase)
  56. check('abc', 'AbC', False, fnmatchcase)
  57. check('AbC', 'AbC', True, fnmatchcase)
  58. check('usr/bin', 'usr/bin', True, fnmatchcase)
  59. check('usr\\bin', 'usr/bin', False, fnmatchcase)
  60. check('usr/bin', 'usr\\bin', False, fnmatchcase)
  61. check('usr\\bin', 'usr\\bin', True, fnmatchcase)
  62. def test_bytes(self):
  63. self.check_match(b'test', b'te*')
  64. self.check_match(b'test\xff', b'te*\xff')
  65. self.check_match(b'foo\nbar', b'foo*')
  66. def test_case(self):
  67. ignorecase = os.path.normcase('ABC') == os.path.normcase('abc')
  68. check = self.check_match
  69. check('abc', 'abc')
  70. check('AbC', 'abc', ignorecase)
  71. check('abc', 'AbC', ignorecase)
  72. check('AbC', 'AbC')
  73. def test_sep(self):
  74. normsep = os.path.normcase('\\') == os.path.normcase('/')
  75. check = self.check_match
  76. check('usr/bin', 'usr/bin')
  77. check('usr\\bin', 'usr/bin', normsep)
  78. check('usr/bin', 'usr\\bin', normsep)
  79. check('usr\\bin', 'usr\\bin')
  80. def test_char_set(self):
  81. ignorecase = os.path.normcase('ABC') == os.path.normcase('abc')
  82. check = self.check_match
  83. tescases = string.ascii_lowercase + string.digits + string.punctuation
  84. for c in tescases:
  85. check(c, '[az]', c in 'az')
  86. check(c, '[!az]', c not in 'az')
  87. # Case insensitive.
  88. for c in tescases:
  89. check(c, '[AZ]', (c in 'az') and ignorecase)
  90. check(c, '[!AZ]', (c not in 'az') or not ignorecase)
  91. for c in string.ascii_uppercase:
  92. check(c, '[az]', (c in 'AZ') and ignorecase)
  93. check(c, '[!az]', (c not in 'AZ') or not ignorecase)
  94. # Repeated same character.
  95. for c in tescases:
  96. check(c, '[aa]', c == 'a')
  97. # Special cases.
  98. for c in tescases:
  99. check(c, '[^az]', c in '^az')
  100. check(c, '[[az]', c in '[az')
  101. check(c, r'[!]]', c != ']')
  102. check('[', '[')
  103. check('[]', '[]')
  104. check('[!', '[!')
  105. check('[!]', '[!]')
  106. def test_range(self):
  107. ignorecase = os.path.normcase('ABC') == os.path.normcase('abc')
  108. normsep = os.path.normcase('\\') == os.path.normcase('/')
  109. check = self.check_match
  110. tescases = string.ascii_lowercase + string.digits + string.punctuation
  111. for c in tescases:
  112. check(c, '[b-d]', c in 'bcd')
  113. check(c, '[!b-d]', c not in 'bcd')
  114. check(c, '[b-dx-z]', c in 'bcdxyz')
  115. check(c, '[!b-dx-z]', c not in 'bcdxyz')
  116. # Case insensitive.
  117. for c in tescases:
  118. check(c, '[B-D]', (c in 'bcd') and ignorecase)
  119. check(c, '[!B-D]', (c not in 'bcd') or not ignorecase)
  120. for c in string.ascii_uppercase:
  121. check(c, '[b-d]', (c in 'BCD') and ignorecase)
  122. check(c, '[!b-d]', (c not in 'BCD') or not ignorecase)
  123. # Upper bound == lower bound.
  124. for c in tescases:
  125. check(c, '[b-b]', c == 'b')
  126. # Special cases.
  127. for c in tescases:
  128. check(c, '[!-#]', c not in '-#')
  129. check(c, '[!--.]', c not in '-.')
  130. check(c, '[^-`]', c in '^_`')
  131. if not (normsep and c == '/'):
  132. check(c, '[[-^]', c in r'[\]^')
  133. check(c, r'[\-^]', c in r'\]^')
  134. check(c, '[b-]', c in '-b')
  135. check(c, '[!b-]', c not in '-b')
  136. check(c, '[-b]', c in '-b')
  137. check(c, '[!-b]', c not in '-b')
  138. check(c, '[-]', c in '-')
  139. check(c, '[!-]', c not in '-')
  140. # Upper bound is less that lower bound: error in RE.
  141. for c in tescases:
  142. check(c, '[d-b]', False)
  143. check(c, '[!d-b]', True)
  144. check(c, '[d-bx-z]', c in 'xyz')
  145. check(c, '[!d-bx-z]', c not in 'xyz')
  146. check(c, '[d-b^-`]', c in '^_`')
  147. if not (normsep and c == '/'):
  148. check(c, '[d-b[-^]', c in r'[\]^')
  149. def test_sep_in_char_set(self):
  150. normsep = os.path.normcase('\\') == os.path.normcase('/')
  151. check = self.check_match
  152. check('/', r'[/]')
  153. check('\\', r'[\]')
  154. check('/', r'[\]', normsep)
  155. check('\\', r'[/]', normsep)
  156. check('[/]', r'[/]', False)
  157. check(r'[\\]', r'[/]', False)
  158. check('\\', r'[\t]')
  159. check('/', r'[\t]', normsep)
  160. check('t', r'[\t]')
  161. check('\t', r'[\t]', False)
  162. def test_sep_in_range(self):
  163. normsep = os.path.normcase('\\') == os.path.normcase('/')
  164. check = self.check_match
  165. check('a/b', 'a[.-0]b', not normsep)
  166. check('a\\b', 'a[.-0]b', False)
  167. check('a\\b', 'a[Z-^]b', not normsep)
  168. check('a/b', 'a[Z-^]b', False)
  169. check('a/b', 'a[/-0]b', not normsep)
  170. check(r'a\b', 'a[/-0]b', False)
  171. check('a[/-0]b', 'a[/-0]b', False)
  172. check(r'a[\-0]b', 'a[/-0]b', False)
  173. check('a/b', 'a[.-/]b')
  174. check(r'a\b', 'a[.-/]b', normsep)
  175. check('a[.-/]b', 'a[.-/]b', False)
  176. check(r'a[.-\]b', 'a[.-/]b', False)
  177. check(r'a\b', r'a[\-^]b')
  178. check('a/b', r'a[\-^]b', normsep)
  179. check(r'a[\-^]b', r'a[\-^]b', False)
  180. check('a[/-^]b', r'a[\-^]b', False)
  181. check(r'a\b', r'a[Z-\]b', not normsep)
  182. check('a/b', r'a[Z-\]b', False)
  183. check(r'a[Z-\]b', r'a[Z-\]b', False)
  184. check('a[Z-/]b', r'a[Z-\]b', False)
  185. def test_warnings(self):
  186. with warnings.catch_warnings():
  187. warnings.simplefilter('error', Warning)
  188. check = self.check_match
  189. check('[', '[[]')
  190. check('&', '[a&&b]')
  191. check('|', '[a||b]')
  192. check('~', '[a~~b]')
  193. check(',', '[a-z+--A-Z]')
  194. check('.', '[a-z--/A-Z]')
  195. class TranslateTestCase(unittest.TestCase):
  196. def test_translate(self):
  197. import re
  198. self.assertEqual(translate('*'), r'(?s:.*)\Z')
  199. self.assertEqual(translate('?'), r'(?s:.)\Z')
  200. self.assertEqual(translate('a?b*'), r'(?s:a.b.*)\Z')
  201. self.assertEqual(translate('[abc]'), r'(?s:[abc])\Z')
  202. self.assertEqual(translate('[]]'), r'(?s:[]])\Z')
  203. self.assertEqual(translate('[!x]'), r'(?s:[^x])\Z')
  204. self.assertEqual(translate('[^x]'), r'(?s:[\^x])\Z')
  205. self.assertEqual(translate('[x'), r'(?s:\[x)\Z')
  206. # from the docs
  207. self.assertEqual(translate('*.txt'), r'(?s:.*\.txt)\Z')
  208. # squash consecutive stars
  209. self.assertEqual(translate('*********'), r'(?s:.*)\Z')
  210. self.assertEqual(translate('A*********'), r'(?s:A.*)\Z')
  211. self.assertEqual(translate('*********A'), r'(?s:.*A)\Z')
  212. self.assertEqual(translate('A*********?[?]?'), r'(?s:A.*.[?].)\Z')
  213. # fancy translation to prevent exponential-time match failure
  214. t = translate('**a*a****a')
  215. self.assertEqual(t, r'(?s:(?>.*?a)(?>.*?a).*a)\Z')
  216. # and try pasting multiple translate results - it's an undocumented
  217. # feature that this works
  218. r1 = translate('**a**a**a*')
  219. r2 = translate('**b**b**b*')
  220. r3 = translate('*c*c*c*')
  221. fatre = "|".join([r1, r2, r3])
  222. self.assertTrue(re.match(fatre, 'abaccad'))
  223. self.assertTrue(re.match(fatre, 'abxbcab'))
  224. self.assertTrue(re.match(fatre, 'cbabcaxc'))
  225. self.assertFalse(re.match(fatre, 'dabccbad'))
  226. class FilterTestCase(unittest.TestCase):
  227. def test_filter(self):
  228. self.assertEqual(filter(['Python', 'Ruby', 'Perl', 'Tcl'], 'P*'),
  229. ['Python', 'Perl'])
  230. self.assertEqual(filter([b'Python', b'Ruby', b'Perl', b'Tcl'], b'P*'),
  231. [b'Python', b'Perl'])
  232. def test_mix_bytes_str(self):
  233. self.assertRaises(TypeError, filter, ['test'], b'*')
  234. self.assertRaises(TypeError, filter, [b'test'], '*')
  235. def test_case(self):
  236. ignorecase = os.path.normcase('P') == os.path.normcase('p')
  237. self.assertEqual(filter(['Test.py', 'Test.rb', 'Test.PL'], '*.p*'),
  238. ['Test.py', 'Test.PL'] if ignorecase else ['Test.py'])
  239. self.assertEqual(filter(['Test.py', 'Test.rb', 'Test.PL'], '*.P*'),
  240. ['Test.py', 'Test.PL'] if ignorecase else ['Test.PL'])
  241. def test_sep(self):
  242. normsep = os.path.normcase('\\') == os.path.normcase('/')
  243. self.assertEqual(filter(['usr/bin', 'usr', 'usr\\lib'], 'usr/*'),
  244. ['usr/bin', 'usr\\lib'] if normsep else ['usr/bin'])
  245. self.assertEqual(filter(['usr/bin', 'usr', 'usr\\lib'], 'usr\\*'),
  246. ['usr/bin', 'usr\\lib'] if normsep else ['usr\\lib'])
  247. if __name__ == "__main__":
  248. unittest.main()