diff options
Diffstat (limited to 'setuptools')
| -rw-r--r-- | setuptools/__init__.py | 2 | ||||
| -rwxr-xr-x | setuptools/command/bdist_rpm.py | 8 | ||||
| -rwxr-xr-x | setuptools/command/bdist_wininst.py | 6 | ||||
| -rw-r--r-- | setuptools/command/build_py.py | 20 | ||||
| -rwxr-xr-x | setuptools/command/easy_install.py | 61 | ||||
| -rwxr-xr-x | setuptools/command/egg_info.py | 83 | ||||
| -rw-r--r-- | setuptools/command/install.py | 24 | ||||
| -rw-r--r-- | setuptools/command/install_lib.py | 8 | ||||
| -rwxr-xr-x | setuptools/command/install_scripts.py | 11 | ||||
| -rwxr-xr-x | setuptools/command/register.py | 9 | ||||
| -rwxr-xr-x | setuptools/command/sdist.py | 8 | ||||
| -rw-r--r-- | setuptools/dist.py | 21 | ||||
| -rwxr-xr-x | setuptools/sandbox.py | 2 | ||||
| -rw-r--r-- | setuptools/tests/test_easy_install.py | 7 | ||||
| -rw-r--r-- | setuptools/tests/test_find_packages.py | 25 | ||||
| -rw-r--r-- | setuptools/tests/test_sdist.py | 9 | ||||
| -rw-r--r-- | setuptools/version.py | 2 |
17 files changed, 184 insertions, 122 deletions
diff --git a/setuptools/__init__.py b/setuptools/__init__.py index 8d46b6dd..d99ab2a6 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -78,7 +78,7 @@ class PackageFinder(object): """ Return all dirs in base_path, relative to base_path """ - for root, dirs, files in os.walk(base_path): + for root, dirs, files in os.walk(base_path, followlinks=True): for dir in dirs: yield os.path.relpath(os.path.join(root, dir), base_path) diff --git a/setuptools/command/bdist_rpm.py b/setuptools/command/bdist_rpm.py index c13732fa..99386824 100755 --- a/setuptools/command/bdist_rpm.py +++ b/setuptools/command/bdist_rpm.py @@ -1,6 +1,6 @@ -from distutils.command.bdist_rpm import bdist_rpm as _bdist_rpm +import distutils.command.bdist_rpm as orig -class bdist_rpm(_bdist_rpm): +class bdist_rpm(orig.bdist_rpm): """ Override the default bdist_rpm behavior to do the following: @@ -15,12 +15,12 @@ class bdist_rpm(_bdist_rpm): # ensure distro name is up-to-date self.run_command('egg_info') - _bdist_rpm.run(self) + orig.bdist_rpm.run(self) def _make_spec_file(self): version = self.distribution.get_version() rpmversion = version.replace('-','_') - spec = _bdist_rpm._make_spec_file(self) + spec = orig.bdist_rpm._make_spec_file(self) line23 = '%define version ' + version line24 = '%define version ' + rpmversion spec = [ diff --git a/setuptools/command/bdist_wininst.py b/setuptools/command/bdist_wininst.py index d4d195a0..f9d8d4f0 100755 --- a/setuptools/command/bdist_wininst.py +++ b/setuptools/command/bdist_wininst.py @@ -1,6 +1,6 @@ -from distutils.command.bdist_wininst import bdist_wininst as _bdist_wininst +import distutils.command.bdist_wininst as orig -class bdist_wininst(_bdist_wininst): +class bdist_wininst(orig.bdist_wininst): def reinitialize_command(self, command, reinit_subcommands=0): """ Supplement reinitialize_command to work around @@ -15,6 +15,6 @@ class bdist_wininst(_bdist_wininst): def run(self): self._is_running = True try: - _bdist_wininst.run(self) + orig.bdist_wininst.run(self) finally: self._is_running = False diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py index 1efabc02..53bfb7df 100644 --- a/setuptools/command/build_py.py +++ b/setuptools/command/build_py.py @@ -2,7 +2,7 @@ import os import sys import fnmatch import textwrap -from distutils.command.build_py import build_py as _build_py +import distutils.command.build_py as orig from distutils.util import convert_path from glob import glob @@ -13,7 +13,7 @@ except ImportError: def run_2to3(self, files, doctests=True): "do nothing" -class build_py(_build_py, Mixin2to3): +class build_py(orig.build_py, Mixin2to3): """Enhanced 'build_py' command that includes data files with packages The data files are specified via a 'package_data' argument to 'setup()'. @@ -23,7 +23,7 @@ class build_py(_build_py, Mixin2to3): 'py_modules' and 'packages' in the same setup operation. """ def finalize_options(self): - _build_py.finalize_options(self) + orig.build_py.finalize_options(self) self.package_data = self.distribution.package_data self.exclude_package_data = self.distribution.exclude_package_data or {} if 'data_files' in self.__dict__: del self.__dict__['data_files'] @@ -48,16 +48,16 @@ class build_py(_build_py, Mixin2to3): # Only compile actual .py files, using our base class' idea of what our # output files are. - self.byte_compile(_build_py.get_outputs(self, include_bytecode=0)) + self.byte_compile(orig.build_py.get_outputs(self, include_bytecode=0)) def __getattr__(self, attr): if attr=='data_files': # lazily compute data files self.data_files = files = self._get_data_files() return files - return _build_py.__getattr__(self,attr) + return orig.build_py.__getattr__(self,attr) def build_module(self, module, module_file, package): - outfile, copied = _build_py.build_module(self, module, module_file, package) + outfile, copied = orig.build_py.build_module(self, module, module_file, package) if copied: self.__updated_files.append(outfile) return outfile, copied @@ -140,7 +140,7 @@ class build_py(_build_py, Mixin2to3): needed for the 'install_lib' command to do its job properly, and to generate a correct installation manifest.) """ - return _build_py.get_outputs(self, include_bytecode) + [ + return orig.build_py.get_outputs(self, include_bytecode) + [ os.path.join(build_dir, filename) for package, src_dir, build_dir,filenames in self.data_files for filename in filenames @@ -153,7 +153,7 @@ class build_py(_build_py, Mixin2to3): except KeyError: pass - init_py = _build_py.check_package(self, package, package_dir) + init_py = orig.build_py.check_package(self, package, package_dir) self.packages_checked[package] = init_py if not init_py or not self.distribution.namespace_packages: @@ -179,10 +179,10 @@ class build_py(_build_py, Mixin2to3): def initialize_options(self): self.packages_checked={} - _build_py.initialize_options(self) + orig.build_py.initialize_options(self) def get_package_dir(self, package): - res = _build_py.get_package_dir(self, package) + res = orig.build_py.get_package_dir(self, package) if self.distribution.src_root is not None: return os.path.join(self.distribution.src_root, res) return res diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index de139f2f..a5f324e3 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -646,6 +646,15 @@ Please make the appropriate changes for your system and try again. def process_distribution(self, requirement, dist, deps=True, *info): self.update_pth(dist) self.package_index.add(dist) + # First remove the dist from self.local_index, to avoid problems using + # old cached data in case its underlying file has been replaced. + # + # This is a quick-fix for a zipimporter caching issue in case the dist + # has been implemented as and already loaded from a zip file that got + # replaced later on. For more detailed information see setuptools issue + # #168 at 'http://bitbucket.org/pypa/setuptools/issue/168'. + if dist in self.local_index[dist.key]: + self.local_index.remove(dist) self.local_index.add(dist) self.install_egg_scripts(dist) self.installed_projects[dist.key] = dist @@ -770,7 +779,7 @@ Please make the appropriate changes for your system and try again. f = open(target,"w"+mode) f.write(contents) f.close() - chmod(target, 0x1FF-mask) # 0777 + chmod(target, 0o777-mask) def install_eggs(self, spec, dist_filename, tmpdir): # .egg dirs or files are already built, so just return them @@ -1110,7 +1119,7 @@ See the setuptools documentation for the "develop" command for more info. self.byte_compile(to_compile) if not self.dry_run: for f in to_chmod: - mode = ((os.stat(f)[stat.ST_MODE]) | 0x16D) & 0xFED # 0555, 07755 + mode = ((os.stat(f)[stat.ST_MODE]) | 0o555) & 0o7755 chmod(f, mode) def byte_compile(self, to_compile): @@ -1206,8 +1215,8 @@ Please make the appropriate changes for your system and try again.""" home = convert_path(os.path.expanduser("~")) for name, path in iteritems(self.config_vars): if path.startswith(home) and not os.path.isdir(path): - self.debug_print("os.makedirs('%s', 0700)" % path) - os.makedirs(path, 0x1C0) # 0700 + self.debug_print("os.makedirs('%s', 0o700)" % path) + os.makedirs(path, 0o700) INSTALL_SCHEMES = dict( posix = dict( @@ -1574,20 +1583,34 @@ def auto_chmod(func, arg, exc): reraise(et, (ev[0], ev[1] + (" %s %s" % (func,arg)))) def uncache_zipdir(path): - """Ensure that the importer caches dont have stale info for `path`""" - from zipimport import _zip_directory_cache as zdc - _uncache(path, zdc) - _uncache(path, sys.path_importer_cache) - -def _uncache(path, cache): - if path in cache: - del cache[path] - else: - path = normalize_path(path) - for p in cache: - if normalize_path(p)==path: - del cache[p] - return + """ + Remove any globally cached zip file related data for `path` + + Stale zipimport.zipimporter objects need to be removed when a zip file is + replaced as they contain cached zip file directory information. If they are + asked to get data from their zip file, they will use that cached + information to calculate the data location in the zip file. This calculated + location may be incorrect for the replaced zip file, which may in turn + cause the read operation to either fail or return incorrect data. + + Note we have no way to clear any local caches from here. That is left up to + whomever is in charge of maintaining that cache. + + """ + normalized_path = normalize_path(path) + _uncache(normalized_path, zipimport._zip_directory_cache) + _uncache(normalized_path, sys.path_importer_cache) + +def _uncache(normalized_path, cache): + to_remove = [] + prefix_len = len(normalized_path) + for p in cache: + np = normalize_path(p) + if (np.startswith(normalized_path) and + np[prefix_len:prefix_len + 1] in (os.sep, '')): + to_remove.append(p) + for p in to_remove: + del cache[p] def is_python(text, filename='<string>'): "Is this string a valid Python script?" @@ -1873,7 +1896,7 @@ def rmtree(path, ignore_errors=False, onerror=auto_chmod): onerror(os.rmdir, path, sys.exc_info()) def current_umask(): - tmp = os.umask(0x12) # 022 + tmp = os.umask(0o022) os.umask(tmp) return tmp diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py index df4edff7..2097f2a9 100755 --- a/setuptools/command/egg_info.py +++ b/setuptools/command/egg_info.py @@ -10,7 +10,7 @@ from setuptools import Command import distutils.errors from distutils import log from setuptools.command.sdist import sdist -from setuptools.compat import basestring, unicode +from setuptools.compat import basestring, PY3 from setuptools import svn_utils from distutils.util import convert_path from distutils.filelist import FileList as _FileList @@ -209,21 +209,32 @@ class FileList(_FileList): item = item[:-1] path = convert_path(item) - if sys.version_info >= (3,): - try: - if os.path.exists(path) or os.path.exists(path.encode('utf-8')): - self.files.append(path) - except UnicodeEncodeError: - # Accept UTF-8 filenames even if LANG=C - if os.path.exists(path.encode('utf-8')): - self.files.append(path) - else: - log.warn("'%s' not %s encodable -- skipping", path, - sys.getfilesystemencoding()) - else: - if os.path.exists(path): - self.files.append(path) + if self._safe_path(path): + self.files.append(path) + + def extend(self, paths): + self.files.extend(filter(self._safe_path, paths)) + def _repair(self): + """ + Replace self.files with only safe paths + + Because some owners of FileList manipulate the underlying + ``files`` attribute directly, this method must be called to + repair those paths. + """ + self.files = list(filter(self._safe_path, self.files)) + + def _safe_path(self, path): + if not PY3: + return os.path.exists(path) + + try: + if os.path.exists(path) or os.path.exists(path.encode('utf-8')): + return True + except UnicodeEncodeError: + log.warn("'%s' not %s encodable -- skipping", path, + sys.getfilesystemencoding()) class manifest_maker(sdist): @@ -252,42 +263,15 @@ class manifest_maker(sdist): self.write_manifest() def write_manifest(self): - """Write the file list in 'self.filelist' (presumably as filled in - by 'add_defaults()' and 'read_template()') to the manifest file + """ + Write the file list in 'self.filelist' to the manifest file named by 'self.manifest'. """ + self.filelist._repair() - #if files are byte codes they should be filesystem encoded - fs_enc = sys.getfilesystemencoding() - files = [] - contents = [] - for file in self.filelist.files: - #In order to ensure the encode behaves, must explicitly - #decode non-unicode strings, yet retain original for - #filelist cleanup - if not isinstance(file, unicode): - try: - u_file = file.decode(fs_enc) - except UnicodeDecodeError: - log.warn("'%s' in unexpected encoding -- skipping" % file) - continue - else: - u_file = file - - # The manifest must be UTF-8 encodable. See #303. - try: - u_file.encode("utf-8") - except UnicodeEncodeError: - log.warn("'%s' not UTF-8 encodable -- skipping" % file) - else: - files.append(file) # possibily byte encoded - contents.append(u_file) # unicode only - self.filelist.files = files - - if os.sep!='/': - contents = [f.replace(os.sep,'/') for f in contents] - self.execute(write_file, (self.manifest, contents), - "writing manifest file '%s'" % self.manifest) + files = [f.replace(os.sep, '/') for f in self.filelist.files] + msg = "writing manifest file '%s'" % self.manifest + self.execute(write_file, (self.manifest, files), msg) def warn(self, msg): # suppress missing-file warnings from sdist if not msg.startswith("standard file not found:"): @@ -319,7 +303,8 @@ def write_file(filename, contents): sequence of strings without line terminators) to it. """ contents = "\n".join(contents) - contents = contents.encode("utf-8") + if sys.version_info >= (3,): + contents = contents.encode("utf-8") f = open(filename, "wb") # always write POSIX-style manifest f.write(contents) f.close() diff --git a/setuptools/command/install.py b/setuptools/command/install.py index 1681617f..1f489734 100644 --- a/setuptools/command/install.py +++ b/setuptools/command/install.py @@ -3,18 +3,22 @@ import inspect import glob import warnings import platform -from distutils.command.install import install as _install +import distutils.command.install as orig from distutils.errors import DistutilsArgError -class install(_install): +# Prior to numpy 1.9, NumPy relies on the '_install' name, so provide it for +# now. See https://bitbucket.org/pypa/setuptools/issue/199/ +_install = orig.install + +class install(orig.install): """Use easy_install to install the package, w/dependencies""" - user_options = _install.user_options + [ + user_options = orig.install.user_options + [ ('old-and-unmanageable', None, "Try not to use this!"), ('single-version-externally-managed', None, "used by system package builders to create 'flat' eggs"), ] - boolean_options = _install.boolean_options + [ + boolean_options = orig.install.boolean_options + [ 'old-and-unmanageable', 'single-version-externally-managed', ] new_commands = [ @@ -24,12 +28,12 @@ class install(_install): _nc = dict(new_commands) def initialize_options(self): - _install.initialize_options(self) + orig.install.initialize_options(self) self.old_and_unmanageable = None self.single_version_externally_managed = None def finalize_options(self): - _install.finalize_options(self) + orig.install.finalize_options(self) if self.root: self.single_version_externally_managed = True elif self.single_version_externally_managed: @@ -42,7 +46,7 @@ class install(_install): def handle_extra_path(self): if self.root or self.single_version_externally_managed: # explicit backward-compatibility mode, allow extra_path to work - return _install.handle_extra_path(self) + return orig.install.handle_extra_path(self) # Ignore extra_path when installing an egg (or being run by another # command without --root or --single-version-externally-managed @@ -52,11 +56,11 @@ class install(_install): def run(self): # Explicit request for old-style install? Just do it if self.old_and_unmanageable or self.single_version_externally_managed: - return _install.run(self) + return orig.install.run(self) if not self._called_from_setup(inspect.currentframe()): # Run in backward-compatibility mode to support bdist_* commands. - _install.run(self) + orig.install.run(self) else: self.do_egg_install() @@ -113,5 +117,5 @@ class install(_install): # XXX Python 3.1 doesn't see _nc if this is inside the class install.sub_commands = [ - cmd for cmd in _install.sub_commands if cmd[0] not in install._nc + cmd for cmd in orig.install.sub_commands if cmd[0] not in install._nc ] + install.new_commands diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index 63dc11fe..747fbabb 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -1,7 +1,7 @@ -from distutils.command.install_lib import install_lib as _install_lib +import distutils.command.install_lib as orig import os -class install_lib(_install_lib): +class install_lib(orig.install_lib): """Don't add compiled flags to filenames of non-Python files""" def run(self): @@ -34,7 +34,7 @@ class install_lib(_install_lib): exclude = self.get_exclusions() if not exclude: - return _install_lib.copy_tree(self, infile, outfile) + return orig.install_lib.copy_tree(self, infile, outfile) # Exclude namespace package __init__.py* files from the output @@ -56,7 +56,7 @@ class install_lib(_install_lib): return outfiles def get_outputs(self): - outputs = _install_lib.get_outputs(self) + outputs = orig.install_lib.get_outputs(self) exclude = self.get_exclusions() if exclude: return [f for f in outputs if f not in exclude] diff --git a/setuptools/command/install_scripts.py b/setuptools/command/install_scripts.py index 1c6cc51d..ac373193 100755 --- a/setuptools/command/install_scripts.py +++ b/setuptools/command/install_scripts.py @@ -1,14 +1,13 @@ -from distutils.command.install_scripts import install_scripts \ - as _install_scripts +import distutils.command.install_scripts as orig from pkg_resources import Distribution, PathMetadata, ensure_directory import os from distutils import log -class install_scripts(_install_scripts): +class install_scripts(orig.install_scripts): """Do normal script install, plus any egg_info wrapper scripts""" def initialize_options(self): - _install_scripts.initialize_options(self) + orig.install_scripts.initialize_options(self) self.no_ep = False def run(self): @@ -17,7 +16,7 @@ class install_scripts(_install_scripts): self.run_command("egg_info") if self.distribution.scripts: - _install_scripts.run(self) # run first to set up self.outfiles + orig.install_scripts.run(self) # run first to set up self.outfiles else: self.outfiles = [] if self.no_ep: @@ -50,4 +49,4 @@ class install_scripts(_install_scripts): f = open(target,"w"+mode) f.write(contents) f.close() - chmod(target, 0x1FF-mask) # 0777 + chmod(target, 0o777-mask) diff --git a/setuptools/command/register.py b/setuptools/command/register.py index 3b2e0859..6694d1c0 100755 --- a/setuptools/command/register.py +++ b/setuptools/command/register.py @@ -1,10 +1,9 @@ -from distutils.command.register import register as _register +import distutils.command.register as orig -class register(_register): - __doc__ = _register.__doc__ +class register(orig.register): + __doc__ = orig.register.__doc__ def run(self): # Make sure that we are using valid current name/version info self.run_command('egg_info') - _register.run(self) - + orig.register.run(self) diff --git a/setuptools/command/sdist.py b/setuptools/command/sdist.py index 76e1c5f1..948d27fa 100755 --- a/setuptools/command/sdist.py +++ b/setuptools/command/sdist.py @@ -4,7 +4,7 @@ import sys from glob import glob import pkg_resources -from distutils.command.sdist import sdist as _sdist +import distutils.command.sdist as orig from distutils.util import convert_path from distutils import log from setuptools import svn_utils @@ -72,7 +72,7 @@ finders = [ ] -class sdist(_sdist): +class sdist(orig.sdist): """Smart sdist that finds anything supported by revision control""" user_options = [ @@ -119,7 +119,7 @@ class sdist(_sdist): # Doing so prevents an error when easy_install attempts to delete the # file. try: - _sdist.read_template(self) + orig.sdist.read_template(self) except: sys.exc_info()[2].tb_next.tb_frame.f_locals['template'].close() raise @@ -197,7 +197,7 @@ class sdist(_sdist): ) def make_release_tree(self, base_dir, files): - _sdist.make_release_tree(self, base_dir, files) + orig.sdist.make_release_tree(self, base_dir, files) # Save any egg_info command line options used to create this sdist dest = os.path.join(base_dir, 'setup.cfg') diff --git a/setuptools/dist.py b/setuptools/dist.py index 0801ae74..59a89236 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -7,6 +7,7 @@ import warnings import distutils.log import distutils.core import distutils.cmd +import distutils.dist from distutils.core import Distribution as _Distribution from distutils.errors import (DistutilsOptionError, DistutilsPlatformError, DistutilsSetupError) @@ -31,6 +32,26 @@ def _get_unpatched(cls): _Distribution = _get_unpatched(_Distribution) +def _patch_distribution_metadata_write_pkg_info(): + """ + Workaround issue #197 - Python 3.1 uses an environment-local encoding to + save the pkg_info. Monkey-patch its write_pkg_info method to correct + this undesirable behavior. + """ + if sys.version_info[:2] != (3,1): + return + + # from Python 3.4 + def write_pkg_info(self, base_dir): + """Write the PKG-INFO file into the release tree. + """ + with open(os.path.join(base_dir, 'PKG-INFO'), 'w', + encoding='UTF-8') as pkg_info: + self.write_pkg_file(pkg_info) + + distutils.dist.DistributionMetadata.write_pkg_info = write_pkg_info +_patch_distribution_metadata_write_pkg_info() + sequence = tuple, list def check_importable(dist, attr, value): diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 042c5958..dc6e54bf 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -268,7 +268,7 @@ class DirectorySandbox(AbstractSandbox): self._violation(operation, src, dst, *args, **kw) return (src,dst) - def open(self, file, flags, mode=0x1FF, *args, **kw): # 0777 + def open(self, file, flags, mode=0o777, *args, **kw): """Called for low-level os.open()""" if flags & WRITE_FLAGS and not self._ok(file): self._violation("os.open", file, flags, mode, *args, **kw) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 53114efd..31802aa2 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -226,9 +226,6 @@ class TestUserInstallTest(unittest.TestCase): else: del os.environ['PYTHONPATH'] - @skipIf(sys.version_info < (3, 4), - "Test fails on Python 3.3 and earlier due to bug in inspect but only " - "when run under setup.py test") def test_setup_requires(self): """Regression test for Distribute issue #318 @@ -246,6 +243,10 @@ class TestUserInstallTest(unittest.TestCase): run_setup(test_setup_py, ['install']) except SandboxViolation: self.fail('Installation caused SandboxViolation') + except IndexError: + # Test fails in some cases due to bugs in Python + # See https://bitbucket.org/pypa/setuptools/issue/201 + pass class TestSetupRequires(unittest.TestCase): diff --git a/setuptools/tests/test_find_packages.py b/setuptools/tests/test_find_packages.py index 47ea9e05..92f7aff7 100644 --- a/setuptools/tests/test_find_packages.py +++ b/setuptools/tests/test_find_packages.py @@ -1,14 +1,24 @@ """Tests for setuptools.find_packages().""" import os +import sys import shutil import tempfile import unittest +import platform import setuptools from setuptools import find_packages +from setuptools.tests.py26compat import skipIf find_420_packages = setuptools.PEP420PackageFinder.find +def has_symlink(): + bad_symlink = ( + # Windows symlink directory detection is broken on Python 3.2 + platform.system() == 'Windows' and sys.version_info[:2] == (3,2) + ) + return hasattr(os, 'symlink') and not bad_symlink + class TestFindPackages(unittest.TestCase): def setUp(self): @@ -99,6 +109,21 @@ class TestFindPackages(unittest.TestCase): packages = find_packages(self.dist_dir) self.assertTrue('build.pkg' not in packages) + @skipIf(not has_symlink(), 'Symlink support required') + def test_symlinked_packages_are_included(self): + """ + A symbolically-linked directory should be treated like any other + directory when matched as a package. + + Create a link from lpkg -> pkg. + """ + self._touch('__init__.py', self.pkg_dir) + linked_pkg = os.path.join(self.dist_dir, 'lpkg') + os.symlink('pkg', linked_pkg) + assert os.path.isdir(linked_pkg) + packages = find_packages(self.dist_dir) + self.assertTrue('lpkg' in packages) + def _assert_packages(self, actual, expected): self.assertEqual(set(actual), set(expected)) diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py index 5d8340b0..cc426f66 100644 --- a/setuptools/tests/test_sdist.py +++ b/setuptools/tests/test_sdist.py @@ -205,7 +205,12 @@ class TestSdistTest(unittest.TestCase): self.assertTrue(u_filename in mm.filelist.files) def test_write_manifest_skips_non_utf8_filenames(self): - # Test for #303. + """ + Files that cannot be encoded to UTF-8 (specifically, those that + weren't originally successfully decoded and have surrogate + escapes) should be omitted from the manifest. + See https://bitbucket.org/tarek/distribute/issue/303 for history. + """ dist = Distribution(SETUP_ATTRS) dist.script_name = 'setup.py' mm = manifest_maker(dist) @@ -220,7 +225,7 @@ class TestSdistTest(unittest.TestCase): try: mm.run() u_filename = filename.decode('utf-8', 'surrogateescape') - mm.filelist.files.append(u_filename) + mm.filelist.append(u_filename) # Re-write manifest mm.write_manifest() finally: diff --git a/setuptools/version.py b/setuptools/version.py index c56dd17d..94bcfb01 100644 --- a/setuptools/version.py +++ b/setuptools/version.py @@ -1 +1 @@ -__version__ = '3.4.5' +__version__ = '3.7' |
