distutils2: 7d1a7251d771 (original) (raw)
--- a/CHANGES.txt +++ b/CHANGES.txt @@ -166,6 +166,9 @@ 1.0a4 - 2012-02-?? 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
--- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -69,3 +69,4 @@ Thanks to:
--- a/distutils2/manifest.py +++ b/distutils2/manifest.py @@ -272,6 +272,7 @@ class Manifest: Return True if files are found. """
# XXX docstring lying about what the special chars are?[](#l3.7) files_found = False[](#l3.8) pattern_re = _translate_pattern(pattern, anchor, prefix, is_regex)[](#l3.9)
@@ -335,11 +336,14 @@ def _glob_to_re(pattern): # 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[](#l3.23)
# to escape the backslash twice[](#l3.24)
sep = r'\\\\'[](#l3.25)
- escaped = r'\1[^%s]' % sep
- pattern_re = re.sub(r'((?<!\)(\\)*).', escaped, pattern_re) return pattern_re @@ -366,7 +370,10 @@ def _translate_pattern(pattern, anchor=T # 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)[](#l3.35)
sep = os.sep[](#l3.36)
if os.sep == '\\':[](#l3.37)
sep = r'\\'[](#l3.38)
else: # no prefix -- respect anchor flag if anchor: pattern_re = "^" + pattern_repattern_re = "^" + sep.join((prefix_re, ".*" + pattern_re))[](#l3.39)
--- a/distutils2/tests/fixer/init.py +++ b/distutils2/tests/fixer/init.py @@ -0,0 +1,1 @@ +"""Example fixers used in tests."""
--- a/distutils2/tests/test_command_build_ext.py +++ b/distutils2/tests/test_command_build_ext.py @@ -150,7 +150,8 @@ class BuildExtTestCase(support.TempdirMa 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'])[](#l5.7)
self.assertIn('my_lib_dir', cmd.library_dirs)[](#l5.8)
self.assertIn('other_lib_dir', cmd.library_dirs)[](#l5.9)
# make sure rpath is turned into a list # if it's a string
--- a/distutils2/tests/test_manifest.py +++ b/distutils2/tests/test_manifest.py @@ -7,7 +7,22 @@ from distutils2.manifest import Manifest from distutils2.tests import unittest, support -_MANIFEST = """[](#l6.7) +MANIFEST_IN = """[](#l6.8) +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 = """[](#l6.23) recursive-include foo *.py # ok
nothing here
@@ -17,12 +32,17 @@ recursive-include bar \ *.dat *.txt """ -_MANIFEST2 = """[](#l6.31) +MANIFEST_IN_3 = """[](#l6.32) README file1 """ +def make_local_path(s):
+ + class ManifestTestCase(support.TempdirManager, support.LoggingCatcher, unittest.TestCase): @@ -37,7 +57,7 @@ class ManifestTestCase(support.TempdirMa tmpdir = self.mkdtemp() MANIFEST = os.path.join(tmpdir, 'MANIFEST.in') with open(MANIFEST, 'w') as f:
f.write(_MANIFEST)[](#l6.50)
f.write(MANIFEST_IN_2)[](#l6.51)
manifest = Manifest() manifest.read_template(MANIFEST) @@ -63,27 +83,74 @@ class ManifestTestCase(support.TempdirMa os.chdir(tmpdir) self.write_file('README', 'xxx') self.write_file('file1', 'xxx')
content = StringIO(_MANIFEST2)[](#l6.59)
content = StringIO(MANIFEST_IN_3)[](#l6.60) manifest = Manifest()[](#l6.61) manifest.read_template(content)[](#l6.62) self.assertEqual(['README', 'file1'], manifest.files)[](#l6.63)
# simple cases[](#l6.66)
self.assertEqual(_glob_to_re('foo*'), 'foo[^/]*\\Z(?ms)')[](#l6.67)
self.assertEqual(_glob_to_re('foo?'), 'foo[^/]\\Z(?ms)')[](#l6.68)
self.assertEqual(_glob_to_re('foo??'), 'foo[^/][^/]\\Z(?ms)')[](#l6.69)
sep = os.sep[](#l6.70)
if os.sep == '\\':[](#l6.71)
sep = r'\\'[](#l6.72)
for glob, regex in ([](#l6.74)
# simple cases[](#l6.75)
('foo*', r'foo[^%(sep)s]*\Z(?ms)'),[](#l6.76)
('foo?', r'foo[^%(sep)s]\Z(?ms)'),[](#l6.77)
('foo??', r'foo[^%(sep)s][^%(sep)s]\Z(?ms)'),[](#l6.78)
# special cases[](#l6.79)
(r'foo\\*', r'foo\\\\[^%(sep)s]*\Z(?ms)'),[](#l6.80)
(r'foo\\\*', r'foo\\\\\\[^%(sep)s]*\Z(?ms)'),[](#l6.81)
('foo????', r'foo[^%(sep)s][^%(sep)s][^%(sep)s][^%(sep)s]\Z(?ms)'),[](#l6.82)
(r'foo\\??', r'foo\\\\[^%(sep)s][^%(sep)s]\Z(?ms)'),[](#l6.83)
):[](#l6.84)
regex = regex % {'sep': sep}[](#l6.85)
self.assertEqual(_glob_to_re(glob), regex)[](#l6.86)
- def test_process_template_line(self):
# testing all MANIFEST.in template patterns[](#l6.89)
manifest = Manifest()[](#l6.90)
l = make_local_path[](#l6.91)
# special cases[](#l6.93)
self.assertEqual(_glob_to_re(r'foo\\*'), r'foo\\\\[^/]*\Z(?ms)')[](#l6.94)
self.assertEqual(_glob_to_re(r'foo\\\*'), r'foo\\\\\\[^/]*\Z(?ms)')[](#l6.95)
self.assertEqual(_glob_to_re('foo????'), r'foo[^/][^/][^/][^/]\Z(?ms)')[](#l6.96)
self.assertEqual(_glob_to_re(r'foo\\??'), r'foo\\\\[^/][^/]\Z(?ms)')[](#l6.97)
# simulated file list[](#l6.98)
manifest.allfiles = ['foo.tmp', 'ok', 'xo', 'four.txt',[](#l6.99)
'buildout.cfg',[](#l6.100)
# filelist does not filter out VCS directories,[](#l6.101)
# it's sdist that does[](#l6.102)
l('.hg/last-message.txt'),[](#l6.103)
l('global/one.txt'),[](#l6.104)
l('global/two.txt'),[](#l6.105)
l('global/files.x'),[](#l6.106)
l('global/here.tmp'),[](#l6.107)
l('f/o/f.oo'),[](#l6.108)
l('dir/graft-one'),[](#l6.109)
l('dir/dir2/graft2'),[](#l6.110)
l('dir3/ok'),[](#l6.111)
l('dir3/sub/ok.txt'),[](#l6.112)
][](#l6.113)
for line in MANIFEST_IN.split('\n'):[](#l6.115)
if line.strip() == '':[](#l6.116)
continue[](#l6.117)
manifest._process_template_line(line)[](#l6.118)
wanted = ['ok',[](#l6.120)
'buildout.cfg',[](#l6.121)
'four.txt',[](#l6.122)
l('.hg/last-message.txt'),[](#l6.123)
l('global/one.txt'),[](#l6.124)
l('global/two.txt'),[](#l6.125)
l('f/o/f.oo'),[](#l6.126)
l('dir/graft-one'),[](#l6.127)
l('dir/dir2/graft2'),[](#l6.128)
][](#l6.129)
self.assertEqual(manifest.files, wanted)[](#l6.131)
def test_remove_duplicates(self): manifest = Manifest() manifest.files = ['a', 'b', 'a', 'g', 'c', 'g']
# files must be sorted beforehand[](#l6.136)
# files must be sorted beforehand (like sdist does)[](#l6.137) manifest.sort()[](#l6.138) manifest.remove_duplicates()[](#l6.139) self.assertEqual(manifest.files, ['a', 'b', 'c', 'g'])[](#l6.140)
@@ -143,6 +210,7 @@ class ManifestTestCase(support.TempdirMa self.assertEqual(manifest.allfiles, ['a.py', 'b.txt']) def test_process_template(self):
l = make_local_path[](#l6.145) # invalid lines[](#l6.146) manifest = Manifest()[](#l6.147) for action in ('include', 'exclude', 'global-include',[](#l6.148)
@@ -153,7 +221,7 @@ class ManifestTestCase(support.TempdirMa # implicit include manifest = Manifest()
manifest.allfiles = ['a.py', 'b.txt', 'd/c.py'][](#l6.153)
manifest.allfiles = ['a.py', 'b.txt', l('d/c.py')][](#l6.154)
manifest._process_template_line('*.py') self.assertEqual(manifest.files, ['a.py']) @@ -161,7 +229,7 @@ class ManifestTestCase(support.TempdirMa # include manifest = Manifest()
manifest.allfiles = ['a.py', 'b.txt', 'd/c.py'][](#l6.162)
manifest.allfiles = ['a.py', 'b.txt', l('d/c.py')][](#l6.163)
manifest._process_template_line('include *.py') self.assertEqual(manifest.files, ['a.py']) @@ -173,31 +241,31 @@ class ManifestTestCase(support.TempdirMa # exclude manifest = Manifest()
manifest.files = ['a.py', 'b.txt', 'd/c.py'][](#l6.171)
manifest.files = ['a.py', 'b.txt', l('d/c.py')][](#l6.172)
manifest._process_template_line('exclude *.py')
self.assertEqual(manifest.files, ['b.txt', 'd/c.py'])[](#l6.175)
self.assertEqual(manifest.files, ['b.txt', l('d/c.py')])[](#l6.176) self.assertNoWarnings()[](#l6.177)
manifest._process_template_line('exclude *.rb')
self.assertEqual(manifest.files, ['b.txt', 'd/c.py'])[](#l6.180)
self.assertEqual(manifest.files, ['b.txt', l('d/c.py')])[](#l6.181) self.assertWarnings()[](#l6.182)
# global-include manifest = Manifest()
manifest.allfiles = ['a.py', 'b.txt', 'd/c.py'][](#l6.186)
manifest.allfiles = ['a.py', 'b.txt', l('d/c.py')][](#l6.187)
manifest._process_template_line('global-include *.py')
self.assertEqual(manifest.files, ['a.py', 'd/c.py'])[](#l6.190)
self.assertEqual(manifest.files, ['a.py', l('d/c.py')])[](#l6.191) self.assertNoWarnings()[](#l6.192)
manifest._process_template_line('global-include *.rb')
self.assertEqual(manifest.files, ['a.py', 'd/c.py'])[](#l6.195)
self.assertEqual(manifest.files, ['a.py', l('d/c.py')])[](#l6.196) self.assertWarnings()[](#l6.197)
# global-exclude manifest = Manifest()
manifest.files = ['a.py', 'b.txt', 'd/c.py'][](#l6.201)
manifest.files = ['a.py', 'b.txt', l('d/c.py')][](#l6.202)
manifest._process_template_line('global-exclude *.py') self.assertEqual(manifest.files, ['b.txt']) @@ -209,50 +277,50 @@ class ManifestTestCase(support.TempdirMa # recursive-include manifest = Manifest()
manifest.allfiles = ['a.py', 'd/b.py', 'd/c.txt', 'd/d/e.py'][](#l6.210)
manifest.allfiles = ['a.py', l('d/b.py'), l('d/c.txt'), l('d/d/e.py')][](#l6.211)
manifest._process_template_line('recursive-include d *.py')
self.assertEqual(manifest.files, ['d/b.py', 'd/d/e.py'])[](#l6.214)
self.assertEqual(manifest.files, [l('d/b.py'), l('d/d/e.py')])[](#l6.215) self.assertNoWarnings()[](#l6.216)
manifest._process_template_line('recursive-include e *.py')
self.assertEqual(manifest.files, ['d/b.py', 'd/d/e.py'])[](#l6.219)
self.assertEqual(manifest.files, [l('d/b.py'), l('d/d/e.py')])[](#l6.220) self.assertWarnings()[](#l6.221)
# recursive-exclude manifest = Manifest()
manifest.files = ['a.py', 'd/b.py', 'd/c.txt', 'd/d/e.py'][](#l6.225)
manifest.files = ['a.py', l('d/b.py'), l('d/c.txt'), l('d/d/e.py')][](#l6.226)
manifest._process_template_line('recursive-exclude d *.py')
self.assertEqual(manifest.files, ['a.py', 'd/c.txt'])[](#l6.229)
self.assertEqual(manifest.files, ['a.py', l('d/c.txt')])[](#l6.230) self.assertNoWarnings()[](#l6.231)
manifest._process_template_line('recursive-exclude e *.py')
self.assertEqual(manifest.files, ['a.py', 'd/c.txt'])[](#l6.234)
self.assertEqual(manifest.files, ['a.py', l('d/c.txt')])[](#l6.235) self.assertWarnings()[](#l6.236)
manifest.allfiles = ['a.py', 'd/b.py', 'd/d/e.py', 'f/f.py'][](#l6.240)
manifest.allfiles = ['a.py', l('d/b.py'), l('d/d/e.py'), l('f/f.py')][](#l6.241)
manifest._process_template_line('graft d')
self.assertEqual(manifest.files, ['d/b.py', 'd/d/e.py'])[](#l6.244)
self.assertEqual(manifest.files, [l('d/b.py'), l('d/d/e.py')])[](#l6.245) self.assertNoWarnings()[](#l6.246)
manifest._process_template_line('graft e')
self.assertEqual(manifest.files, ['d/b.py', 'd/d/e.py'])[](#l6.249)
self.assertEqual(manifest.files, [l('d/b.py'), l('d/d/e.py')])[](#l6.250) self.assertWarnings()[](#l6.251)
manifest.files = ['a.py', 'd/b.py', 'd/d/e.py', 'f/f.py'][](#l6.255)
manifest.files = ['a.py', l('d/b.py'), l('d/d/e.py'), l('f/f.py')][](#l6.256)
manifest._process_template_line('prune d')
self.assertEqual(manifest.files, ['a.py', 'f/f.py'])[](#l6.259)
self.assertEqual(manifest.files, ['a.py', l('f/f.py')])[](#l6.260) self.assertNoWarnings()[](#l6.261)
manifest._process_template_line('prune e')
self.assertEqual(manifest.files, ['a.py', 'f/f.py'])[](#l6.264)
self.assertEqual(manifest.files, ['a.py', l('f/f.py')])[](#l6.265) self.assertWarnings()[](#l6.266)
--- a/distutils2/tests/test_util.py +++ b/distutils2/tests/test_util.py @@ -173,6 +173,11 @@ class UtilTestCase(support.EnvironRestor sys.stdout = self.old_stdout sys.stderr = self.old_stderr
- def test_set_platform(self):
self.addCleanup(util.set_platform, util.get_platform())[](#l7.8)
util.set_platform("fake")[](#l7.9)
self.assertEqual("fake", util.get_platform())[](#l7.10)
+ def test_convert_path(self): # linux/mac os.sep = '/'
--- a/distutils2/tests/test_version.py +++ b/distutils2/tests/test_version.py @@ -16,6 +16,7 @@ class VersionTestCase(unittest.TestCase) (V('1.2'), '1.2'), (V('1.2.3a4'), '1.2.3a4'), (V('1.2c4'), '1.2c4'),
(V('4.17rc2'), '4.17rc2'),[](#l8.7) (V('1.2.3.4'), '1.2.3.4'),[](#l8.8) (V('1.2.3.4.0b3'), '1.2.3.4b3'),[](#l8.9) (V('1.2.0.0.0'), '1.2'),[](#l8.10)
@@ -146,6 +147,14 @@ class VersionTestCase(unittest.TestCase) """ doctest.script_from_examples(comparison_doctest_string)
# the doctest above is never run, so temporarily add real unit[](#l8.15)
# tests until the doctest is rewritten[](#l8.16)
self.assertLessEqual(V('1.2.0rc1'), V('1.2.0'))[](#l8.17)
self.assertGreater(V('1.0'), V('1.0c2'))[](#l8.18)
self.assertGreater(V('1.0'), V('1.0rc2'))[](#l8.19)
self.assertGreater(V('1.0rc2'), V('1.0rc1'))[](#l8.20)
self.assertGreater(V('1.0c4'), V('1.0c1'))[](#l8.21)
+ def test_suggest_normalized_version(self): self.assertEqual(suggest('1.0'), '1.0')
--- a/distutils2/version.py +++ b/distutils2/version.py @@ -11,19 +11,20 @@ from distutils2.errors import Irrational
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 @@ class NormalizedVersion: 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[](#l9.38) if postdev and postdev is not _FINAL_MARKER:[](#l9.39)
if postdev[0] == 'f':[](#l9.40)
if postdev[0] == _FINAL_MARKER[0]:[](#l9.41) postdev = postdev[1:][](#l9.42) i = 0[](#l9.43) while i < len(postdev):[](#l9.44)