Commit 76fefe98 authored by Jason R. Coombs's avatar Jason R. Coombs

Merge branch 'master' into pr1145

parents a5add17b ff9bc490
v36.5.1
v36.6.1
-------
* #170: When working with Mercurial checkouts, use Windows-friendly
syntax for suppressing output.
* #1132: Removed redundant and costly serialization/parsing step
in ``EntryPoint.__init__``.
v36.6.0
-------
* #1143: Added ``setuptools.build_meta`` module, an implementation
of PEP-517 for Setuptools-defined packages.
* #1143: Added ``dist_info`` command for producing dist_info
metadata.
v36.5.0
-------
* #170: When working with Mercurial checkouts, use Windows-friendly
syntax for suppressing output.
* Inspired by #1134, performed substantial refactoring of
``pkg_resources.find_on_path`` to facilitate an optimization
for paths with many non-version entries.
......
......@@ -480,8 +480,10 @@ def get_build_platform():
try:
version = _macosx_vers()
machine = os.uname()[4].replace(" ", "_")
return "macosx-%d.%d-%s" % (int(version[0]), int(version[1]),
_macosx_arch(machine))
return "macosx-%d.%d-%s" % (
int(version[0]), int(version[1]),
_macosx_arch(machine),
)
except ValueError:
# if someone is running a non-Mac darwin system, this will fall
# through to the default implementation
......@@ -806,7 +808,8 @@ class WorkingSet(object):
already-installed distribution; it should return a ``Distribution`` or
``None``.
Unless `replace_conflicting=True`, raises a VersionConflict exception if
Unless `replace_conflicting=True`, raises a VersionConflict exception
if
any requirements are found on the path that have the correct name but
the wrong version. Otherwise, if an `installer` is supplied it will be
invoked to obtain the correct version of the requirement and activate
......@@ -885,8 +888,8 @@ class WorkingSet(object):
# return list of distros to activate
return to_activate
def find_plugins(self, plugin_env, full_env=None, installer=None,
fallback=True):
def find_plugins(
self, plugin_env, full_env=None, installer=None, fallback=True):
"""Find all activatable distributions in `plugin_env`
Example usage::
......@@ -1040,7 +1043,8 @@ class _ReqExtras(dict):
class Environment(object):
"""Searchable snapshot of distributions on a search path"""
def __init__(self, search_path=None, platform=get_supported_platform(),
def __init__(
self, search_path=None, platform=get_supported_platform(),
python=PY_MAJOR):
"""Snapshot distributions available on a search path
......@@ -1113,7 +1117,8 @@ class Environment(object):
dists.append(dist)
dists.sort(key=operator.attrgetter('hashcmp'), reverse=True)
def best_match(self, req, working_set, installer=None, replace_conflicting=False):
def best_match(
self, req, working_set, installer=None, replace_conflicting=False):
"""Find distribution best matching `req` and usable on `working_set`
This calls the ``find(req)`` method of the `working_set` to see if a
......@@ -1248,8 +1253,8 @@ class ResourceManager:
tmpl = textwrap.dedent("""
Can't extract file(s) to egg cache
The following error occurred while trying to extract file(s) to the Python egg
cache:
The following error occurred while trying to extract file(s)
to the Python egg cache:
{old_exc}
......@@ -1257,9 +1262,9 @@ class ResourceManager:
{cache_path}
Perhaps your account does not have write access to this directory? You can
change the cache directory by setting the PYTHON_EGG_CACHE environment
variable to point to an accessible directory.
Perhaps your account does not have write access to this directory?
You can change the cache directory by setting the PYTHON_EGG_CACHE
environment variable to point to an accessible directory.
""").lstrip()
err = ExtractionError(tmpl.format(**locals()))
err.manager = self
......@@ -1309,11 +1314,13 @@ class ResourceManager:
return
mode = os.stat(path).st_mode
if mode & stat.S_IWOTH or mode & stat.S_IWGRP:
msg = ("%s is writable by group/others and vulnerable to attack "
msg = (
"%s is writable by group/others and vulnerable to attack "
"when "
"used with get_resource_filename. Consider a more secure "
"location (set with .set_extraction_path or the "
"PYTHON_EGG_CACHE environment variable)." % path)
"PYTHON_EGG_CACHE environment variable)." % path
)
warnings.warn(msg, UserWarning)
def postprocess(self, tempname, filename):
......@@ -1597,8 +1604,11 @@ class DefaultProvider(EggProvider):
@classmethod
def _register(cls):
loader_cls = getattr(importlib_machinery, 'SourceFileLoader',
type(None))
loader_cls = getattr(
importlib_machinery,
'SourceFileLoader',
type(None),
)
register_loader_type(loader_cls, cls)
......@@ -1766,7 +1776,10 @@ class ZipProvider(EggProvider):
if self._is_current(real_path, zip_path):
return real_path
outf, tmpnam = _mkstemp(".$extract", dir=os.path.dirname(real_path))
outf, tmpnam = _mkstemp(
".$extract",
dir=os.path.dirname(real_path),
)
os.write(outf, self.loader.get_data(zip_path))
os.close(outf)
utime(tmpnam, (timestamp, timestamp))
......@@ -1972,7 +1985,8 @@ def find_eggs_in_zip(importer, path_item, only=False):
for subitem in metadata.resource_listdir('/'):
if _is_egg_path(subitem):
subpath = os.path.join(path_item, subitem)
for dist in find_eggs_in_zip(zipimport.zipimporter(subpath), subpath):
dists = find_eggs_in_zip(zipimport.zipimporter(subpath), subpath)
for dist in dists:
yield dist
elif subitem.lower().endswith('.dist-info'):
subpath = os.path.join(path_item, subitem)
......@@ -1981,7 +1995,6 @@ def find_eggs_in_zip(importer, path_item, only=False):
yield Distribution.from_location(path_item, subitem, submeta)
register_finder(zipimport.zipimporter, find_eggs_in_zip)
......@@ -2124,7 +2137,11 @@ def non_empty_lines(path):
"""
Yield non-empty lines from file at path
"""
return (line.rstrip() for line in open(path) if line.strip())
with open(path) as f:
for line in f:
line = line.strip()
if line:
yield line
def resolve_egg_link(path):
......@@ -2375,7 +2392,7 @@ class EntryPoint(object):
self.name = name
self.module_name = module_name
self.attrs = tuple(attrs)
self.extras = Requirement.parse(("x[%s]" % ','.join(extras))).extras
self.extras = tuple(extras)
self.dist = dist
def __str__(self):
......@@ -2523,7 +2540,8 @@ class Distribution(object):
"""Wrap an actual or potential sys.path entry w/metadata"""
PKG_INFO = 'PKG-INFO'
def __init__(self, location=None, metadata=None, project_name=None,
def __init__(
self, location=None, metadata=None, project_name=None,
version=None, py_version=PY_MAJOR, platform=None,
precedence=EGG_DIST):
self.project_name = safe_name(project_name or 'Unknown')
......@@ -2799,7 +2817,8 @@ class Distribution(object):
if replace:
break
else:
# don't modify path (even removing duplicates) if found and not replace
# don't modify path (even removing duplicates) if
# found and not replace
return
elif item == bdir and self.precedence == EGG_DIST:
# if it's an .egg, give it precedence over its directory
......@@ -2896,7 +2915,10 @@ class EggInfoDistribution(Distribution):
class DistInfoDistribution(Distribution):
"""Wrap an actual or potential sys.path entry w/metadata, .dist-info style"""
"""
Wrap an actual or potential sys.path entry
w/metadata, .dist-info style.
"""
PKG_INFO = 'METADATA'
EQEQ = re.compile(r"([\(,])\s*(\d.*?)\s*([,\)])")
......@@ -2946,7 +2968,7 @@ _distributionImpl = {
'.egg': Distribution,
'.egg-info': EggInfoDistribution,
'.dist-info': DistInfoDistribution,
}
}
def issue_warning(*args, **kw):
......@@ -3031,7 +3053,8 @@ class Requirement(packaging.requirements.Requirement):
def __hash__(self):
return self.__hash
def __repr__(self): return "Requirement.parse(%r)" % str(self)
def __repr__(self):
return "Requirement.parse(%r)" % str(self)
@staticmethod
def parse(s):
......@@ -3165,7 +3188,10 @@ def _initialize_master_working_set():
dist.activate(replace=False)
for dist in working_set
)
add_activation_listener(lambda dist: dist.activate(replace=True), existing=False)
add_activation_listener(
lambda dist: dist.activate(replace=True),
existing=False,
)
working_set.entries = []
# match order
list(map(working_set.add_entry, sys.path))
......
......@@ -92,8 +92,8 @@ class TestZipProvider(object):
ts = timestamp(self.ref_time)
os.utime(filename, (ts, ts))
filename = zp.get_resource_filename(manager, 'data.dat')
f = open(filename)
assert f.read() == 'hello, world!'
with open(filename) as f:
assert f.read() == 'hello, world!'
manager.cleanup_resources()
......
[bumpversion]
current_version = 36.4.0
current_version = 36.6.0
commit = True
tag = True
......@@ -22,5 +22,7 @@ formats = zip
[bdist_wheel]
universal = 1
[bumpversion:file:setup.py]
[metadata]
license_file = LICENSE
[bumpversion:file:setup.py]
......@@ -89,7 +89,7 @@ def pypi_link(pkg_filename):
setup_params = dict(
name="setuptools",
version="36.4.0",
version="36.6.0",
description="Easily download, build, install, upgrade, and uninstall "
"Python packages",
author="Python Packaging Authority",
......
"""A PEP 517 interface to setuptools
Previously, when a user or a command line tool (let's call it a "frontend")
needed to make a request of setuptools to take a certain action, for
example, generating a list of installation requirements, the frontend would
would call "setup.py egg_info" or "setup.py bdist_wheel" on the command line.
PEP 517 defines a different method of interfacing with setuptools. Rather
than calling "setup.py" directly, the frontend should:
1. Set the current directory to the directory with a setup.py file
2. Import this module into a safe python interpreter (one in which
setuptools can potentially set global variables or crash hard).
3. Call one of the functions defined in PEP 517.
What each function does is defined in PEP 517. However, here is a "casual"
definition of the functions (this definition should not be relied on for
bug reports or API stability):
- `build_wheel`: build a wheel in the folder and return the basename
- `get_requires_for_build_wheel`: get the `setup_requires` to build
- `prepare_metadata_for_build_wheel`: get the `install_requires`
- `build_sdist`: build an sdist in the folder and return the basename
- `get_requires_for_build_sdist`: get the `setup_requires` to build
Again, this is not a formal definition! Just a "taste" of the module.
"""
import os
import sys
import tokenize
import shutil
import contextlib
import setuptools
import distutils
class SetupRequirementsError(BaseException):
def __init__(self, specifiers):
self.specifiers = specifiers
class Distribution(setuptools.dist.Distribution):
def fetch_build_eggs(self, specifiers):
raise SetupRequirementsError(specifiers)
@classmethod
@contextlib.contextmanager
def patch(cls):
"""
Replace
distutils.dist.Distribution with this class
for the duration of this context.
"""
orig = distutils.core.Distribution
distutils.core.Distribution = cls
try:
yield
finally:
distutils.core.Distribution = orig
def _run_setup(setup_script='setup.py'):
# Note that we can reuse our build directory between calls
# Correctness comes first, then optimization later
__file__ = setup_script
f = getattr(tokenize, 'open', open)(__file__)
code = f.read().replace('\\r\\n', '\\n')
f.close()
exec(compile(code, __file__, 'exec'))
def _fix_config(config_settings):
config_settings = config_settings or {}
config_settings.setdefault('--global-option', [])
return config_settings
def _get_build_requires(config_settings):
config_settings = _fix_config(config_settings)
requirements = ['setuptools', 'wheel']
sys.argv = sys.argv[:1] + ['egg_info'] + \
config_settings["--global-option"]
try:
with Distribution.patch():
_run_setup()
except SetupRequirementsError as e:
requirements += e.specifiers
return requirements
def get_requires_for_build_wheel(config_settings=None):
config_settings = _fix_config(config_settings)
return _get_build_requires(config_settings)
def get_requires_for_build_sdist(config_settings=None):
config_settings = _fix_config(config_settings)
return _get_build_requires(config_settings)
def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None):
sys.argv = sys.argv[:1] + ['dist_info', '--egg-base', metadata_directory]
_run_setup()
dist_infos = [f for f in os.listdir(metadata_directory)
if f.endswith('.dist-info')]
assert len(dist_infos) == 1
return dist_infos[0]
def build_wheel(wheel_directory, config_settings=None,
metadata_directory=None):
config_settings = _fix_config(config_settings)
wheel_directory = os.path.abspath(wheel_directory)
sys.argv = sys.argv[:1] + ['bdist_wheel'] + \
config_settings["--global-option"]
_run_setup()
if wheel_directory != 'dist':
shutil.rmtree(wheel_directory)
shutil.copytree('dist', wheel_directory)
wheels = [f for f in os.listdir(wheel_directory)
if f.endswith('.whl')]
assert len(wheels) == 1
return wheels[0]
def build_sdist(sdist_directory, config_settings=None):
config_settings = _fix_config(config_settings)
sdist_directory = os.path.abspath(sdist_directory)
sys.argv = sys.argv[:1] + ['sdist'] + \
config_settings["--global-option"]
_run_setup()
if sdist_directory != 'dist':
shutil.rmtree(sdist_directory)
shutil.copytree('dist', sdist_directory)
sdists = [f for f in os.listdir(sdist_directory)
if f.endswith('.tar.gz')]
assert len(sdists) == 1
return sdists[0]
......@@ -3,6 +3,7 @@ __all__ = [
'easy_install', 'egg_info', 'install', 'install_lib', 'rotate', 'saveopts',
'sdist', 'setopt', 'test', 'install_egg_info', 'install_scripts',
'register', 'bdist_wininst', 'upload_docs', 'upload', 'build_clib',
'dist_info',
]
from distutils.command.bdist import bdist
......
......@@ -95,7 +95,9 @@ class develop(namespaces.DevelopInstaller, easy_install):
path_to_setup = egg_base.replace(os.sep, '/').rstrip('/')
if path_to_setup != os.curdir:
path_to_setup = '../' * (path_to_setup.count('/') + 1)
resolved = normalize_path(os.path.join(install_dir, egg_path, path_to_setup))
resolved = normalize_path(
os.path.join(install_dir, egg_path, path_to_setup)
)
if resolved != normalize_path(os.curdir):
raise DistutilsOptionError(
"Can't get a consistent path to setup script from"
......
"""
Create a dist_info directory
As defined in the wheel specification
"""
import os
import shutil
from distutils.core import Command
from distutils import log
class dist_info(Command):
description = 'create a .dist-info directory'
user_options = [
('egg-base=', 'e', "directory containing .egg-info directories"
" (default: top of the source tree)"),
]
def initialize_options(self):
self.egg_base = None
def finalize_options(self):
pass
def run(self):
egg_info = self.get_finalized_command('egg_info')
egg_info.run()
dist_info_dir = egg_info.egg_info[:-len('.egg-info')] + '.dist-info'
log.info("creating '{}'".format(os.path.abspath(dist_info_dir)))
bdist_wheel = self.get_finalized_command('bdist_wheel')
bdist_wheel.egg2dist(egg_info.egg_info, dist_info_dir)
if self.egg_base:
destination = os.path.join(self.egg_base, dist_info_dir)
log.info("creating '{}'".format(os.path.abspath(destination)))
shutil.move(dist_info_dir, destination)
......@@ -1817,7 +1817,7 @@ def _update_zipimporter_cache(normalized_path, cache, updater=None):
# get/del patterns instead. For more detailed information see the
# following links:
# https://github.com/pypa/setuptools/issues/202#issuecomment-202913420
# https://bitbucket.org/pypy/pypy/src/dd07756a34a41f674c0cacfbc8ae1d4cc9ea2ae4/pypy/module/zipimport/interp_zipimport.py#cl-99
# http://bit.ly/2h9itJX
old_entry = cache[p]
del cache[p]
new_entry = updater and updater(p, old_entry)
......
This diff is collapsed.
import os
import pytest
from .files import build_files
from .textwrap import DALS
futures = pytest.importorskip('concurrent.futures')
importlib = pytest.importorskip('importlib')
class BuildBackendBase(object):
def __init__(self, cwd=None, env={}, backend_name='setuptools.build_meta'):
self.cwd = cwd
self.env = env
self.backend_name = backend_name
class BuildBackend(BuildBackendBase):
"""PEP 517 Build Backend"""
def __init__(self, *args, **kwargs):
super(BuildBackend, self).__init__(*args, **kwargs)
self.pool = futures.ProcessPoolExecutor()
def __getattr__(self, name):
"""Handles aribrary function invocations on the build backend."""
def method(*args, **kw):
root = os.path.abspath(self.cwd)
caller = BuildBackendCaller(root, self.env, self.backend_name)
return self.pool.submit(caller, name, *args, **kw).result()
return method
class BuildBackendCaller(BuildBackendBase):
def __call__(self, name, *args, **kw):
"""Handles aribrary function invocations on the build backend."""
os.chdir(self.cwd)
os.environ.update(self.env)
mod = importlib.import_module(self.backend_name)
return getattr(mod, name)(*args, **kw)
@pytest.fixture
def build_backend(tmpdir):
defn = {
'setup.py': DALS("""
__import__('setuptools').setup(
name='foo',
py_modules=['hello'],
setup_requires=['six'],
)
"""),
'hello.py': DALS("""
def run():
print('hello')
"""),
}
build_files(defn, prefix=str(tmpdir))
with tmpdir.as_cwd():
yield BuildBackend(cwd='.')
def test_get_requires_for_build_wheel(build_backend):
actual = build_backend.get_requires_for_build_wheel()
expected = ['six', 'setuptools', 'wheel']
assert sorted(actual) == sorted(expected)
def test_build_wheel(build_backend):
dist_dir = os.path.abspath('pip-wheel')
os.makedirs(dist_dir)
wheel_name = build_backend.build_wheel(dist_dir)
assert os.path.isfile(os.path.join(dist_dir, wheel_name))
def test_build_sdist(build_backend):
dist_dir = os.path.abspath('pip-sdist')
os.makedirs(dist_dir)
sdist_name = build_backend.build_sdist(dist_dir)
assert os.path.isfile(os.path.join(dist_dir, sdist_name))
def test_prepare_metadata_for_build_wheel(build_backend):
dist_dir = os.path.abspath('pip-dist-info')
os.makedirs(dist_dir)
dist_info = build_backend.prepare_metadata_for_build_wheel(dist_dir)
assert os.path.isfile(os.path.join(dist_dir, dist_info, 'METADATA'))
......@@ -167,7 +167,9 @@ class TestNamespaces:
target = tmpdir / 'packages'
# use pip to install to the target directory
install_cmd = [
'pip',
sys.executable,
'-m',
'pip.__main__',
'install',
str(pkg_A),
'-t', str(target),
......
......@@ -164,7 +164,8 @@ class TestEggInfo(object):
self._run_install_command(tmpdir_cwd, env)
egg_info_dir = self._find_egg_info_files(env.paths['lib']).base
sources_txt = os.path.join(egg_info_dir, 'SOURCES.txt')
assert 'docs/usage.rst' in open(sources_txt).read().split('\n')
with open(sources_txt) as f:
assert 'docs/usage.rst' in f.read().split('\n')
def _setup_script_with_requires(self, requires, use_setup_cfg=False):
setup_script = DALS(
......@@ -447,7 +448,8 @@ class TestEggInfo(object):
self._run_install_command(tmpdir_cwd, env)
egg_info_dir = self._find_egg_info_files(env.paths['lib']).base
pkginfo = os.path.join(egg_info_dir, 'PKG-INFO')
assert 'Requires-Python: >=1.2.3' in open(pkginfo).read().split('\n')
with open(pkginfo) as f:
assert 'Requires-Python: >=1.2.3' in f.read().split('\n')
def test_manifest_maker_warning_suppression(self):
fixtures = [
......
......@@ -30,7 +30,9 @@ class TestNamespaces:
targets = site_packages, path_packages
# use pip to install to the target directory
install_cmd = [
'pip',
sys.executable,
'-m',
'pip.__main__',
'install',
str(pkg_A),
'-t', str(site_packages),
......@@ -38,7 +40,9 @@ class TestNamespaces:
subprocess.check_call(install_cmd)
namespaces.make_site_dir(site_packages)
install_cmd = [
'pip',
sys.executable,
'-m',
'pip.__main__',
'install',
str(pkg_B),
'-t', str(path_packages),
......@@ -88,7 +92,9 @@ class TestNamespaces:
target = tmpdir / 'packages'
# use pip to install to the target directory
install_cmd = [
'pip',
sys.executable,
'-m',
'pip.__main__',
'install',
str(pkg_A),
'-t', str(target),
......
......@@ -19,6 +19,7 @@ from setuptools.command.sdist import sdist
from setuptools.command.egg_info import manifest_maker
from setuptools.dist import Distribution
from setuptools.tests import fail_on_ascii
from .text import Filenames
py3_only = pytest.mark.xfail(six.PY2, reason="Test runs on Python 3 only")
......@@ -36,13 +37,7 @@ from setuptools import setup
setup(**%r)
""" % SETUP_ATTRS
if six.PY3:
LATIN1_FILENAME = 'smörbröd.py'.encode('latin-1')
else:
LATIN1_FILENAME = 'sm\xf6rbr\xf6d.py'
# Cannot use context manager because of Python 2.4
@contextlib.contextmanager
def quiet():
old_stdout, old_stderr = sys.stdout, sys.stderr
......@@ -53,17 +48,10 @@ def quiet():
sys.stdout, sys.stderr = old_stdout, old_stderr
# Fake byte literals for Python <= 2.5
def b(s, encoding='utf-8'):
if six.PY3:
return s.encode(encoding)
return s
# Convert to POSIX path
def posix(path):
if six.PY3 and not isinstance(path, str):
return path.replace(os.sep.encode('ascii'), b('/'))
return path.replace(os.sep.encode('ascii'), b'/')
else:
return path.replace(os.sep, '/')
......@@ -86,6 +74,21 @@ def read_all_bytes(filename):
return fp.read()
def latin1_fail():
try:
desc, filename = tempfile.mkstemp(suffix=Filenames.latin_1)
os.close(desc)
os.remove(filename)
except Exception:
return True
fail_on_latin1_encoded_filenames = pytest.mark.xfail(
latin1_fail(),
reason="System does not support latin-1 filenames",
)
class TestSdistTest:
def setup_method(self, method):
self.temp_dir = tempfile.mkdtemp()
......@@ -134,8 +137,8 @@ class TestSdistTest:
def test_defaults_case_sensitivity(self):
"""
Make sure default files (README.*, etc.) are added in a case-sensitive
way to avoid problems with packages built on Windows.
Make sure default files (README.*, etc.) are added in a case-sensitive
way to avoid problems with packages built on Windows.
"""
open(os.path.join(self.temp_dir, 'readme.rst'), 'w').close()
......@@ -152,7 +155,9 @@ class TestSdistTest:
with quiet():
cmd.run()
# lowercase all names so we can test in a case-insensitive way to make sure the files are not included
# lowercase all names so we can test in a
# case-insensitive way to make sure the files
# are not included.
manifest = map(lambda x: x.lower(), cmd.filelist.files)
assert 'readme.rst' not in manifest, manifest
assert 'setup.py' not in manifest, manifest
......@@ -201,8 +206,7 @@ class TestSdistTest:
mm.manifest = os.path.join('sdist_test.egg-info', 'SOURCES.txt')
os.mkdir('sdist_test.egg-info')
# UTF-8 filename
filename = os.path.join(b('sdist_test'), b('smörbröd.py'))
filename = os.path.join(b'sdist_test', Filenames.utf_8)
# Must touch the file or risk removal
open(filename, "w").close()
......@@ -241,7 +245,7 @@ class TestSdistTest:
os.mkdir('sdist_test.egg-info')
# Latin-1 filename
filename = os.path.join(b('sdist_test'), LATIN1_FILENAME)
filename = os.path.join(b'sdist_test', Filenames.latin_1)
# Add filename with surrogates and write manifest
with quiet():
......@@ -275,10 +279,10 @@ class TestSdistTest:
cmd.run()
# Add UTF-8 filename to manifest
filename = os.path.join(b('sdist_test'), b('smörbröd.py'))
filename = os.path.join(b'sdist_test', Filenames.utf_8)
cmd.manifest = os.path.join('sdist_test.egg-info', 'SOURCES.txt')
manifest = open(cmd.manifest, 'ab')
manifest.write(b('\n') + filename)
manifest.write(b'\n' + filename)
manifest.close()
# The file must exist to be included in the filelist
......@@ -295,6 +299,7 @@ class TestSdistTest:
assert filename in cmd.filelist.files
@py3_only
@fail_on_latin1_encoded_filenames
def test_read_manifest_skips_non_utf8_filenames(self):
# Test for #303.
dist = Distribution(SETUP_ATTRS)
......@@ -307,10 +312,10 @@ class TestSdistTest:
cmd.run()
# Add Latin-1 filename to manifest
filename = os.path.join(b('sdist_test'), LATIN1_FILENAME)
filename = os.path.join(b'sdist_test', Filenames.latin_1)
cmd.manifest = os.path.join('sdist_test.egg-info', 'SOURCES.txt')
manifest = open(cmd.manifest, 'ab')
manifest.write(b('\n') + filename)
manifest.write(b'\n' + filename)
manifest.close()
# The file must exist to be included in the filelist
......@@ -326,6 +331,7 @@ class TestSdistTest:
assert filename not in cmd.filelist.files
@fail_on_ascii
@fail_on_latin1_encoded_filenames
def test_sdist_with_utf8_encoded_filename(self):
# Test for #303.
dist = Distribution(SETUP_ATTRS)
......@@ -333,8 +339,7 @@ class TestSdistTest:
cmd = sdist(dist)
cmd.ensure_finalized()
# UTF-8 filename
filename = os.path.join(b('sdist_test'), b('smörbröd.py'))
filename = os.path.join(b'sdist_test', Filenames.utf_8)
open(filename, 'w').close()
with quiet():
......@@ -360,6 +365,7 @@ class TestSdistTest:
else:
assert filename in cmd.filelist.files
@fail_on_latin1_encoded_filenames
def test_sdist_with_latin1_encoded_filename(self):
# Test for #303.
dist = Distribution(SETUP_ATTRS)
......@@ -368,7 +374,7 @@ class TestSdistTest:
cmd.ensure_finalized()
# Latin-1 filename
filename = os.path.join(b('sdist_test'), LATIN1_FILENAME)
filename = os.path.join(b'sdist_test', Filenames.latin_1)
open(filename, 'w').close()
assert os.path.isfile(filename)
......@@ -381,10 +387,9 @@ class TestSdistTest:
# Latin-1 is similar to Windows-1252 however
# on mbcs filesys it is not in latin-1 encoding
fs_enc = sys.getfilesystemencoding()
if fs_enc == 'mbcs':
filename = filename.decode('mbcs')
else:
filename = filename.decode('latin-1')
if fs_enc != 'mbcs':
fs_enc = 'latin-1'
filename = filename.decode(fs_enc)
assert filename in cmd.filelist.files
else:
......
This diff is collapsed.
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
class Filenames:
unicode = 'smörbröd.py'
latin_1 = unicode.encode('latin-1')
utf_8 = unicode.encode('utf-8')
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment