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