distutils2 (merge default -> python3): Merge fixes for #13974, #6884 and #11841 from default

http://hg.python.org/distutils2/rev/7d1a7251d771 changeset: 1291:7d1a7251d771 branch: python3 parent: 1286:158697fd8fa1 parent: 1290:c82c97b2eae1 user: Éric Araujo <merwok@netwok.org> date: Mon Feb 27 12:29:18 2012 +0100 summary: Merge fixes for #13974, #6884 and #11841 from default files: CHANGES.txt | 3 + CONTRIBUTORS.txt | 1 + distutils2/manifest.py | 19 +- distutils2/tests/fixer/__init__.py | 1 + distutils2/tests/test_command_build_ext.py | 3 +- distutils2/tests/test_manifest.py | 138 +++++++-- distutils2/tests/test_util.py | 5 + distutils2/tests/test_version.py | 9 + distutils2/version.py | 24 +- 9 files changed, 150 insertions(+), 53 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt --- a/CHANGES.txt +++ b/CHANGES.txt @@ -166,6 +166,9 @@ script with pysetup create [éric] - #1326113: build_ext now correctly parses multiple values given to the --libraries option [éric] +- #13974: add test for util.set_platform [tshepang] +- #6884: Fix MANIFEST.in parsing bugs on Windows [éric, nadeem] +- #11841: Fix comparison bug with 'rc' versions [filip] 1.0a3 - 2010-10-08 diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -69,3 +69,4 @@ - Vinay Sajip - Victor Stinner - Alexandre Vassalotti +- Nadeem Vawda diff --git a/distutils2/manifest.py b/distutils2/manifest.py --- a/distutils2/manifest.py +++ b/distutils2/manifest.py @@ -272,6 +272,7 @@ Return True if files are found. """ + # XXX docstring lying about what the special chars are? files_found = False pattern_re = _translate_pattern(pattern, anchor, prefix, is_regex) @@ -335,11 +336,14 @@ # IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix, # and by extension they shouldn't match such "special characters" under # any OS. So change all non-escaped dots in the RE to match any - # character except the special characters. - # XXX currently the "special characters" are just slash -- i.e. this is - # Unix-only. - pattern_re = re.sub(r'((?<!\\)(\\\\)*)\.', r'\1[^/]', pattern_re) - + # character except the special characters (currently: just os.sep). + sep = os.sep + if os.sep == '\\': + # we're using a regex to manipulate a regex, so we need + # to escape the backslash twice + sep = r'\\\\' + escaped = r'\1[^%s]' % sep + pattern_re = re.sub(r'((?<!\\)(\\\\)*)\.', escaped, pattern_re) return pattern_re @@ -366,7 +370,10 @@ # ditch end of pattern character empty_pattern = _glob_to_re('') prefix_re = _glob_to_re(prefix)[:-len(empty_pattern)] - pattern_re = "^" + os.path.join(prefix_re, ".*" + pattern_re) + sep = os.sep + if os.sep == '\\': + sep = r'\\' + pattern_re = "^" + sep.join((prefix_re, ".*" + pattern_re)) else: # no prefix -- respect anchor flag if anchor: pattern_re = "^" + pattern_re diff --git a/distutils2/tests/fixer/__init__.py b/distutils2/tests/fixer/__init__.py --- a/distutils2/tests/fixer/__init__.py +++ b/distutils2/tests/fixer/__init__.py @@ -0,0 +1,1 @@ +"""Example fixers used in tests.""" diff --git a/distutils2/tests/test_command_build_ext.py b/distutils2/tests/test_command_build_ext.py --- a/distutils2/tests/test_command_build_ext.py +++ b/distutils2/tests/test_command_build_ext.py @@ -150,7 +150,8 @@ cmd = build_ext(dist) cmd.library_dirs = 'my_lib_dir%sother_lib_dir' % os.pathsep cmd.finalize_options() - self.assertEqual(cmd.library_dirs, ['my_lib_dir', 'other_lib_dir']) + self.assertIn('my_lib_dir', cmd.library_dirs) + self.assertIn('other_lib_dir', cmd.library_dirs) # make sure rpath is turned into a list # if it's a string diff --git a/distutils2/tests/test_manifest.py b/distutils2/tests/test_manifest.py --- a/distutils2/tests/test_manifest.py +++ b/distutils2/tests/test_manifest.py @@ -7,7 +7,22 @@ from distutils2.tests import unittest, support -_MANIFEST = """\ +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 @@ -17,12 +32,17 @@ *.dat *.txt """ -_MANIFEST2 = """\ +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): @@ -37,7 +57,7 @@ tmpdir = self.mkdtemp() MANIFEST = os.path.join(tmpdir, 'MANIFEST.in') with open(MANIFEST, 'w') as f: - f.write(_MANIFEST) + f.write(MANIFEST_IN_2) manifest = Manifest() manifest.read_template(MANIFEST) @@ -63,27 +83,74 @@ os.chdir(tmpdir) self.write_file('README', 'xxx') self.write_file('file1', 'xxx') - content = StringIO(_MANIFEST2) + content = StringIO(MANIFEST_IN_3) manifest = Manifest() manifest.read_template(content) self.assertEqual(['README', 'file1'], manifest.files) def test_glob_to_re(self): - # simple cases - self.assertEqual(_glob_to_re('foo*'), 'foo[^/]*\\Z(?ms)') - self.assertEqual(_glob_to_re('foo?'), 'foo[^/]\\Z(?ms)') - self.assertEqual(_glob_to_re('foo??'), 'foo[^/][^/]\\Z(?ms)') + sep = os.sep + if os.sep == '\\': + sep = r'\\' - # special cases - self.assertEqual(_glob_to_re(r'foo\\*'), r'foo\\\\[^/]*\Z(?ms)') - self.assertEqual(_glob_to_re(r'foo\\\*'), r'foo\\\\\\[^/]*\Z(?ms)') - self.assertEqual(_glob_to_re('foo????'), r'foo[^/][^/][^/][^/]\Z(?ms)') - self.assertEqual(_glob_to_re(r'foo\\??'), r'foo\\\\[^/][^/]\Z(?ms)') + 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 + # files must be sorted beforehand (like sdist does) manifest.sort() manifest.remove_duplicates() self.assertEqual(manifest.files, ['a', 'b', 'c', 'g']) @@ -143,6 +210,7 @@ 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', @@ -153,7 +221,7 @@ # implicit include manifest = Manifest() - manifest.allfiles = ['a.py', 'b.txt', 'd/c.py'] + manifest.allfiles = ['a.py', 'b.txt', l('d/c.py')] manifest._process_template_line('*.py') self.assertEqual(manifest.files, ['a.py']) @@ -161,7 +229,7 @@ # include manifest = Manifest() - manifest.allfiles = ['a.py', 'b.txt', 'd/c.py'] + manifest.allfiles = ['a.py', 'b.txt', l('d/c.py')] manifest._process_template_line('include *.py') self.assertEqual(manifest.files, ['a.py']) @@ -173,31 +241,31 @@ # exclude manifest = Manifest() - manifest.files = ['a.py', 'b.txt', 'd/c.py'] + manifest.files = ['a.py', 'b.txt', l('d/c.py')] manifest._process_template_line('exclude *.py') - self.assertEqual(manifest.files, ['b.txt', 'd/c.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', 'd/c.py']) + self.assertEqual(manifest.files, ['b.txt', l('d/c.py')]) self.assertWarnings() # global-include manifest = Manifest() - manifest.allfiles = ['a.py', 'b.txt', 'd/c.py'] + manifest.allfiles = ['a.py', 'b.txt', l('d/c.py')] manifest._process_template_line('global-include *.py') - self.assertEqual(manifest.files, ['a.py', 'd/c.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', 'd/c.py']) + self.assertEqual(manifest.files, ['a.py', l('d/c.py')]) self.assertWarnings() # global-exclude manifest = Manifest() - manifest.files = ['a.py', 'b.txt', 'd/c.py'] + manifest.files = ['a.py', 'b.txt', l('d/c.py')] manifest._process_template_line('global-exclude *.py') self.assertEqual(manifest.files, ['b.txt']) @@ -209,50 +277,50 @@ # recursive-include manifest = Manifest() - manifest.allfiles = ['a.py', 'd/b.py', 'd/c.txt', 'd/d/e.py'] + 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, ['d/b.py', 'd/d/e.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, ['d/b.py', 'd/d/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', 'd/b.py', 'd/c.txt', 'd/d/e.py'] + 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', 'd/c.txt']) + 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', 'd/c.txt']) + self.assertEqual(manifest.files, ['a.py', l('d/c.txt')]) self.assertWarnings() # graft manifest = Manifest() - manifest.allfiles = ['a.py', 'd/b.py', 'd/d/e.py', 'f/f.py'] + 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, ['d/b.py', 'd/d/e.py']) + 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, ['d/b.py', 'd/d/e.py']) + self.assertEqual(manifest.files, [l('d/b.py'), l('d/d/e.py')]) self.assertWarnings() # prune manifest = Manifest() - manifest.files = ['a.py', 'd/b.py', 'd/d/e.py', 'f/f.py'] + 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', 'f/f.py']) + self.assertEqual(manifest.files, ['a.py', l('f/f.py')]) self.assertNoWarnings() manifest._process_template_line('prune e') - self.assertEqual(manifest.files, ['a.py', 'f/f.py']) + self.assertEqual(manifest.files, ['a.py', l('f/f.py')]) self.assertWarnings() diff --git a/distutils2/tests/test_util.py b/distutils2/tests/test_util.py --- a/distutils2/tests/test_util.py +++ b/distutils2/tests/test_util.py @@ -173,6 +173,11 @@ sys.stdout = self.old_stdout sys.stderr = self.old_stderr + def test_set_platform(self): + self.addCleanup(util.set_platform, util.get_platform()) + util.set_platform("fake") + self.assertEqual("fake", util.get_platform()) + def test_convert_path(self): # linux/mac os.sep = '/' diff --git a/distutils2/tests/test_version.py b/distutils2/tests/test_version.py --- a/distutils2/tests/test_version.py +++ b/distutils2/tests/test_version.py @@ -16,6 +16,7 @@ (V('1.2'), '1.2'), (V('1.2.3a4'), '1.2.3a4'), (V('1.2c4'), '1.2c4'), + (V('4.17rc2'), '4.17rc2'), (V('1.2.3.4'), '1.2.3.4'), (V('1.2.3.4.0b3'), '1.2.3.4b3'), (V('1.2.0.0.0'), '1.2'), @@ -146,6 +147,14 @@ """ doctest.script_from_examples(comparison_doctest_string) + # the doctest above is never run, so temporarily add real unit + # tests until the doctest is rewritten + self.assertLessEqual(V('1.2.0rc1'), V('1.2.0')) + self.assertGreater(V('1.0'), V('1.0c2')) + self.assertGreater(V('1.0'), V('1.0rc2')) + self.assertGreater(V('1.0rc2'), V('1.0rc1')) + self.assertGreater(V('1.0c4'), V('1.0c1')) + def test_suggest_normalized_version(self): self.assertEqual(suggest('1.0'), '1.0') diff --git a/distutils2/version.py b/distutils2/version.py --- a/distutils2/version.py +++ b/distutils2/version.py @@ -11,19 +11,20 @@ # A marker used in the second and third parts of the `parts` tuple, for # versions that don't have those segments, to sort properly. An example # of versions in sort order ('highest' last): -# 1.0b1 ((1,0), ('b',1), ('f',)) -# 1.0.dev345 ((1,0), ('f',), ('dev', 345)) -# 1.0 ((1,0), ('f',), ('f',)) -# 1.0.post256.dev345 ((1,0), ('f',), ('f', 'post', 256, 'dev', 345)) -# 1.0.post345 ((1,0), ('f',), ('f', 'post', 345, 'f')) +# 1.0b1 ((1,0), ('b',1), ('z',)) +# 1.0.dev345 ((1,0), ('z',), ('dev', 345)) +# 1.0 ((1,0), ('z',), ('z',)) +# 1.0.post256.dev345 ((1,0), ('z',), ('z', 'post', 256, 'dev', 345)) +# 1.0.post345 ((1,0), ('z',), ('z', 'post', 345, 'z')) # ^ ^ ^ -# 'b' < 'f' ---------------------/ | | +# 'b' < 'z' ---------------------/ | | # | | -# 'dev' < 'f' < 'post' -------------------/ | +# 'dev' < 'z' ----------------------------/ | # | -# 'dev' < 'f' ----------------------------------------------/ -# Other letters would do, but 'f' for 'final' is kind of nice. -_FINAL_MARKER = ('f',) +# 'dev' < 'z' ----------------------------------------------/ +# 'f' for 'final' would be kind of nice, but due to bugs in the support of +# 'rc' we must use 'z' +_FINAL_MARKER = ('z',) _VERSION_RE = re.compile(r''' ^ @@ -167,8 +168,9 @@ if prerel is not _FINAL_MARKER: s += prerel[0] s += '.'.join(str(v) for v in prerel[1:]) + # XXX clean up: postdev is always true; code is obscure if postdev and postdev is not _FINAL_MARKER: - if postdev[0] == 'f': + if postdev[0] == _FINAL_MARKER[0]: postdev = postdev[1:] i = 0 while i < len(postdev): -- Repository URL: http://hg.python.org/distutils2
participants (1)
-
eric.araujo