17db96d56Sopenharmony_ci"""Tests for distutils.filelist."""
27db96d56Sopenharmony_ciimport os
37db96d56Sopenharmony_ciimport re
47db96d56Sopenharmony_ciimport unittest
57db96d56Sopenharmony_cifrom distutils import debug
67db96d56Sopenharmony_cifrom distutils.log import WARN
77db96d56Sopenharmony_cifrom distutils.errors import DistutilsTemplateError
87db96d56Sopenharmony_cifrom distutils.filelist import glob_to_re, translate_pattern, FileList
97db96d56Sopenharmony_cifrom distutils import filelist
107db96d56Sopenharmony_ci
117db96d56Sopenharmony_cifrom test.support import os_helper
127db96d56Sopenharmony_cifrom test.support import captured_stdout, run_unittest
137db96d56Sopenharmony_cifrom distutils.tests import support
147db96d56Sopenharmony_ci
157db96d56Sopenharmony_ciMANIFEST_IN = """\
167db96d56Sopenharmony_ciinclude ok
177db96d56Sopenharmony_ciinclude xo
187db96d56Sopenharmony_ciexclude xo
197db96d56Sopenharmony_ciinclude foo.tmp
207db96d56Sopenharmony_ciinclude buildout.cfg
217db96d56Sopenharmony_ciglobal-include *.x
227db96d56Sopenharmony_ciglobal-include *.txt
237db96d56Sopenharmony_ciglobal-exclude *.tmp
247db96d56Sopenharmony_cirecursive-include f *.oo
257db96d56Sopenharmony_cirecursive-exclude global *.x
267db96d56Sopenharmony_cigraft dir
277db96d56Sopenharmony_ciprune dir3
287db96d56Sopenharmony_ci"""
297db96d56Sopenharmony_ci
307db96d56Sopenharmony_ci
317db96d56Sopenharmony_cidef make_local_path(s):
327db96d56Sopenharmony_ci    """Converts '/' in a string to os.sep"""
337db96d56Sopenharmony_ci    return s.replace('/', os.sep)
347db96d56Sopenharmony_ci
357db96d56Sopenharmony_ci
367db96d56Sopenharmony_ciclass FileListTestCase(support.LoggingSilencer,
377db96d56Sopenharmony_ci                       unittest.TestCase):
387db96d56Sopenharmony_ci
397db96d56Sopenharmony_ci    def assertNoWarnings(self):
407db96d56Sopenharmony_ci        self.assertEqual(self.get_logs(WARN), [])
417db96d56Sopenharmony_ci        self.clear_logs()
427db96d56Sopenharmony_ci
437db96d56Sopenharmony_ci    def assertWarnings(self):
447db96d56Sopenharmony_ci        self.assertGreater(len(self.get_logs(WARN)), 0)
457db96d56Sopenharmony_ci        self.clear_logs()
467db96d56Sopenharmony_ci
477db96d56Sopenharmony_ci    def test_glob_to_re(self):
487db96d56Sopenharmony_ci        sep = os.sep
497db96d56Sopenharmony_ci        if os.sep == '\\':
507db96d56Sopenharmony_ci            sep = re.escape(os.sep)
517db96d56Sopenharmony_ci
527db96d56Sopenharmony_ci        for glob, regex in (
537db96d56Sopenharmony_ci            # simple cases
547db96d56Sopenharmony_ci            ('foo*', r'(?s:foo[^%(sep)s]*)\Z'),
557db96d56Sopenharmony_ci            ('foo?', r'(?s:foo[^%(sep)s])\Z'),
567db96d56Sopenharmony_ci            ('foo??', r'(?s:foo[^%(sep)s][^%(sep)s])\Z'),
577db96d56Sopenharmony_ci            # special cases
587db96d56Sopenharmony_ci            (r'foo\\*', r'(?s:foo\\\\[^%(sep)s]*)\Z'),
597db96d56Sopenharmony_ci            (r'foo\\\*', r'(?s:foo\\\\\\[^%(sep)s]*)\Z'),
607db96d56Sopenharmony_ci            ('foo????', r'(?s:foo[^%(sep)s][^%(sep)s][^%(sep)s][^%(sep)s])\Z'),
617db96d56Sopenharmony_ci            (r'foo\\??', r'(?s:foo\\\\[^%(sep)s][^%(sep)s])\Z')):
627db96d56Sopenharmony_ci            regex = regex % {'sep': sep}
637db96d56Sopenharmony_ci            self.assertEqual(glob_to_re(glob), regex)
647db96d56Sopenharmony_ci
657db96d56Sopenharmony_ci    def test_process_template_line(self):
667db96d56Sopenharmony_ci        # testing  all MANIFEST.in template patterns
677db96d56Sopenharmony_ci        file_list = FileList()
687db96d56Sopenharmony_ci        l = make_local_path
697db96d56Sopenharmony_ci
707db96d56Sopenharmony_ci        # simulated file list
717db96d56Sopenharmony_ci        file_list.allfiles = ['foo.tmp', 'ok', 'xo', 'four.txt',
727db96d56Sopenharmony_ci                              'buildout.cfg',
737db96d56Sopenharmony_ci                              # filelist does not filter out VCS directories,
747db96d56Sopenharmony_ci                              # it's sdist that does
757db96d56Sopenharmony_ci                              l('.hg/last-message.txt'),
767db96d56Sopenharmony_ci                              l('global/one.txt'),
777db96d56Sopenharmony_ci                              l('global/two.txt'),
787db96d56Sopenharmony_ci                              l('global/files.x'),
797db96d56Sopenharmony_ci                              l('global/here.tmp'),
807db96d56Sopenharmony_ci                              l('f/o/f.oo'),
817db96d56Sopenharmony_ci                              l('dir/graft-one'),
827db96d56Sopenharmony_ci                              l('dir/dir2/graft2'),
837db96d56Sopenharmony_ci                              l('dir3/ok'),
847db96d56Sopenharmony_ci                              l('dir3/sub/ok.txt'),
857db96d56Sopenharmony_ci                             ]
867db96d56Sopenharmony_ci
877db96d56Sopenharmony_ci        for line in MANIFEST_IN.split('\n'):
887db96d56Sopenharmony_ci            if line.strip() == '':
897db96d56Sopenharmony_ci                continue
907db96d56Sopenharmony_ci            file_list.process_template_line(line)
917db96d56Sopenharmony_ci
927db96d56Sopenharmony_ci        wanted = ['ok',
937db96d56Sopenharmony_ci                  'buildout.cfg',
947db96d56Sopenharmony_ci                  'four.txt',
957db96d56Sopenharmony_ci                  l('.hg/last-message.txt'),
967db96d56Sopenharmony_ci                  l('global/one.txt'),
977db96d56Sopenharmony_ci                  l('global/two.txt'),
987db96d56Sopenharmony_ci                  l('f/o/f.oo'),
997db96d56Sopenharmony_ci                  l('dir/graft-one'),
1007db96d56Sopenharmony_ci                  l('dir/dir2/graft2'),
1017db96d56Sopenharmony_ci                 ]
1027db96d56Sopenharmony_ci
1037db96d56Sopenharmony_ci        self.assertEqual(file_list.files, wanted)
1047db96d56Sopenharmony_ci
1057db96d56Sopenharmony_ci    def test_debug_print(self):
1067db96d56Sopenharmony_ci        file_list = FileList()
1077db96d56Sopenharmony_ci        with captured_stdout() as stdout:
1087db96d56Sopenharmony_ci            file_list.debug_print('xxx')
1097db96d56Sopenharmony_ci        self.assertEqual(stdout.getvalue(), '')
1107db96d56Sopenharmony_ci
1117db96d56Sopenharmony_ci        debug.DEBUG = True
1127db96d56Sopenharmony_ci        try:
1137db96d56Sopenharmony_ci            with captured_stdout() as stdout:
1147db96d56Sopenharmony_ci                file_list.debug_print('xxx')
1157db96d56Sopenharmony_ci            self.assertEqual(stdout.getvalue(), 'xxx\n')
1167db96d56Sopenharmony_ci        finally:
1177db96d56Sopenharmony_ci            debug.DEBUG = False
1187db96d56Sopenharmony_ci
1197db96d56Sopenharmony_ci    def test_set_allfiles(self):
1207db96d56Sopenharmony_ci        file_list = FileList()
1217db96d56Sopenharmony_ci        files = ['a', 'b', 'c']
1227db96d56Sopenharmony_ci        file_list.set_allfiles(files)
1237db96d56Sopenharmony_ci        self.assertEqual(file_list.allfiles, files)
1247db96d56Sopenharmony_ci
1257db96d56Sopenharmony_ci    def test_remove_duplicates(self):
1267db96d56Sopenharmony_ci        file_list = FileList()
1277db96d56Sopenharmony_ci        file_list.files = ['a', 'b', 'a', 'g', 'c', 'g']
1287db96d56Sopenharmony_ci        # files must be sorted beforehand (sdist does it)
1297db96d56Sopenharmony_ci        file_list.sort()
1307db96d56Sopenharmony_ci        file_list.remove_duplicates()
1317db96d56Sopenharmony_ci        self.assertEqual(file_list.files, ['a', 'b', 'c', 'g'])
1327db96d56Sopenharmony_ci
1337db96d56Sopenharmony_ci    def test_translate_pattern(self):
1347db96d56Sopenharmony_ci        # not regex
1357db96d56Sopenharmony_ci        self.assertTrue(hasattr(
1367db96d56Sopenharmony_ci            translate_pattern('a', anchor=True, is_regex=False),
1377db96d56Sopenharmony_ci            'search'))
1387db96d56Sopenharmony_ci
1397db96d56Sopenharmony_ci        # is a regex
1407db96d56Sopenharmony_ci        regex = re.compile('a')
1417db96d56Sopenharmony_ci        self.assertEqual(
1427db96d56Sopenharmony_ci            translate_pattern(regex, anchor=True, is_regex=True),
1437db96d56Sopenharmony_ci            regex)
1447db96d56Sopenharmony_ci
1457db96d56Sopenharmony_ci        # plain string flagged as regex
1467db96d56Sopenharmony_ci        self.assertTrue(hasattr(
1477db96d56Sopenharmony_ci            translate_pattern('a', anchor=True, is_regex=True),
1487db96d56Sopenharmony_ci            'search'))
1497db96d56Sopenharmony_ci
1507db96d56Sopenharmony_ci        # glob support
1517db96d56Sopenharmony_ci        self.assertTrue(translate_pattern(
1527db96d56Sopenharmony_ci            '*.py', anchor=True, is_regex=False).search('filelist.py'))
1537db96d56Sopenharmony_ci
1547db96d56Sopenharmony_ci    def test_exclude_pattern(self):
1557db96d56Sopenharmony_ci        # return False if no match
1567db96d56Sopenharmony_ci        file_list = FileList()
1577db96d56Sopenharmony_ci        self.assertFalse(file_list.exclude_pattern('*.py'))
1587db96d56Sopenharmony_ci
1597db96d56Sopenharmony_ci        # return True if files match
1607db96d56Sopenharmony_ci        file_list = FileList()
1617db96d56Sopenharmony_ci        file_list.files = ['a.py', 'b.py']
1627db96d56Sopenharmony_ci        self.assertTrue(file_list.exclude_pattern('*.py'))
1637db96d56Sopenharmony_ci
1647db96d56Sopenharmony_ci        # test excludes
1657db96d56Sopenharmony_ci        file_list = FileList()
1667db96d56Sopenharmony_ci        file_list.files = ['a.py', 'a.txt']
1677db96d56Sopenharmony_ci        file_list.exclude_pattern('*.py')
1687db96d56Sopenharmony_ci        self.assertEqual(file_list.files, ['a.txt'])
1697db96d56Sopenharmony_ci
1707db96d56Sopenharmony_ci    def test_include_pattern(self):
1717db96d56Sopenharmony_ci        # return False if no match
1727db96d56Sopenharmony_ci        file_list = FileList()
1737db96d56Sopenharmony_ci        file_list.set_allfiles([])
1747db96d56Sopenharmony_ci        self.assertFalse(file_list.include_pattern('*.py'))
1757db96d56Sopenharmony_ci
1767db96d56Sopenharmony_ci        # return True if files match
1777db96d56Sopenharmony_ci        file_list = FileList()
1787db96d56Sopenharmony_ci        file_list.set_allfiles(['a.py', 'b.txt'])
1797db96d56Sopenharmony_ci        self.assertTrue(file_list.include_pattern('*.py'))
1807db96d56Sopenharmony_ci
1817db96d56Sopenharmony_ci        # test * matches all files
1827db96d56Sopenharmony_ci        file_list = FileList()
1837db96d56Sopenharmony_ci        self.assertIsNone(file_list.allfiles)
1847db96d56Sopenharmony_ci        file_list.set_allfiles(['a.py', 'b.txt'])
1857db96d56Sopenharmony_ci        file_list.include_pattern('*')
1867db96d56Sopenharmony_ci        self.assertEqual(file_list.allfiles, ['a.py', 'b.txt'])
1877db96d56Sopenharmony_ci
1887db96d56Sopenharmony_ci    def test_process_template(self):
1897db96d56Sopenharmony_ci        l = make_local_path
1907db96d56Sopenharmony_ci        # invalid lines
1917db96d56Sopenharmony_ci        file_list = FileList()
1927db96d56Sopenharmony_ci        for action in ('include', 'exclude', 'global-include',
1937db96d56Sopenharmony_ci                       'global-exclude', 'recursive-include',
1947db96d56Sopenharmony_ci                       'recursive-exclude', 'graft', 'prune', 'blarg'):
1957db96d56Sopenharmony_ci            self.assertRaises(DistutilsTemplateError,
1967db96d56Sopenharmony_ci                              file_list.process_template_line, action)
1977db96d56Sopenharmony_ci
1987db96d56Sopenharmony_ci        # include
1997db96d56Sopenharmony_ci        file_list = FileList()
2007db96d56Sopenharmony_ci        file_list.set_allfiles(['a.py', 'b.txt', l('d/c.py')])
2017db96d56Sopenharmony_ci
2027db96d56Sopenharmony_ci        file_list.process_template_line('include *.py')
2037db96d56Sopenharmony_ci        self.assertEqual(file_list.files, ['a.py'])
2047db96d56Sopenharmony_ci        self.assertNoWarnings()
2057db96d56Sopenharmony_ci
2067db96d56Sopenharmony_ci        file_list.process_template_line('include *.rb')
2077db96d56Sopenharmony_ci        self.assertEqual(file_list.files, ['a.py'])
2087db96d56Sopenharmony_ci        self.assertWarnings()
2097db96d56Sopenharmony_ci
2107db96d56Sopenharmony_ci        # exclude
2117db96d56Sopenharmony_ci        file_list = FileList()
2127db96d56Sopenharmony_ci        file_list.files = ['a.py', 'b.txt', l('d/c.py')]
2137db96d56Sopenharmony_ci
2147db96d56Sopenharmony_ci        file_list.process_template_line('exclude *.py')
2157db96d56Sopenharmony_ci        self.assertEqual(file_list.files, ['b.txt', l('d/c.py')])
2167db96d56Sopenharmony_ci        self.assertNoWarnings()
2177db96d56Sopenharmony_ci
2187db96d56Sopenharmony_ci        file_list.process_template_line('exclude *.rb')
2197db96d56Sopenharmony_ci        self.assertEqual(file_list.files, ['b.txt', l('d/c.py')])
2207db96d56Sopenharmony_ci        self.assertWarnings()
2217db96d56Sopenharmony_ci
2227db96d56Sopenharmony_ci        # global-include
2237db96d56Sopenharmony_ci        file_list = FileList()
2247db96d56Sopenharmony_ci        file_list.set_allfiles(['a.py', 'b.txt', l('d/c.py')])
2257db96d56Sopenharmony_ci
2267db96d56Sopenharmony_ci        file_list.process_template_line('global-include *.py')
2277db96d56Sopenharmony_ci        self.assertEqual(file_list.files, ['a.py', l('d/c.py')])
2287db96d56Sopenharmony_ci        self.assertNoWarnings()
2297db96d56Sopenharmony_ci
2307db96d56Sopenharmony_ci        file_list.process_template_line('global-include *.rb')
2317db96d56Sopenharmony_ci        self.assertEqual(file_list.files, ['a.py', l('d/c.py')])
2327db96d56Sopenharmony_ci        self.assertWarnings()
2337db96d56Sopenharmony_ci
2347db96d56Sopenharmony_ci        # global-exclude
2357db96d56Sopenharmony_ci        file_list = FileList()
2367db96d56Sopenharmony_ci        file_list.files = ['a.py', 'b.txt', l('d/c.py')]
2377db96d56Sopenharmony_ci
2387db96d56Sopenharmony_ci        file_list.process_template_line('global-exclude *.py')
2397db96d56Sopenharmony_ci        self.assertEqual(file_list.files, ['b.txt'])
2407db96d56Sopenharmony_ci        self.assertNoWarnings()
2417db96d56Sopenharmony_ci
2427db96d56Sopenharmony_ci        file_list.process_template_line('global-exclude *.rb')
2437db96d56Sopenharmony_ci        self.assertEqual(file_list.files, ['b.txt'])
2447db96d56Sopenharmony_ci        self.assertWarnings()
2457db96d56Sopenharmony_ci
2467db96d56Sopenharmony_ci        # recursive-include
2477db96d56Sopenharmony_ci        file_list = FileList()
2487db96d56Sopenharmony_ci        file_list.set_allfiles(['a.py', l('d/b.py'), l('d/c.txt'),
2497db96d56Sopenharmony_ci                                l('d/d/e.py')])
2507db96d56Sopenharmony_ci
2517db96d56Sopenharmony_ci        file_list.process_template_line('recursive-include d *.py')
2527db96d56Sopenharmony_ci        self.assertEqual(file_list.files, [l('d/b.py'), l('d/d/e.py')])
2537db96d56Sopenharmony_ci        self.assertNoWarnings()
2547db96d56Sopenharmony_ci
2557db96d56Sopenharmony_ci        file_list.process_template_line('recursive-include e *.py')
2567db96d56Sopenharmony_ci        self.assertEqual(file_list.files, [l('d/b.py'), l('d/d/e.py')])
2577db96d56Sopenharmony_ci        self.assertWarnings()
2587db96d56Sopenharmony_ci
2597db96d56Sopenharmony_ci        # recursive-exclude
2607db96d56Sopenharmony_ci        file_list = FileList()
2617db96d56Sopenharmony_ci        file_list.files = ['a.py', l('d/b.py'), l('d/c.txt'), l('d/d/e.py')]
2627db96d56Sopenharmony_ci
2637db96d56Sopenharmony_ci        file_list.process_template_line('recursive-exclude d *.py')
2647db96d56Sopenharmony_ci        self.assertEqual(file_list.files, ['a.py', l('d/c.txt')])
2657db96d56Sopenharmony_ci        self.assertNoWarnings()
2667db96d56Sopenharmony_ci
2677db96d56Sopenharmony_ci        file_list.process_template_line('recursive-exclude e *.py')
2687db96d56Sopenharmony_ci        self.assertEqual(file_list.files, ['a.py', l('d/c.txt')])
2697db96d56Sopenharmony_ci        self.assertWarnings()
2707db96d56Sopenharmony_ci
2717db96d56Sopenharmony_ci        # graft
2727db96d56Sopenharmony_ci        file_list = FileList()
2737db96d56Sopenharmony_ci        file_list.set_allfiles(['a.py', l('d/b.py'), l('d/d/e.py'),
2747db96d56Sopenharmony_ci                                l('f/f.py')])
2757db96d56Sopenharmony_ci
2767db96d56Sopenharmony_ci        file_list.process_template_line('graft d')
2777db96d56Sopenharmony_ci        self.assertEqual(file_list.files, [l('d/b.py'), l('d/d/e.py')])
2787db96d56Sopenharmony_ci        self.assertNoWarnings()
2797db96d56Sopenharmony_ci
2807db96d56Sopenharmony_ci        file_list.process_template_line('graft e')
2817db96d56Sopenharmony_ci        self.assertEqual(file_list.files, [l('d/b.py'), l('d/d/e.py')])
2827db96d56Sopenharmony_ci        self.assertWarnings()
2837db96d56Sopenharmony_ci
2847db96d56Sopenharmony_ci        # prune
2857db96d56Sopenharmony_ci        file_list = FileList()
2867db96d56Sopenharmony_ci        file_list.files = ['a.py', l('d/b.py'), l('d/d/e.py'), l('f/f.py')]
2877db96d56Sopenharmony_ci
2887db96d56Sopenharmony_ci        file_list.process_template_line('prune d')
2897db96d56Sopenharmony_ci        self.assertEqual(file_list.files, ['a.py', l('f/f.py')])
2907db96d56Sopenharmony_ci        self.assertNoWarnings()
2917db96d56Sopenharmony_ci
2927db96d56Sopenharmony_ci        file_list.process_template_line('prune e')
2937db96d56Sopenharmony_ci        self.assertEqual(file_list.files, ['a.py', l('f/f.py')])
2947db96d56Sopenharmony_ci        self.assertWarnings()
2957db96d56Sopenharmony_ci
2967db96d56Sopenharmony_ci
2977db96d56Sopenharmony_ciclass FindAllTestCase(unittest.TestCase):
2987db96d56Sopenharmony_ci    @os_helper.skip_unless_symlink
2997db96d56Sopenharmony_ci    def test_missing_symlink(self):
3007db96d56Sopenharmony_ci        with os_helper.temp_cwd():
3017db96d56Sopenharmony_ci            os.symlink('foo', 'bar')
3027db96d56Sopenharmony_ci            self.assertEqual(filelist.findall(), [])
3037db96d56Sopenharmony_ci
3047db96d56Sopenharmony_ci    def test_basic_discovery(self):
3057db96d56Sopenharmony_ci        """
3067db96d56Sopenharmony_ci        When findall is called with no parameters or with
3077db96d56Sopenharmony_ci        '.' as the parameter, the dot should be omitted from
3087db96d56Sopenharmony_ci        the results.
3097db96d56Sopenharmony_ci        """
3107db96d56Sopenharmony_ci        with os_helper.temp_cwd():
3117db96d56Sopenharmony_ci            os.mkdir('foo')
3127db96d56Sopenharmony_ci            file1 = os.path.join('foo', 'file1.txt')
3137db96d56Sopenharmony_ci            os_helper.create_empty_file(file1)
3147db96d56Sopenharmony_ci            os.mkdir('bar')
3157db96d56Sopenharmony_ci            file2 = os.path.join('bar', 'file2.txt')
3167db96d56Sopenharmony_ci            os_helper.create_empty_file(file2)
3177db96d56Sopenharmony_ci            expected = [file2, file1]
3187db96d56Sopenharmony_ci            self.assertEqual(sorted(filelist.findall()), expected)
3197db96d56Sopenharmony_ci
3207db96d56Sopenharmony_ci    def test_non_local_discovery(self):
3217db96d56Sopenharmony_ci        """
3227db96d56Sopenharmony_ci        When findall is called with another path, the full
3237db96d56Sopenharmony_ci        path name should be returned.
3247db96d56Sopenharmony_ci        """
3257db96d56Sopenharmony_ci        with os_helper.temp_dir() as temp_dir:
3267db96d56Sopenharmony_ci            file1 = os.path.join(temp_dir, 'file1.txt')
3277db96d56Sopenharmony_ci            os_helper.create_empty_file(file1)
3287db96d56Sopenharmony_ci            expected = [file1]
3297db96d56Sopenharmony_ci            self.assertEqual(filelist.findall(temp_dir), expected)
3307db96d56Sopenharmony_ci
3317db96d56Sopenharmony_ci
3327db96d56Sopenharmony_cidef test_suite():
3337db96d56Sopenharmony_ci    return unittest.TestSuite([
3347db96d56Sopenharmony_ci        unittest.TestLoader().loadTestsFromTestCase(FileListTestCase),
3357db96d56Sopenharmony_ci        unittest.TestLoader().loadTestsFromTestCase(FindAllTestCase),
3367db96d56Sopenharmony_ci    ])
3377db96d56Sopenharmony_ci
3387db96d56Sopenharmony_ci
3397db96d56Sopenharmony_ciif __name__ == "__main__":
3407db96d56Sopenharmony_ci    run_unittest(test_suite())
341