mirror of
https://github.com/python/cpython.git
synced 2025-08-01 07:33:08 +00:00
Merge 3.2
This commit is contained in:
commit
c071a613df
4 changed files with 133 additions and 47 deletions
|
@ -201,6 +201,7 @@ class FileList:
|
||||||
|
|
||||||
Return True if files are found, False otherwise.
|
Return True if files are found, False otherwise.
|
||||||
"""
|
"""
|
||||||
|
# XXX docstring lying about what the special chars are?
|
||||||
files_found = False
|
files_found = False
|
||||||
pattern_re = translate_pattern(pattern, anchor, prefix, is_regex)
|
pattern_re = translate_pattern(pattern, anchor, prefix, is_regex)
|
||||||
self.debug_print("include_pattern: applying regex r'%s'" %
|
self.debug_print("include_pattern: applying regex r'%s'" %
|
||||||
|
@ -284,11 +285,14 @@ def glob_to_re(pattern):
|
||||||
# IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix,
|
# IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix,
|
||||||
# and by extension they shouldn't match such "special characters" under
|
# 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
|
# any OS. So change all non-escaped dots in the RE to match any
|
||||||
# character except the special characters.
|
# character except the special characters (currently: just os.sep).
|
||||||
# XXX currently the "special characters" are just slash -- i.e. this is
|
sep = os.sep
|
||||||
# Unix-only.
|
if os.sep == '\\':
|
||||||
pattern_re = re.sub(r'((?<!\\)(\\\\)*)\.', r'\1[^/]', pattern_re)
|
# 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
|
return pattern_re
|
||||||
|
|
||||||
|
|
||||||
|
@ -312,9 +316,11 @@ def translate_pattern(pattern, anchor=1, prefix=None, is_regex=0):
|
||||||
if prefix is not None:
|
if prefix is not None:
|
||||||
# ditch end of pattern character
|
# ditch end of pattern character
|
||||||
empty_pattern = glob_to_re('')
|
empty_pattern = glob_to_re('')
|
||||||
prefix_re = (glob_to_re(prefix))[:-len(empty_pattern)]
|
prefix_re = glob_to_re(prefix)[:-len(empty_pattern)]
|
||||||
# paths should always use / in manifest templates
|
sep = os.sep
|
||||||
pattern_re = "^%s/.*%s" % (prefix_re, pattern_re)
|
if os.sep == '\\':
|
||||||
|
sep = r'\\'
|
||||||
|
pattern_re = "^" + sep.join((prefix_re, ".*" + pattern_re))
|
||||||
else: # no prefix -- respect anchor flag
|
else: # no prefix -- respect anchor flag
|
||||||
if anchor:
|
if anchor:
|
||||||
pattern_re = "^" + pattern_re
|
pattern_re = "^" + pattern_re
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
"""Tests for distutils.filelist."""
|
"""Tests for distutils.filelist."""
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
import unittest
|
import unittest
|
||||||
from distutils import debug
|
from distutils import debug
|
||||||
|
@ -9,6 +10,26 @@ from distutils.filelist import glob_to_re, translate_pattern, FileList
|
||||||
from test.support import captured_stdout, run_unittest
|
from test.support import captured_stdout, run_unittest
|
||||||
from distutils.tests import support
|
from distutils.tests import 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
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def make_local_path(s):
|
||||||
|
"""Converts '/' in a string to os.sep"""
|
||||||
|
return s.replace('/', os.sep)
|
||||||
|
|
||||||
|
|
||||||
class FileListTestCase(support.LoggingSilencer,
|
class FileListTestCase(support.LoggingSilencer,
|
||||||
unittest.TestCase):
|
unittest.TestCase):
|
||||||
|
@ -22,16 +43,62 @@ class FileListTestCase(support.LoggingSilencer,
|
||||||
self.clear_logs()
|
self.clear_logs()
|
||||||
|
|
||||||
def test_glob_to_re(self):
|
def test_glob_to_re(self):
|
||||||
# simple cases
|
sep = os.sep
|
||||||
self.assertEqual(glob_to_re('foo*'), 'foo[^/]*\\Z(?ms)')
|
if os.sep == '\\':
|
||||||
self.assertEqual(glob_to_re('foo?'), 'foo[^/]\\Z(?ms)')
|
sep = re.escape(os.sep)
|
||||||
self.assertEqual(glob_to_re('foo??'), 'foo[^/][^/]\\Z(?ms)')
|
|
||||||
|
|
||||||
# special cases
|
for glob, regex in (
|
||||||
self.assertEqual(glob_to_re(r'foo\\*'), r'foo\\\\[^/]*\Z(?ms)')
|
# simple cases
|
||||||
self.assertEqual(glob_to_re(r'foo\\\*'), r'foo\\\\\\[^/]*\Z(?ms)')
|
('foo*', r'foo[^%(sep)s]*\Z(?ms)'),
|
||||||
self.assertEqual(glob_to_re('foo????'), r'foo[^/][^/][^/][^/]\Z(?ms)')
|
('foo?', r'foo[^%(sep)s]\Z(?ms)'),
|
||||||
self.assertEqual(glob_to_re(r'foo\\??'), r'foo\\\\[^/][^/]\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
|
||||||
|
file_list = FileList()
|
||||||
|
l = make_local_path
|
||||||
|
|
||||||
|
# simulated file list
|
||||||
|
file_list.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
|
||||||
|
file_list.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(file_list.files, wanted)
|
||||||
|
|
||||||
def test_debug_print(self):
|
def test_debug_print(self):
|
||||||
file_list = FileList()
|
file_list = FileList()
|
||||||
|
@ -117,6 +184,7 @@ class FileListTestCase(support.LoggingSilencer,
|
||||||
self.assertEqual(file_list.allfiles, ['a.py', 'b.txt'])
|
self.assertEqual(file_list.allfiles, ['a.py', 'b.txt'])
|
||||||
|
|
||||||
def test_process_template(self):
|
def test_process_template(self):
|
||||||
|
l = make_local_path
|
||||||
# invalid lines
|
# invalid lines
|
||||||
file_list = FileList()
|
file_list = FileList()
|
||||||
for action in ('include', 'exclude', 'global-include',
|
for action in ('include', 'exclude', 'global-include',
|
||||||
|
@ -127,7 +195,7 @@ class FileListTestCase(support.LoggingSilencer,
|
||||||
|
|
||||||
# include
|
# include
|
||||||
file_list = FileList()
|
file_list = FileList()
|
||||||
file_list.set_allfiles(['a.py', 'b.txt', 'd/c.py'])
|
file_list.set_allfiles(['a.py', 'b.txt', l('d/c.py')])
|
||||||
|
|
||||||
file_list.process_template_line('include *.py')
|
file_list.process_template_line('include *.py')
|
||||||
self.assertEqual(file_list.files, ['a.py'])
|
self.assertEqual(file_list.files, ['a.py'])
|
||||||
|
@ -139,31 +207,31 @@ class FileListTestCase(support.LoggingSilencer,
|
||||||
|
|
||||||
# exclude
|
# exclude
|
||||||
file_list = FileList()
|
file_list = FileList()
|
||||||
file_list.files = ['a.py', 'b.txt', 'd/c.py']
|
file_list.files = ['a.py', 'b.txt', l('d/c.py')]
|
||||||
|
|
||||||
file_list.process_template_line('exclude *.py')
|
file_list.process_template_line('exclude *.py')
|
||||||
self.assertEqual(file_list.files, ['b.txt', 'd/c.py'])
|
self.assertEqual(file_list.files, ['b.txt', l('d/c.py')])
|
||||||
self.assertNoWarnings()
|
self.assertNoWarnings()
|
||||||
|
|
||||||
file_list.process_template_line('exclude *.rb')
|
file_list.process_template_line('exclude *.rb')
|
||||||
self.assertEqual(file_list.files, ['b.txt', 'd/c.py'])
|
self.assertEqual(file_list.files, ['b.txt', l('d/c.py')])
|
||||||
self.assertWarnings()
|
self.assertWarnings()
|
||||||
|
|
||||||
# global-include
|
# global-include
|
||||||
file_list = FileList()
|
file_list = FileList()
|
||||||
file_list.set_allfiles(['a.py', 'b.txt', 'd/c.py'])
|
file_list.set_allfiles(['a.py', 'b.txt', l('d/c.py')])
|
||||||
|
|
||||||
file_list.process_template_line('global-include *.py')
|
file_list.process_template_line('global-include *.py')
|
||||||
self.assertEqual(file_list.files, ['a.py', 'd/c.py'])
|
self.assertEqual(file_list.files, ['a.py', l('d/c.py')])
|
||||||
self.assertNoWarnings()
|
self.assertNoWarnings()
|
||||||
|
|
||||||
file_list.process_template_line('global-include *.rb')
|
file_list.process_template_line('global-include *.rb')
|
||||||
self.assertEqual(file_list.files, ['a.py', 'd/c.py'])
|
self.assertEqual(file_list.files, ['a.py', l('d/c.py')])
|
||||||
self.assertWarnings()
|
self.assertWarnings()
|
||||||
|
|
||||||
# global-exclude
|
# global-exclude
|
||||||
file_list = FileList()
|
file_list = FileList()
|
||||||
file_list.files = ['a.py', 'b.txt', 'd/c.py']
|
file_list.files = ['a.py', 'b.txt', l('d/c.py')]
|
||||||
|
|
||||||
file_list.process_template_line('global-exclude *.py')
|
file_list.process_template_line('global-exclude *.py')
|
||||||
self.assertEqual(file_list.files, ['b.txt'])
|
self.assertEqual(file_list.files, ['b.txt'])
|
||||||
|
@ -175,50 +243,52 @@ class FileListTestCase(support.LoggingSilencer,
|
||||||
|
|
||||||
# recursive-include
|
# recursive-include
|
||||||
file_list = FileList()
|
file_list = FileList()
|
||||||
file_list.set_allfiles(['a.py', 'd/b.py', 'd/c.txt', 'd/d/e.py'])
|
file_list.set_allfiles(['a.py', l('d/b.py'), l('d/c.txt'),
|
||||||
|
l('d/d/e.py')])
|
||||||
|
|
||||||
file_list.process_template_line('recursive-include d *.py')
|
file_list.process_template_line('recursive-include d *.py')
|
||||||
self.assertEqual(file_list.files, ['d/b.py', 'd/d/e.py'])
|
self.assertEqual(file_list.files, [l('d/b.py'), l('d/d/e.py')])
|
||||||
self.assertNoWarnings()
|
self.assertNoWarnings()
|
||||||
|
|
||||||
file_list.process_template_line('recursive-include e *.py')
|
file_list.process_template_line('recursive-include e *.py')
|
||||||
self.assertEqual(file_list.files, ['d/b.py', 'd/d/e.py'])
|
self.assertEqual(file_list.files, [l('d/b.py'), l('d/d/e.py')])
|
||||||
self.assertWarnings()
|
self.assertWarnings()
|
||||||
|
|
||||||
# recursive-exclude
|
# recursive-exclude
|
||||||
file_list = FileList()
|
file_list = FileList()
|
||||||
file_list.files = ['a.py', 'd/b.py', 'd/c.txt', 'd/d/e.py']
|
file_list.files = ['a.py', l('d/b.py'), l('d/c.txt'), l('d/d/e.py')]
|
||||||
|
|
||||||
file_list.process_template_line('recursive-exclude d *.py')
|
file_list.process_template_line('recursive-exclude d *.py')
|
||||||
self.assertEqual(file_list.files, ['a.py', 'd/c.txt'])
|
self.assertEqual(file_list.files, ['a.py', l('d/c.txt')])
|
||||||
self.assertNoWarnings()
|
self.assertNoWarnings()
|
||||||
|
|
||||||
file_list.process_template_line('recursive-exclude e *.py')
|
file_list.process_template_line('recursive-exclude e *.py')
|
||||||
self.assertEqual(file_list.files, ['a.py', 'd/c.txt'])
|
self.assertEqual(file_list.files, ['a.py', l('d/c.txt')])
|
||||||
self.assertWarnings()
|
self.assertWarnings()
|
||||||
|
|
||||||
# graft
|
# graft
|
||||||
file_list = FileList()
|
file_list = FileList()
|
||||||
file_list.set_allfiles(['a.py', 'd/b.py', 'd/d/e.py', 'f/f.py'])
|
file_list.set_allfiles(['a.py', l('d/b.py'), l('d/d/e.py'),
|
||||||
|
l('f/f.py')])
|
||||||
|
|
||||||
file_list.process_template_line('graft d')
|
file_list.process_template_line('graft d')
|
||||||
self.assertEqual(file_list.files, ['d/b.py', 'd/d/e.py'])
|
self.assertEqual(file_list.files, [l('d/b.py'), l('d/d/e.py')])
|
||||||
self.assertNoWarnings()
|
self.assertNoWarnings()
|
||||||
|
|
||||||
file_list.process_template_line('graft e')
|
file_list.process_template_line('graft e')
|
||||||
self.assertEqual(file_list.files, ['d/b.py', 'd/d/e.py'])
|
self.assertEqual(file_list.files, [l('d/b.py'), l('d/d/e.py')])
|
||||||
self.assertWarnings()
|
self.assertWarnings()
|
||||||
|
|
||||||
# prune
|
# prune
|
||||||
file_list = FileList()
|
file_list = FileList()
|
||||||
file_list.files = ['a.py', 'd/b.py', 'd/d/e.py', 'f/f.py']
|
file_list.files = ['a.py', l('d/b.py'), l('d/d/e.py'), l('f/f.py')]
|
||||||
|
|
||||||
file_list.process_template_line('prune d')
|
file_list.process_template_line('prune d')
|
||||||
self.assertEqual(file_list.files, ['a.py', 'f/f.py'])
|
self.assertEqual(file_list.files, ['a.py', l('f/f.py')])
|
||||||
self.assertNoWarnings()
|
self.assertNoWarnings()
|
||||||
|
|
||||||
file_list.process_template_line('prune e')
|
file_list.process_template_line('prune e')
|
||||||
self.assertEqual(file_list.files, ['a.py', 'f/f.py'])
|
self.assertEqual(file_list.files, ['a.py', l('f/f.py')])
|
||||||
self.assertWarnings()
|
self.assertWarnings()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,12 @@ import zipfile
|
||||||
from os.path import join
|
from os.path import join
|
||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
|
|
||||||
|
try:
|
||||||
|
import zlib
|
||||||
|
ZLIB_SUPPORT = True
|
||||||
|
except ImportError:
|
||||||
|
ZLIB_SUPPORT = False
|
||||||
|
|
||||||
from test.support import captured_stdout, check_warnings, run_unittest
|
from test.support import captured_stdout, check_warnings, run_unittest
|
||||||
|
|
||||||
from distutils.command.sdist import sdist, show_formats
|
from distutils.command.sdist import sdist, show_formats
|
||||||
|
@ -28,6 +34,7 @@ setup(name='fake')
|
||||||
MANIFEST = """\
|
MANIFEST = """\
|
||||||
# file GENERATED by distutils, do NOT edit
|
# file GENERATED by distutils, do NOT edit
|
||||||
README
|
README
|
||||||
|
buildout.cfg
|
||||||
inroot.txt
|
inroot.txt
|
||||||
setup.py
|
setup.py
|
||||||
data%(sep)sdata.dt
|
data%(sep)sdata.dt
|
||||||
|
@ -39,13 +46,6 @@ somecode%(sep)sdoc.dat
|
||||||
somecode%(sep)sdoc.txt
|
somecode%(sep)sdoc.txt
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
|
||||||
import zlib
|
|
||||||
ZLIB_SUPPORT = True
|
|
||||||
except ImportError:
|
|
||||||
ZLIB_SUPPORT = False
|
|
||||||
|
|
||||||
|
|
||||||
class SDistTestCase(PyPIRCCommandTestCase):
|
class SDistTestCase(PyPIRCCommandTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -143,7 +143,7 @@ class SDistTestCase(PyPIRCCommandTestCase):
|
||||||
dist_folder = join(self.tmp_dir, 'dist')
|
dist_folder = join(self.tmp_dir, 'dist')
|
||||||
result = os.listdir(dist_folder)
|
result = os.listdir(dist_folder)
|
||||||
result.sort()
|
result.sort()
|
||||||
self.assertEqual(result, ['fake-1.0.tar', 'fake-1.0.tar.gz'] )
|
self.assertEqual(result, ['fake-1.0.tar', 'fake-1.0.tar.gz'])
|
||||||
|
|
||||||
os.remove(join(dist_folder, 'fake-1.0.tar'))
|
os.remove(join(dist_folder, 'fake-1.0.tar'))
|
||||||
os.remove(join(dist_folder, 'fake-1.0.tar.gz'))
|
os.remove(join(dist_folder, 'fake-1.0.tar.gz'))
|
||||||
|
@ -180,11 +180,18 @@ class SDistTestCase(PyPIRCCommandTestCase):
|
||||||
self.write_file((data_dir, 'data.dt'), '#')
|
self.write_file((data_dir, 'data.dt'), '#')
|
||||||
some_dir = join(self.tmp_dir, 'some')
|
some_dir = join(self.tmp_dir, 'some')
|
||||||
os.mkdir(some_dir)
|
os.mkdir(some_dir)
|
||||||
|
# make sure VCS directories are pruned (#14004)
|
||||||
|
hg_dir = join(self.tmp_dir, '.hg')
|
||||||
|
os.mkdir(hg_dir)
|
||||||
|
self.write_file((hg_dir, 'last-message.txt'), '#')
|
||||||
|
# a buggy regex used to prevent this from working on windows (#6884)
|
||||||
|
self.write_file((self.tmp_dir, 'buildout.cfg'), '#')
|
||||||
self.write_file((self.tmp_dir, 'inroot.txt'), '#')
|
self.write_file((self.tmp_dir, 'inroot.txt'), '#')
|
||||||
self.write_file((some_dir, 'file.txt'), '#')
|
self.write_file((some_dir, 'file.txt'), '#')
|
||||||
self.write_file((some_dir, 'other_file.txt'), '#')
|
self.write_file((some_dir, 'other_file.txt'), '#')
|
||||||
|
|
||||||
dist.data_files = [('data', ['data/data.dt',
|
dist.data_files = [('data', ['data/data.dt',
|
||||||
|
'buildout.cfg',
|
||||||
'inroot.txt',
|
'inroot.txt',
|
||||||
'notexisting']),
|
'notexisting']),
|
||||||
'some/file.txt',
|
'some/file.txt',
|
||||||
|
@ -214,15 +221,15 @@ class SDistTestCase(PyPIRCCommandTestCase):
|
||||||
zip_file.close()
|
zip_file.close()
|
||||||
|
|
||||||
# making sure everything was added
|
# making sure everything was added
|
||||||
self.assertEqual(len(content), 11)
|
self.assertEqual(len(content), 12)
|
||||||
|
|
||||||
# checking the MANIFEST
|
# checking the MANIFEST
|
||||||
f = open(join(self.tmp_dir, 'MANIFEST'))
|
f = open(join(self.tmp_dir, 'MANIFEST'))
|
||||||
try:
|
try:
|
||||||
manifest = f.read()
|
manifest = f.read()
|
||||||
self.assertEqual(manifest, MANIFEST % {'sep': os.sep})
|
|
||||||
finally:
|
finally:
|
||||||
f.close()
|
f.close()
|
||||||
|
self.assertEqual(manifest, MANIFEST % {'sep': os.sep})
|
||||||
|
|
||||||
@unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
|
@unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
|
||||||
def test_metadata_check_option(self):
|
def test_metadata_check_option(self):
|
||||||
|
|
|
@ -498,6 +498,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #6884: Fix long-standing bugs with MANIFEST.in parsing in distutils
|
||||||
|
on Windows.
|
||||||
|
|
||||||
- Issue #8033: sqlite3: Fix 64-bit integer handling in user functions
|
- Issue #8033: sqlite3: Fix 64-bit integer handling in user functions
|
||||||
on 32-bit architectures. Initial patch by Philippe Devalkeneer.
|
on 32-bit architectures. Initial patch by Philippe Devalkeneer.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue