diff options
Diffstat (limited to 'Lib/packaging/tests/test_manifest.py')
-rw-r--r-- | Lib/packaging/tests/test_manifest.py | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/Lib/packaging/tests/test_manifest.py b/Lib/packaging/tests/test_manifest.py new file mode 100644 index 0000000..7aa59c1 --- /dev/null +++ b/Lib/packaging/tests/test_manifest.py @@ -0,0 +1,331 @@ +"""Tests for packaging.manifest.""" +import os +import re +from io import StringIO +from packaging.errors import PackagingTemplateError +from packaging.manifest import Manifest, _translate_pattern, _glob_to_re + +from packaging.tests import unittest, support + +MANIFEST_IN = """\ +include ok +include xo +exclude xo +include foo.tmp +include buildout.cfg +global-include *.x +global-include *.txt +global-exclude *.tmp +recursive-include f *.oo +recursive-exclude global *.x +graft dir +prune dir3 +""" + +MANIFEST_IN_2 = """\ +recursive-include foo *.py # ok +# nothing here + +# + +recursive-include bar \\ + *.dat *.txt +""" + +MANIFEST_IN_3 = """\ +README +file1 +""" + + +def make_local_path(s): + """Converts '/' in a string to os.sep""" + return s.replace('/', os.sep) + + +class ManifestTestCase(support.TempdirManager, + support.LoggingCatcher, + unittest.TestCase): + + def assertNoWarnings(self): + self.assertEqual(self.get_logs(), []) + + def assertWarnings(self): + self.assertNotEqual(self.get_logs(), []) + + def test_manifest_reader(self): + tmpdir = self.mkdtemp() + MANIFEST = os.path.join(tmpdir, 'MANIFEST.in') + with open(MANIFEST, 'w') as f: + f.write(MANIFEST_IN_2) + + manifest = Manifest() + manifest.read_template(MANIFEST) + + warnings = self.get_logs() + # the manifest should have been read and 3 warnings issued + # (we didn't provide the files) + self.assertEqual(3, len(warnings)) + for warning in warnings: + self.assertIn('no files found matching', warning) + + # manifest also accepts file-like objects + with open(MANIFEST) as f: + manifest.read_template(f) + + # the manifest should have been read and 3 warnings issued + # (we didn't provide the files) + self.assertEqual(3, len(warnings)) + + def test_default_actions(self): + tmpdir = self.mkdtemp() + self.addCleanup(os.chdir, os.getcwd()) + os.chdir(tmpdir) + self.write_file('README', 'xxx') + self.write_file('file1', 'xxx') + content = StringIO(MANIFEST_IN_3) + manifest = Manifest() + manifest.read_template(content) + self.assertEqual(['README', 'file1'], manifest.files) + + def test_glob_to_re(self): + sep = os.sep + if os.sep == '\\': + sep = r'\\' + + for glob, regex in ( + # simple cases + ('foo*', r'foo[^%(sep)s]*\Z(?ms)'), + ('foo?', r'foo[^%(sep)s]\Z(?ms)'), + ('foo??', r'foo[^%(sep)s][^%(sep)s]\Z(?ms)'), + # special cases + (r'foo\\*', r'foo\\\\[^%(sep)s]*\Z(?ms)'), + (r'foo\\\*', r'foo\\\\\\[^%(sep)s]*\Z(?ms)'), + ('foo????', r'foo[^%(sep)s][^%(sep)s][^%(sep)s][^%(sep)s]\Z(?ms)'), + (r'foo\\??', r'foo\\\\[^%(sep)s][^%(sep)s]\Z(?ms)'), + ): + regex = regex % {'sep': sep} + self.assertEqual(_glob_to_re(glob), regex) + + def test_process_template_line(self): + # testing all MANIFEST.in template patterns + manifest = Manifest() + l = make_local_path + + # simulated file list + manifest.allfiles = ['foo.tmp', 'ok', 'xo', 'four.txt', + 'buildout.cfg', + # filelist does not filter out VCS directories, + # it's sdist that does + l('.hg/last-message.txt'), + l('global/one.txt'), + l('global/two.txt'), + l('global/files.x'), + l('global/here.tmp'), + l('f/o/f.oo'), + l('dir/graft-one'), + l('dir/dir2/graft2'), + l('dir3/ok'), + l('dir3/sub/ok.txt'), + ] + + for line in MANIFEST_IN.split('\n'): + if line.strip() == '': + continue + manifest._process_template_line(line) + + wanted = ['ok', + 'buildout.cfg', + 'four.txt', + l('.hg/last-message.txt'), + l('global/one.txt'), + l('global/two.txt'), + l('f/o/f.oo'), + l('dir/graft-one'), + l('dir/dir2/graft2'), + ] + + self.assertEqual(manifest.files, wanted) + + def test_remove_duplicates(self): + manifest = Manifest() + manifest.files = ['a', 'b', 'a', 'g', 'c', 'g'] + # files must be sorted beforehand (like sdist does) + manifest.sort() + manifest.remove_duplicates() + self.assertEqual(manifest.files, ['a', 'b', 'c', 'g']) + + def test_translate_pattern(self): + # blackbox test of a private function + + # not regex + pattern = _translate_pattern('a', anchor=True, is_regex=False) + self.assertTrue(hasattr(pattern, 'search')) + + # is a regex + regex = re.compile('a') + pattern = _translate_pattern(regex, anchor=True, is_regex=True) + self.assertEqual(pattern, regex) + + # plain string flagged as regex + pattern = _translate_pattern('a', anchor=True, is_regex=True) + self.assertTrue(hasattr(pattern, 'search')) + + # glob support + pattern = _translate_pattern('*.py', anchor=True, is_regex=False) + self.assertTrue(pattern.search('filelist.py')) + + def test_exclude_pattern(self): + # return False if no match + manifest = Manifest() + self.assertFalse(manifest.exclude_pattern('*.py')) + + # return True if files match + manifest = Manifest() + manifest.files = ['a.py', 'b.py'] + self.assertTrue(manifest.exclude_pattern('*.py')) + + # test excludes + manifest = Manifest() + manifest.files = ['a.py', 'a.txt'] + manifest.exclude_pattern('*.py') + self.assertEqual(manifest.files, ['a.txt']) + + def test_include_pattern(self): + # return False if no match + manifest = Manifest() + manifest.allfiles = [] + self.assertFalse(manifest._include_pattern('*.py')) + + # return True if files match + manifest = Manifest() + manifest.allfiles = ['a.py', 'b.txt'] + self.assertTrue(manifest._include_pattern('*.py')) + + # test * matches all files + manifest = Manifest() + self.assertIsNone(manifest.allfiles) + manifest.allfiles = ['a.py', 'b.txt'] + manifest._include_pattern('*') + self.assertEqual(manifest.allfiles, ['a.py', 'b.txt']) + + def test_process_template(self): + l = make_local_path + # invalid lines + manifest = Manifest() + for action in ('include', 'exclude', 'global-include', + 'global-exclude', 'recursive-include', + 'recursive-exclude', 'graft', 'prune'): + self.assertRaises(PackagingTemplateError, + manifest._process_template_line, action) + + # implicit include + manifest = Manifest() + manifest.allfiles = ['a.py', 'b.txt', l('d/c.py')] + + manifest._process_template_line('*.py') + self.assertEqual(manifest.files, ['a.py']) + self.assertNoWarnings() + + # include + manifest = Manifest() + manifest.allfiles = ['a.py', 'b.txt', l('d/c.py')] + + manifest._process_template_line('include *.py') + self.assertEqual(manifest.files, ['a.py']) + self.assertNoWarnings() + + manifest._process_template_line('include *.rb') + self.assertEqual(manifest.files, ['a.py']) + self.assertWarnings() + + # exclude + manifest = Manifest() + manifest.files = ['a.py', 'b.txt', l('d/c.py')] + + manifest._process_template_line('exclude *.py') + self.assertEqual(manifest.files, ['b.txt', l('d/c.py')]) + self.assertNoWarnings() + + manifest._process_template_line('exclude *.rb') + self.assertEqual(manifest.files, ['b.txt', l('d/c.py')]) + self.assertWarnings() + + # global-include + manifest = Manifest() + manifest.allfiles = ['a.py', 'b.txt', l('d/c.py')] + + manifest._process_template_line('global-include *.py') + self.assertEqual(manifest.files, ['a.py', l('d/c.py')]) + self.assertNoWarnings() + + manifest._process_template_line('global-include *.rb') + self.assertEqual(manifest.files, ['a.py', l('d/c.py')]) + self.assertWarnings() + + # global-exclude + manifest = Manifest() + manifest.files = ['a.py', 'b.txt', l('d/c.py')] + + manifest._process_template_line('global-exclude *.py') + self.assertEqual(manifest.files, ['b.txt']) + self.assertNoWarnings() + + manifest._process_template_line('global-exclude *.rb') + self.assertEqual(manifest.files, ['b.txt']) + self.assertWarnings() + + # recursive-include + manifest = Manifest() + manifest.allfiles = ['a.py', l('d/b.py'), l('d/c.txt'), l('d/d/e.py')] + + manifest._process_template_line('recursive-include d *.py') + self.assertEqual(manifest.files, [l('d/b.py'), l('d/d/e.py')]) + self.assertNoWarnings() + + manifest._process_template_line('recursive-include e *.py') + self.assertEqual(manifest.files, [l('d/b.py'), l('d/d/e.py')]) + self.assertWarnings() + + # recursive-exclude + manifest = Manifest() + manifest.files = ['a.py', l('d/b.py'), l('d/c.txt'), l('d/d/e.py')] + + manifest._process_template_line('recursive-exclude d *.py') + self.assertEqual(manifest.files, ['a.py', l('d/c.txt')]) + self.assertNoWarnings() + + manifest._process_template_line('recursive-exclude e *.py') + self.assertEqual(manifest.files, ['a.py', l('d/c.txt')]) + self.assertWarnings() + + # graft + manifest = Manifest() + manifest.allfiles = ['a.py', l('d/b.py'), l('d/d/e.py'), l('f/f.py')] + + manifest._process_template_line('graft d') + self.assertEqual(manifest.files, [l('d/b.py'), l('d/d/e.py')]) + self.assertNoWarnings() + + manifest._process_template_line('graft e') + self.assertEqual(manifest.files, [l('d/b.py'), l('d/d/e.py')]) + self.assertWarnings() + + # prune + manifest = Manifest() + manifest.files = ['a.py', l('d/b.py'), l('d/d/e.py'), l('f/f.py')] + + manifest._process_template_line('prune d') + self.assertEqual(manifest.files, ['a.py', l('f/f.py')]) + self.assertNoWarnings() + + manifest._process_template_line('prune e') + self.assertEqual(manifest.files, ['a.py', l('f/f.py')]) + self.assertWarnings() + + +def test_suite(): + return unittest.makeSuite(ManifestTestCase) + +if __name__ == '__main__': + unittest.main(defaultTest='test_suite') |