summaryrefslogtreecommitdiff
path: root/setuptools
diff options
context:
space:
mode:
Diffstat (limited to 'setuptools')
-rw-r--r--setuptools/__init__.py2
-rwxr-xr-xsetuptools/command/bdist_rpm.py8
-rwxr-xr-xsetuptools/command/bdist_wininst.py6
-rw-r--r--setuptools/command/build_py.py20
-rwxr-xr-xsetuptools/command/easy_install.py61
-rwxr-xr-xsetuptools/command/egg_info.py83
-rw-r--r--setuptools/command/install.py24
-rw-r--r--setuptools/command/install_lib.py8
-rwxr-xr-xsetuptools/command/install_scripts.py11
-rwxr-xr-xsetuptools/command/register.py9
-rwxr-xr-xsetuptools/command/sdist.py8
-rw-r--r--setuptools/dist.py21
-rwxr-xr-xsetuptools/sandbox.py2
-rw-r--r--setuptools/tests/test_easy_install.py7
-rw-r--r--setuptools/tests/test_find_packages.py25
-rw-r--r--setuptools/tests/test_sdist.py9
-rw-r--r--setuptools/version.py2
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'