summaryrefslogtreecommitdiff
path: root/setuptools
diff options
context:
space:
mode:
authorSteve Kowalik <steven@wedontsleep.org>2016-02-16 16:01:54 +1100
committerSteve Kowalik <steven@wedontsleep.org>2016-02-16 16:01:54 +1100
commit69175b941a74a4e2f37b856437b3ca20bc2f240a (patch)
treee0349b731b724c76963f9fd429f53b22cbf142d3 /setuptools
parent43d0308ad6a8c83be645b09e8c1871b36ff3c4c9 (diff)
parent8ccd428cd2a733891bffce13e017774ea82bd8d2 (diff)
downloadpython-setuptools-git-69175b941a74a4e2f37b856437b3ca20bc2f240a.tar.gz
Merge from master, resolving conflicts.
Diffstat (limited to 'setuptools')
-rw-r--r--setuptools/__init__.py2
-rw-r--r--setuptools/command/__init__.py2
-rwxr-xr-xsetuptools/command/alias.py2
-rw-r--r--setuptools/command/build_py.py34
-rwxr-xr-xsetuptools/command/easy_install.py50
-rwxr-xr-xsetuptools/command/egg_info.py1
-rwxr-xr-xsetuptools/command/install_egg_info.py4
-rw-r--r--setuptools/command/test.py1
-rw-r--r--setuptools/command/upload.py23
-rw-r--r--setuptools/command/upload_docs.py3
-rw-r--r--setuptools/dist.py1
-rw-r--r--setuptools/extension.py2
-rw-r--r--setuptools/launch.py35
-rwxr-xr-xsetuptools/package_index.py2
-rwxr-xr-xsetuptools/sandbox.py8
-rw-r--r--setuptools/ssl_support.py3
-rw-r--r--setuptools/tests/contexts.py13
-rw-r--r--setuptools/tests/test_dist_info.py2
-rw-r--r--setuptools/tests/test_easy_install.py224
-rw-r--r--setuptools/tests/test_egg_info.py2
-rw-r--r--setuptools/tests/test_sdist.py1
-rw-r--r--setuptools/tests/test_unicode_utils.py10
-rw-r--r--setuptools/unicode_utils.py6
23 files changed, 285 insertions, 146 deletions
diff --git a/setuptools/__init__.py b/setuptools/__init__.py
index ec0d5dc2..67b57e4f 100644
--- a/setuptools/__init__.py
+++ b/setuptools/__init__.py
@@ -8,7 +8,7 @@ from distutils.core import Command as _Command
from distutils.util import convert_path
from fnmatch import fnmatchcase
-from setuptools.extern.six.moves import filterfalse
+from setuptools.extern.six.moves import filterfalse, map
import setuptools.version
from setuptools.extension import Extension
diff --git a/setuptools/command/__init__.py b/setuptools/command/__init__.py
index f6dbc39c..3fb2f6df 100644
--- a/setuptools/command/__init__.py
+++ b/setuptools/command/__init__.py
@@ -2,7 +2,7 @@ __all__ = [
'alias', 'bdist_egg', 'bdist_rpm', 'build_ext', 'build_py', 'develop',
'easy_install', 'egg_info', 'install', 'install_lib', 'rotate', 'saveopts',
'sdist', 'setopt', 'test', 'install_egg_info', 'install_scripts',
- 'register', 'bdist_wininst', 'upload_docs',
+ 'register', 'bdist_wininst', 'upload_docs', 'upload',
]
from distutils.command.bdist import bdist
diff --git a/setuptools/command/alias.py b/setuptools/command/alias.py
index 452a9244..4532b1cc 100755
--- a/setuptools/command/alias.py
+++ b/setuptools/command/alias.py
@@ -1,5 +1,7 @@
from distutils.errors import DistutilsOptionError
+from setuptools.extern.six.moves import map
+
from setuptools.command.setopt import edit_config, option_base, config_file
diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py
index 8a50f032..8623c777 100644
--- a/setuptools/command/build_py.py
+++ b/setuptools/command/build_py.py
@@ -9,6 +9,7 @@ import distutils.errors
import collections
import itertools
+from setuptools.extern.six.moves import map
try:
from setuptools.lib2to3_ex import Mixin2to3
@@ -59,9 +60,10 @@ class build_py(orig.build_py, Mixin2to3):
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
+ "lazily compute data files"
+ if attr == 'data_files':
+ self.data_files = self._get_data_files()
+ return self.data_files
return orig.build_py.__getattr__(self, attr)
def build_module(self, module, module_file, package):
@@ -74,23 +76,21 @@ class build_py(orig.build_py, Mixin2to3):
def _get_data_files(self):
"""Generate list of '(package,src_dir,build_dir,filenames)' tuples"""
self.analyze_manifest()
- data = []
- for package in self.packages or ():
- # Locate package source directory
- src_dir = self.get_package_dir(package)
+ return list(map(self._get_pkg_data_files, self.packages or ()))
- # Compute package build directory
- build_dir = os.path.join(*([self.build_lib] + package.split('.')))
+ def _get_pkg_data_files(self, package):
+ # Locate package source directory
+ src_dir = self.get_package_dir(package)
- # Length of path to strip from found files
- plen = len(src_dir) + 1
+ # Compute package build directory
+ build_dir = os.path.join(*([self.build_lib] + package.split('.')))
- # Strip directory from globbed filenames
- filenames = [
- file[plen:] for file in self.find_data_files(package, src_dir)
- ]
- data.append((package, src_dir, build_dir, filenames))
- return data
+ # Strip directory from globbed filenames
+ filenames = [
+ os.path.relpath(file, src_dir)
+ for file in self.find_data_files(package, src_dir)
+ ]
+ return package, src_dir, build_dir, filenames
def find_data_files(self, package, src_dir):
"""Return filenames for package's data files in 'src_dir'"""
diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py
index a11618d1..46056173 100755
--- a/setuptools/command/easy_install.py
+++ b/setuptools/command/easy_install.py
@@ -41,7 +41,7 @@ import shlex
import io
from setuptools.extern import six
-from setuptools.extern.six.moves import configparser
+from setuptools.extern.six.moves import configparser, map
from setuptools import Command
from setuptools.sandbox import run_setup
@@ -1876,17 +1876,6 @@ def chmod(path, mode):
log.debug("chmod failed: %s", e)
-def fix_jython_executable(executable, options):
- warnings.warn("Use JythonCommandSpec", DeprecationWarning, stacklevel=2)
-
- if not JythonCommandSpec.relevant():
- return executable
-
- cmd = CommandSpec.best().from_param(executable)
- cmd.install_options(options)
- return cmd.as_header().lstrip('#!').rstrip('\n')
-
-
class CommandSpec(list):
"""
A command spec for a #! header, specified as a list of arguments akin to
@@ -1901,7 +1890,7 @@ class CommandSpec(list):
"""
Choose the best CommandSpec class based on environmental conditions.
"""
- return cls if not JythonCommandSpec.relevant() else JythonCommandSpec
+ return cls
@classmethod
def _sys_executable(cls):
@@ -1968,36 +1957,6 @@ class WindowsCommandSpec(CommandSpec):
split_args = dict(posix=False)
-class JythonCommandSpec(CommandSpec):
- @classmethod
- def relevant(cls):
- return (
- sys.platform.startswith('java')
- and
- __import__('java').lang.System.getProperty('os.name') != 'Linux'
- )
-
- def as_header(self):
- """
- Workaround Jython's sys.executable being a .sh (an invalid
- shebang line interpreter)
- """
- if not is_sh(self[0]):
- return super(JythonCommandSpec, self).as_header()
-
- if self.options:
- # Can't apply the workaround, leave it broken
- log.warn(
- "WARNING: Unable to adapt shebang line for Jython,"
- " the following script is NOT executable\n"
- " see http://bugs.jython.org/issue1112 for"
- " more information.")
- return super(JythonCommandSpec, self).as_header()
-
- items = ['/usr/bin/env'] + self + list(self.options)
- return self._render(items)
-
-
class ScriptWriter(object):
"""
Encapsulates behavior around writing entry point scripts for console and
@@ -2074,7 +2033,10 @@ class ScriptWriter(object):
"""
Select the best ScriptWriter for this environment.
"""
- return WindowsScriptWriter.best() if sys.platform == 'win32' else cls
+ if sys.platform == 'win32' or (os.name == 'java' and os._name == 'nt'):
+ return WindowsScriptWriter.best()
+ else:
+ return cls
@classmethod
def _get_script_args(cls, type_, name, header, script_text):
diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py
index 18a3105f..d1bd9b04 100755
--- a/setuptools/command/egg_info.py
+++ b/setuptools/command/egg_info.py
@@ -15,6 +15,7 @@ import warnings
import time
from setuptools.extern import six
+from setuptools.extern.six.moves import map
from setuptools import Command
from setuptools.command.sdist import sdist
diff --git a/setuptools/command/install_egg_info.py b/setuptools/command/install_egg_info.py
index fd0f118b..60b615d2 100755
--- a/setuptools/command/install_egg_info.py
+++ b/setuptools/command/install_egg_info.py
@@ -1,6 +1,8 @@
from distutils import log, dir_util
import os
+from setuptools.extern.six.moves import map
+
from setuptools import Command
from setuptools.archive_util import unpack_archive
import pkg_resources
@@ -27,7 +29,7 @@ class install_egg_info(Command):
).egg_name() + '.egg-info'
self.source = ei_cmd.egg_info
self.target = os.path.join(self.install_dir, basename)
- self.outputs = [self.target]
+ self.outputs = []
def run(self):
self.run_command('egg_info')
diff --git a/setuptools/command/test.py b/setuptools/command/test.py
index 3a2a9b93..371e913b 100644
--- a/setuptools/command/test.py
+++ b/setuptools/command/test.py
@@ -3,6 +3,7 @@ from unittest import TestLoader
import sys
from setuptools.extern import six
+from setuptools.extern.six.moves import map
from pkg_resources import (resource_listdir, resource_exists, normalize_path,
working_set, _namespace_packages,
diff --git a/setuptools/command/upload.py b/setuptools/command/upload.py
new file mode 100644
index 00000000..08c20ba8
--- /dev/null
+++ b/setuptools/command/upload.py
@@ -0,0 +1,23 @@
+from distutils.command import upload as orig
+
+
+class upload(orig.upload):
+ """
+ Override default upload behavior to look up password
+ in the keyring if available.
+ """
+
+ def finalize_options(self):
+ orig.upload.finalize_options(self)
+ self.password or self._load_password_from_keyring()
+
+ def _load_password_from_keyring(self):
+ """
+ Attempt to load password from keyring. Suppress Exceptions.
+ """
+ try:
+ keyring = __import__('keyring')
+ self.password = keyring.get_password(self.repository,
+ self.username)
+ except Exception:
+ pass
diff --git a/setuptools/command/upload_docs.py b/setuptools/command/upload_docs.py
index ca35a3ce..f887b47e 100644
--- a/setuptools/command/upload_docs.py
+++ b/setuptools/command/upload_docs.py
@@ -8,18 +8,17 @@ PyPI's pythonhosted.org).
from base64 import standard_b64encode
from distutils import log
from distutils.errors import DistutilsOptionError
-from distutils.command.upload import upload
import os
import socket
import zipfile
import tempfile
-import sys
import shutil
from setuptools.extern import six
from setuptools.extern.six.moves import http_client, urllib
from pkg_resources import iter_entry_points
+from .upload import upload
errors = 'surrogateescape' if six.PY3 else 'strict'
diff --git a/setuptools/dist.py b/setuptools/dist.py
index 4964a9e8..77855415 100644
--- a/setuptools/dist.py
+++ b/setuptools/dist.py
@@ -14,6 +14,7 @@ from distutils.errors import (DistutilsOptionError, DistutilsPlatformError,
DistutilsSetupError)
from setuptools.extern import six
+from setuptools.extern.six.moves import map
from pkg_resources.extern import packaging
from setuptools.depends import Require
diff --git a/setuptools/extension.py b/setuptools/extension.py
index 35eb7c7c..d10609b6 100644
--- a/setuptools/extension.py
+++ b/setuptools/extension.py
@@ -5,6 +5,8 @@ import distutils.core
import distutils.errors
import distutils.extension
+from setuptools.extern.six.moves import map
+
from .dist import _get_unpatched
from . import msvc9_support
diff --git a/setuptools/launch.py b/setuptools/launch.py
new file mode 100644
index 00000000..06e15e1e
--- /dev/null
+++ b/setuptools/launch.py
@@ -0,0 +1,35 @@
+"""
+Launch the Python script on the command line after
+setuptools is bootstrapped via import.
+"""
+
+# Note that setuptools gets imported implicitly by the
+# invocation of this script using python -m setuptools.launch
+
+import tokenize
+import sys
+
+
+def run():
+ """
+ Run the script in sys.argv[1] as if it had
+ been invoked naturally.
+ """
+ __builtins__
+ script_name = sys.argv[1]
+ namespace = dict(
+ __file__ = script_name,
+ __name__ = '__main__',
+ __doc__ = None,
+ )
+ sys.argv[:] = sys.argv[1:]
+
+ open_ = getattr(tokenize, 'open', open)
+ script = open_(script_name).read()
+ norm_script = script.replace('\\r\\n', '\\n')
+ code = compile(norm_script, script_name, 'exec')
+ exec(code, namespace)
+
+
+if __name__ == '__main__':
+ run()
diff --git a/setuptools/package_index.py b/setuptools/package_index.py
index ea136c09..c53343e4 100755
--- a/setuptools/package_index.py
+++ b/setuptools/package_index.py
@@ -15,7 +15,7 @@ except ImportError:
from urllib2 import splituser
from setuptools.extern import six
-from setuptools.extern.six.moves import urllib, http_client, configparser
+from setuptools.extern.six.moves import urllib, http_client, configparser, map
from pkg_resources import (
CHECKOUT_DIST, Distribution, BINARY_DIST, normalize_path, SOURCE_DIST,
diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py
index 37035f37..23e296b1 100755
--- a/setuptools/sandbox.py
+++ b/setuptools/sandbox.py
@@ -9,7 +9,7 @@ import contextlib
import pickle
from setuptools.extern import six
-from setuptools.extern.six.moves import builtins
+from setuptools.extern.six.moves import builtins, map
import pkg_resources
@@ -207,8 +207,12 @@ def _needs_hiding(mod_name):
True
>>> _needs_hiding('distutils')
True
+ >>> _needs_hiding('os')
+ False
+ >>> _needs_hiding('Cython')
+ True
"""
- pattern = re.compile('(setuptools|pkg_resources|distutils)(\.|$)')
+ pattern = re.compile('(setuptools|pkg_resources|distutils|Cython)(\.|$)')
return bool(pattern.match(mod_name))
diff --git a/setuptools/ssl_support.py b/setuptools/ssl_support.py
index 7baedd19..657197cf 100644
--- a/setuptools/ssl_support.py
+++ b/setuptools/ssl_support.py
@@ -3,7 +3,7 @@ import socket
import atexit
import re
-from setuptools.extern.six.moves import urllib, http_client
+from setuptools.extern.six.moves import urllib, http_client, map
import pkg_resources
from pkg_resources import ResolutionError, ExtractionError
@@ -25,6 +25,7 @@ cert_paths = """
/usr/local/share/certs/ca-root.crt
/etc/ssl/cert.pem
/System/Library/OpenSSL/certs/cert.pem
+/usr/local/share/certs/ca-root-nss.crt
""".strip().split()
diff --git a/setuptools/tests/contexts.py b/setuptools/tests/contexts.py
index 8c9a2d3e..ae28c7c3 100644
--- a/setuptools/tests/contexts.py
+++ b/setuptools/tests/contexts.py
@@ -6,6 +6,7 @@ import contextlib
import site
from setuptools.extern import six
+import pkg_resources
@contextlib.contextmanager
@@ -78,6 +79,18 @@ def save_user_site_setting():
@contextlib.contextmanager
+def save_pkg_resources_state():
+ pr_state = pkg_resources.__getstate__()
+ # also save sys.path
+ sys_path = sys.path[:]
+ try:
+ yield pr_state, sys_path
+ finally:
+ sys.path[:] = sys_path
+ pkg_resources.__setstate__(pr_state)
+
+
+@contextlib.contextmanager
def suppress_exceptions(*excs):
try:
yield
diff --git a/setuptools/tests/test_dist_info.py b/setuptools/tests/test_dist_info.py
index 47d7a495..002968a3 100644
--- a/setuptools/tests/test_dist_info.py
+++ b/setuptools/tests/test_dist_info.py
@@ -4,6 +4,8 @@ import os
import shutil
import tempfile
+from setuptools.extern.six.moves import map
+
import pytest
import pkg_resources
diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py
index 94e317b3..07d8a3c5 100644
--- a/setuptools/tests/test_easy_install.py
+++ b/setuptools/tests/test_easy_install.py
@@ -18,6 +18,7 @@ import io
from setuptools.extern import six
from setuptools.extern.six.moves import urllib
+import time
import pytest
try:
@@ -310,32 +311,32 @@ class TestSetupRequires:
"""
with contexts.tempdir() as dir:
dist_path = os.path.join(dir, 'setuptools-test-fetcher-1.0.tar.gz')
- script = DALS("""
- import setuptools
- setuptools.setup(
- name="setuptools-test-fetcher",
- version="1.0",
- setup_requires = ['does-not-exist'],
- )
- """)
- make_trivial_sdist(dist_path, script)
+ make_sdist(dist_path, [
+ ('setup.py', DALS("""
+ import setuptools
+ setuptools.setup(
+ name="setuptools-test-fetcher",
+ version="1.0",
+ setup_requires = ['does-not-exist'],
+ )
+ """))])
yield dist_path
def test_setup_requires_overrides_version_conflict(self):
"""
- Regression test for issue #323.
+ Regression test for distribution issue 323:
+ https://bitbucket.org/tarek/distribute/issues/323
Ensures that a distribution's setup_requires requirements can still be
installed and used locally even if a conflicting version of that
requirement is already on the path.
"""
- pr_state = pkg_resources.__getstate__()
fake_dist = PRDistribution('does-not-matter', project_name='foobar',
version='0.0')
working_set.add(fake_dist)
- try:
+ with contexts.save_pkg_resources_state():
with contexts.tempdir() as temp_dir:
test_pkg = create_setup_requires_package(temp_dir)
test_setup_py = os.path.join(test_pkg, 'setup.py')
@@ -347,19 +348,144 @@ class TestSetupRequires:
lines = stdout.readlines()
assert len(lines) > 0
assert lines[-1].strip(), 'test_pkg'
- finally:
- pkg_resources.__setstate__(pr_state)
+ def test_setup_requires_override_nspkg(self):
+ """
+ Like ``test_setup_requires_overrides_version_conflict`` but where the
+ ``setup_requires`` package is part of a namespace package that has
+ *already* been imported.
+ """
+
+ with contexts.save_pkg_resources_state():
+ with contexts.tempdir() as temp_dir:
+ foobar_1_archive = os.path.join(temp_dir, 'foo.bar-0.1.tar.gz')
+ make_nspkg_sdist(foobar_1_archive, 'foo.bar', '0.1')
+ # Now actually go ahead an extract to the temp dir and add the
+ # extracted path to sys.path so foo.bar v0.1 is importable
+ foobar_1_dir = os.path.join(temp_dir, 'foo.bar-0.1')
+ os.mkdir(foobar_1_dir)
+ with tarfile_open(foobar_1_archive) as tf:
+ tf.extractall(foobar_1_dir)
+ sys.path.insert(1, foobar_1_dir)
+
+ dist = PRDistribution(foobar_1_dir, project_name='foo.bar',
+ version='0.1')
+ working_set.add(dist)
+
+ template = DALS("""\
+ import foo # Even with foo imported first the
+ # setup_requires package should override
+ import setuptools
+ setuptools.setup(**%r)
+
+ if not (hasattr(foo, '__path__') and
+ len(foo.__path__) == 2):
+ print('FAIL')
+
+ if 'foo.bar-0.2' not in foo.__path__[0]:
+ print('FAIL')
+ """)
+
+ test_pkg = create_setup_requires_package(
+ temp_dir, 'foo.bar', '0.2', make_nspkg_sdist, template)
+
+ test_setup_py = os.path.join(test_pkg, 'setup.py')
+
+ with contexts.quiet() as (stdout, stderr):
+ try:
+ # Don't even need to install the package, just
+ # running the setup.py at all is sufficient
+ run_setup(test_setup_py, ['--name'])
+ except pkg_resources.VersionConflict:
+ self.fail('Installing setup.py requirements '
+ 'caused a VersionConflict')
+
+ assert 'FAIL' not in stdout.getvalue()
+ lines = stdout.readlines()
+ assert len(lines) > 0
+ assert lines[-1].strip() == 'test_pkg'
+
+
+def make_trivial_sdist(dist_path, distname, version):
+ """
+ Create a simple sdist tarball at dist_path, containing just a simple
+ setup.py.
+ """
+
+ make_sdist(dist_path, [
+ ('setup.py',
+ DALS("""\
+ import setuptools
+ setuptools.setup(
+ name=%r,
+ version=%r
+ )
+ """ % (distname, version)))])
-def create_setup_requires_package(path):
+
+def make_nspkg_sdist(dist_path, distname, version):
+ """
+ Make an sdist tarball with distname and version which also contains one
+ package with the same name as distname. The top-level package is
+ designated a namespace package).
+ """
+
+ parts = distname.split('.')
+ nspackage = parts[0]
+
+ packages = ['.'.join(parts[:idx]) for idx in range(1, len(parts) + 1)]
+
+ setup_py = DALS("""\
+ import setuptools
+ setuptools.setup(
+ name=%r,
+ version=%r,
+ packages=%r,
+ namespace_packages=[%r]
+ )
+ """ % (distname, version, packages, nspackage))
+
+ init = "__import__('pkg_resources').declare_namespace(__name__)"
+
+ files = [('setup.py', setup_py),
+ (os.path.join(nspackage, '__init__.py'), init)]
+ for package in packages[1:]:
+ filename = os.path.join(*(package.split('.') + ['__init__.py']))
+ files.append((filename, ''))
+
+ make_sdist(dist_path, files)
+
+
+def make_sdist(dist_path, files):
+ """
+ Create a simple sdist tarball at dist_path, containing the files
+ listed in ``files`` as ``(filename, content)`` tuples.
+ """
+
+ with tarfile_open(dist_path, 'w:gz') as dist:
+ for filename, content in files:
+ file_bytes = io.BytesIO(content.encode('utf-8'))
+ file_info = tarfile.TarInfo(name=filename)
+ file_info.size = len(file_bytes.getvalue())
+ file_info.mtime = int(time.time())
+ dist.addfile(file_info, fileobj=file_bytes)
+
+
+def create_setup_requires_package(path, distname='foobar', version='0.1',
+ make_package=make_trivial_sdist,
+ setup_py_template=None):
"""Creates a source tree under path for a trivial test package that has a
single requirement in setup_requires--a tarball for that requirement is
also created and added to the dependency_links argument.
+
+ ``distname`` and ``version`` refer to the name/version of the package that
+ the test package requires via ``setup_requires``. The name of the test
+ package itself is just 'test_pkg'.
"""
test_setup_attrs = {
'name': 'test_pkg', 'version': '0.0',
- 'setup_requires': ['foobar==0.1'],
+ 'setup_requires': ['%s==%s' % (distname, version)],
'dependency_links': [os.path.abspath(path)]
}
@@ -367,22 +493,17 @@ def create_setup_requires_package(path):
test_setup_py = os.path.join(test_pkg, 'setup.py')
os.mkdir(test_pkg)
- with open(test_setup_py, 'w') as f:
- f.write(DALS("""
+ if setup_py_template is None:
+ setup_py_template = DALS("""\
import setuptools
setuptools.setup(**%r)
- """ % test_setup_attrs))
+ """)
- foobar_path = os.path.join(path, 'foobar-0.1.tar.gz')
- make_trivial_sdist(
- foobar_path,
- DALS("""
- import setuptools
- setuptools.setup(
- name='foobar',
- version='0.1'
- )
- """))
+ with open(test_setup_py, 'w') as f:
+ f.write(setup_py_template % test_setup_attrs)
+
+ foobar_path = os.path.join(path, '%s-%s.tar.gz' % (distname, version))
+ make_package(foobar_path, distname, version)
return test_pkg
@@ -427,51 +548,6 @@ class TestScriptHeader:
expected = '#!"%s"\n' % self.exe_with_spaces
assert actual == expected
- @pytest.mark.xfail(
- six.PY3 and is_ascii,
- reason="Test fails in this locale on Python 3"
- )
- @mock.patch.dict(sys.modules, java=mock.Mock(lang=mock.Mock(System=
- mock.Mock(getProperty=mock.Mock(return_value="")))))
- @mock.patch('sys.platform', 'java1.5.0_13')
- def test_get_script_header_jython_workaround(self, tmpdir):
- # Create a mock sys.executable that uses a shebang line
- header = DALS("""
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- """)
- exe = tmpdir / 'exe.py'
- with exe.open('w') as f:
- f.write(header)
-
- exe = ei.nt_quote_arg(os.path.normpath(str(exe)))
-
- # Make sure Windows paths are quoted properly before they're sent
- # through shlex.split by get_script_header
- executable = '"%s"' % exe if os.path.splitdrive(exe)[0] else exe
-
- header = ei.ScriptWriter.get_script_header('#!/usr/local/bin/python',
- executable=executable)
- assert header == '#!/usr/bin/env %s\n' % exe
-
- expect_out = 'stdout' if sys.version_info < (2,7) else 'stderr'
-
- with contexts.quiet() as (stdout, stderr):
- # When options are included, generate a broken shebang line
- # with a warning emitted
- candidate = ei.ScriptWriter.get_script_header('#!/usr/bin/python -x',
- executable=executable)
- assert candidate == '#!%s -x\n' % exe
- output = locals()[expect_out]
- assert 'Unable to adapt shebang line' in output.getvalue()
-
- with contexts.quiet() as (stdout, stderr):
- candidate = ei.ScriptWriter.get_script_header('#!/usr/bin/python',
- executable=self.non_ascii_exe)
- assert candidate == '#!%s -x\n' % self.non_ascii_exe
- output = locals()[expect_out]
- assert 'Unable to adapt shebang line' in output.getvalue()
-
class TestCommandSpec:
def test_custom_launch_command(self):
diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py
index 333d11d6..7d51585b 100644
--- a/setuptools/tests/test_egg_info.py
+++ b/setuptools/tests/test_egg_info.py
@@ -1,6 +1,8 @@
import os
import stat
+from setuptools.extern.six.moves import map
+
import pytest
from . import environment
diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py
index 753b507d..d2a1f1bb 100644
--- a/setuptools/tests/test_sdist.py
+++ b/setuptools/tests/test_sdist.py
@@ -10,6 +10,7 @@ import contextlib
import io
from setuptools.extern import six
+from setuptools.extern.six.moves import map
import pytest
diff --git a/setuptools/tests/test_unicode_utils.py b/setuptools/tests/test_unicode_utils.py
new file mode 100644
index 00000000..a24a9bd5
--- /dev/null
+++ b/setuptools/tests/test_unicode_utils.py
@@ -0,0 +1,10 @@
+from setuptools import unicode_utils
+
+
+def test_filesys_decode_fs_encoding_is_None(monkeypatch):
+ """
+ Test filesys_decode does not raise TypeError when
+ getfilesystemencoding returns None.
+ """
+ monkeypatch.setattr('sys.getfilesystemencoding', lambda: None)
+ unicode_utils.filesys_decode(b'test')
diff --git a/setuptools/unicode_utils.py b/setuptools/unicode_utils.py
index 18903d9e..ffab3e24 100644
--- a/setuptools/unicode_utils.py
+++ b/setuptools/unicode_utils.py
@@ -22,11 +22,13 @@ def filesys_decode(path):
NONE when no expected encoding works
"""
- fs_enc = sys.getfilesystemencoding()
if isinstance(path, six.text_type):
return path
- for enc in (fs_enc, "utf-8"):
+ fs_enc = sys.getfilesystemencoding() or 'utf-8'
+ candidates = fs_enc, 'utf-8'
+
+ for enc in candidates:
try:
return path.decode(enc)
except UnicodeDecodeError: