Home | History | Annotate | Download | only in tests
      1 """Tests for distutils.filelist."""
      2 import os
      3 import re
      4 import unittest
      5 from distutils import debug
      6 from distutils.log import WARN
      7 from distutils.errors import DistutilsTemplateError
      8 from distutils.filelist import glob_to_re, translate_pattern, FileList
      9 
     10 from test.test_support import captured_stdout, run_unittest
     11 from distutils.tests import support
     12 
     13 MANIFEST_IN = """\
     14 include ok
     15 include xo
     16 exclude xo
     17 include foo.tmp
     18 include buildout.cfg
     19 global-include *.x
     20 global-include *.txt
     21 global-exclude *.tmp
     22 recursive-include f *.oo
     23 recursive-exclude global *.x
     24 graft dir
     25 prune dir3
     26 """
     27 
     28 
     29 def make_local_path(s):
     30     """Converts '/' in a string to os.sep"""
     31     return s.replace('/', os.sep)
     32 
     33 
     34 class FileListTestCase(support.LoggingSilencer,
     35                        unittest.TestCase):
     36 
     37     def assertNoWarnings(self):
     38         self.assertEqual(self.get_logs(WARN), [])
     39         self.clear_logs()
     40 
     41     def assertWarnings(self):
     42         self.assertGreater(len(self.get_logs(WARN)), 0)
     43         self.clear_logs()
     44 
     45     def test_glob_to_re(self):
     46         sep = os.sep
     47         if os.sep == '\\':
     48             sep = re.escape(os.sep)
     49 
     50         for glob, regex in (
     51             # simple cases
     52             ('foo*', r'foo[^%(sep)s]*\Z(?ms)'),
     53             ('foo?', r'foo[^%(sep)s]\Z(?ms)'),
     54             ('foo??', r'foo[^%(sep)s][^%(sep)s]\Z(?ms)'),
     55             # special cases
     56             (r'foo\\*', r'foo\\\\[^%(sep)s]*\Z(?ms)'),
     57             (r'foo\\\*', r'foo\\\\\\[^%(sep)s]*\Z(?ms)'),
     58             ('foo????', r'foo[^%(sep)s][^%(sep)s][^%(sep)s][^%(sep)s]\Z(?ms)'),
     59             (r'foo\\??', r'foo\\\\[^%(sep)s][^%(sep)s]\Z(?ms)')):
     60             regex = regex % {'sep': sep}
     61             self.assertEqual(glob_to_re(glob), regex)
     62 
     63     def test_process_template_line(self):
     64         # testing  all MANIFEST.in template patterns
     65         file_list = FileList()
     66         l = make_local_path
     67 
     68         # simulated file list
     69         file_list.allfiles = ['foo.tmp', 'ok', 'xo', 'four.txt',
     70                               'buildout.cfg',
     71                               # filelist does not filter out VCS directories,
     72                               # it's sdist that does
     73                               l('.hg/last-message.txt'),
     74                               l('global/one.txt'),
     75                               l('global/two.txt'),
     76                               l('global/files.x'),
     77                               l('global/here.tmp'),
     78                               l('f/o/f.oo'),
     79                               l('dir/graft-one'),
     80                               l('dir/dir2/graft2'),
     81                               l('dir3/ok'),
     82                               l('dir3/sub/ok.txt'),
     83                              ]
     84 
     85         for line in MANIFEST_IN.split('\n'):
     86             if line.strip() == '':
     87                 continue
     88             file_list.process_template_line(line)
     89 
     90         wanted = ['ok',
     91                   'buildout.cfg',
     92                   'four.txt',
     93                   l('.hg/last-message.txt'),
     94                   l('global/one.txt'),
     95                   l('global/two.txt'),
     96                   l('f/o/f.oo'),
     97                   l('dir/graft-one'),
     98                   l('dir/dir2/graft2'),
     99                  ]
    100 
    101         self.assertEqual(file_list.files, wanted)
    102 
    103     def test_debug_print(self):
    104         file_list = FileList()
    105         with captured_stdout() as stdout:
    106             file_list.debug_print('xxx')
    107         self.assertEqual(stdout.getvalue(), '')
    108 
    109         debug.DEBUG = True
    110         try:
    111             with captured_stdout() as stdout:
    112                 file_list.debug_print('xxx')
    113             self.assertEqual(stdout.getvalue(), 'xxx\n')
    114         finally:
    115             debug.DEBUG = False
    116 
    117     def test_set_allfiles(self):
    118         file_list = FileList()
    119         files = ['a', 'b', 'c']
    120         file_list.set_allfiles(files)
    121         self.assertEqual(file_list.allfiles, files)
    122 
    123     def test_remove_duplicates(self):
    124         file_list = FileList()
    125         file_list.files = ['a', 'b', 'a', 'g', 'c', 'g']
    126         # files must be sorted beforehand (sdist does it)
    127         file_list.sort()
    128         file_list.remove_duplicates()
    129         self.assertEqual(file_list.files, ['a', 'b', 'c', 'g'])
    130 
    131     def test_translate_pattern(self):
    132         # not regex
    133         self.assertTrue(hasattr(
    134             translate_pattern('a', anchor=True, is_regex=False),
    135             'search'))
    136 
    137         # is a regex
    138         regex = re.compile('a')
    139         self.assertEqual(
    140             translate_pattern(regex, anchor=True, is_regex=True),
    141             regex)
    142 
    143         # plain string flagged as regex
    144         self.assertTrue(hasattr(
    145             translate_pattern('a', anchor=True, is_regex=True),
    146             'search'))
    147 
    148         # glob support
    149         self.assertTrue(translate_pattern(
    150             '*.py', anchor=True, is_regex=False).search('filelist.py'))
    151 
    152     def test_exclude_pattern(self):
    153         # return False if no match
    154         file_list = FileList()
    155         self.assertFalse(file_list.exclude_pattern('*.py'))
    156 
    157         # return True if files match
    158         file_list = FileList()
    159         file_list.files = ['a.py', 'b.py']
    160         self.assertTrue(file_list.exclude_pattern('*.py'))
    161 
    162         # test excludes
    163         file_list = FileList()
    164         file_list.files = ['a.py', 'a.txt']
    165         file_list.exclude_pattern('*.py')
    166         self.assertEqual(file_list.files, ['a.txt'])
    167 
    168     def test_include_pattern(self):
    169         # return False if no match
    170         file_list = FileList()
    171         file_list.set_allfiles([])
    172         self.assertFalse(file_list.include_pattern('*.py'))
    173 
    174         # return True if files match
    175         file_list = FileList()
    176         file_list.set_allfiles(['a.py', 'b.txt'])
    177         self.assertTrue(file_list.include_pattern('*.py'))
    178 
    179         # test * matches all files
    180         file_list = FileList()
    181         self.assertIsNone(file_list.allfiles)
    182         file_list.set_allfiles(['a.py', 'b.txt'])
    183         file_list.include_pattern('*')
    184         self.assertEqual(file_list.allfiles, ['a.py', 'b.txt'])
    185 
    186     def test_process_template(self):
    187         l = make_local_path
    188         # invalid lines
    189         file_list = FileList()
    190         for action in ('include', 'exclude', 'global-include',
    191                        'global-exclude', 'recursive-include',
    192                        'recursive-exclude', 'graft', 'prune', 'blarg'):
    193             self.assertRaises(DistutilsTemplateError,
    194                               file_list.process_template_line, action)
    195 
    196         # include
    197         file_list = FileList()
    198         file_list.set_allfiles(['a.py', 'b.txt', l('d/c.py')])
    199 
    200         file_list.process_template_line('include *.py')
    201         self.assertEqual(file_list.files, ['a.py'])
    202         self.assertNoWarnings()
    203 
    204         file_list.process_template_line('include *.rb')
    205         self.assertEqual(file_list.files, ['a.py'])
    206         self.assertWarnings()
    207 
    208         # exclude
    209         file_list = FileList()
    210         file_list.files = ['a.py', 'b.txt', l('d/c.py')]
    211 
    212         file_list.process_template_line('exclude *.py')
    213         self.assertEqual(file_list.files, ['b.txt', l('d/c.py')])
    214         self.assertNoWarnings()
    215 
    216         file_list.process_template_line('exclude *.rb')
    217         self.assertEqual(file_list.files, ['b.txt', l('d/c.py')])
    218         self.assertWarnings()
    219 
    220         # global-include
    221         file_list = FileList()
    222         file_list.set_allfiles(['a.py', 'b.txt', l('d/c.py')])
    223 
    224         file_list.process_template_line('global-include *.py')
    225         self.assertEqual(file_list.files, ['a.py', l('d/c.py')])
    226         self.assertNoWarnings()
    227 
    228         file_list.process_template_line('global-include *.rb')
    229         self.assertEqual(file_list.files, ['a.py', l('d/c.py')])
    230         self.assertWarnings()
    231 
    232         # global-exclude
    233         file_list = FileList()
    234         file_list.files = ['a.py', 'b.txt', l('d/c.py')]
    235 
    236         file_list.process_template_line('global-exclude *.py')
    237         self.assertEqual(file_list.files, ['b.txt'])
    238         self.assertNoWarnings()
    239 
    240         file_list.process_template_line('global-exclude *.rb')
    241         self.assertEqual(file_list.files, ['b.txt'])
    242         self.assertWarnings()
    243 
    244         # recursive-include
    245         file_list = FileList()
    246         file_list.set_allfiles(['a.py', l('d/b.py'), l('d/c.txt'),
    247                                 l('d/d/e.py')])
    248 
    249         file_list.process_template_line('recursive-include d *.py')
    250         self.assertEqual(file_list.files, [l('d/b.py'), l('d/d/e.py')])
    251         self.assertNoWarnings()
    252 
    253         file_list.process_template_line('recursive-include e *.py')
    254         self.assertEqual(file_list.files, [l('d/b.py'), l('d/d/e.py')])
    255         self.assertWarnings()
    256 
    257         # recursive-exclude
    258         file_list = FileList()
    259         file_list.files = ['a.py', l('d/b.py'), l('d/c.txt'), l('d/d/e.py')]
    260 
    261         file_list.process_template_line('recursive-exclude d *.py')
    262         self.assertEqual(file_list.files, ['a.py', l('d/c.txt')])
    263         self.assertNoWarnings()
    264 
    265         file_list.process_template_line('recursive-exclude e *.py')
    266         self.assertEqual(file_list.files, ['a.py', l('d/c.txt')])
    267         self.assertWarnings()
    268 
    269         # graft
    270         file_list = FileList()
    271         file_list.set_allfiles(['a.py', l('d/b.py'), l('d/d/e.py'),
    272                                 l('f/f.py')])
    273 
    274         file_list.process_template_line('graft d')
    275         self.assertEqual(file_list.files, [l('d/b.py'), l('d/d/e.py')])
    276         self.assertNoWarnings()
    277 
    278         file_list.process_template_line('graft e')
    279         self.assertEqual(file_list.files, [l('d/b.py'), l('d/d/e.py')])
    280         self.assertWarnings()
    281 
    282         # prune
    283         file_list = FileList()
    284         file_list.files = ['a.py', l('d/b.py'), l('d/d/e.py'), l('f/f.py')]
    285 
    286         file_list.process_template_line('prune d')
    287         self.assertEqual(file_list.files, ['a.py', l('f/f.py')])
    288         self.assertNoWarnings()
    289 
    290         file_list.process_template_line('prune e')
    291         self.assertEqual(file_list.files, ['a.py', l('f/f.py')])
    292         self.assertWarnings()
    293 
    294 
    295 def test_suite():
    296     return unittest.makeSuite(FileListTestCase)
    297 
    298 if __name__ == "__main__":
    299     run_unittest(test_suite())
    300