aboutsummaryrefslogtreecommitdiffstats
path: root/setuptools/tests
diff options
context:
space:
mode:
Diffstat (limited to 'setuptools/tests')
-rw-r--r--setuptools/tests/__init__.py5
-rw-r--r--setuptools/tests/contexts.py10
-rw-r--r--setuptools/tests/files.py32
-rw-r--r--setuptools/tests/fixtures.py5
-rw-r--r--setuptools/tests/py26compat.py5
-rw-r--r--setuptools/tests/test_develop.py136
-rw-r--r--setuptools/tests/test_easy_install.py314
-rw-r--r--setuptools/tests/test_egg_info.py79
-rw-r--r--setuptools/tests/test_integration.py18
-rw-r--r--setuptools/tests/test_msvc9compiler.py20
-rw-r--r--setuptools/tests/test_packageindex.py33
-rw-r--r--setuptools/tests/test_sandbox.py93
-rw-r--r--setuptools/tests/test_sdist.py242
-rw-r--r--setuptools/tests/test_setuptools.py48
14 files changed, 660 insertions, 380 deletions
diff --git a/setuptools/tests/__init__.py b/setuptools/tests/__init__.py
index 8cde6f60..b2c6894f 100644
--- a/setuptools/tests/__init__.py
+++ b/setuptools/tests/__init__.py
@@ -16,6 +16,11 @@ import setuptools.depends as dep
from setuptools import Feature
from setuptools.depends import Require
+c_type = os.environ.get("LC_CTYPE", os.environ.get("LC_ALL"))
+is_ascii = c_type in ("C", "POSIX")
+fail_on_ascii = pytest.mark.xfail(is_ascii, reason="Test fails in this locale")
+
+
def makeSetup(**args):
"""Return distribution from 'setup(**args)', without executing commands"""
diff --git a/setuptools/tests/contexts.py b/setuptools/tests/contexts.py
index fabab071..d9dcad84 100644
--- a/setuptools/tests/contexts.py
+++ b/setuptools/tests/contexts.py
@@ -27,7 +27,7 @@ def environment(**replacements):
to clear the values.
"""
saved = dict(
- (key, os.environ['key'])
+ (key, os.environ[key])
for key in replacements
if key in os.environ
)
@@ -49,14 +49,6 @@ def environment(**replacements):
@contextlib.contextmanager
-def argv(repl):
- old_argv = sys.argv[:]
- sys.argv[:] = repl
- yield
- sys.argv[:] = old_argv
-
-
-@contextlib.contextmanager
def quiet():
"""
Redirect stdout/stderr to StringIO objects to prevent console output from
diff --git a/setuptools/tests/files.py b/setuptools/tests/files.py
new file mode 100644
index 00000000..4364241b
--- /dev/null
+++ b/setuptools/tests/files.py
@@ -0,0 +1,32 @@
+import os
+
+
+def build_files(file_defs, prefix=""):
+ """
+ Build a set of files/directories, as described by the file_defs dictionary.
+
+ Each key/value pair in the dictionary is interpreted as a filename/contents
+ pair. If the contents value is a dictionary, a directory is created, and the
+ dictionary interpreted as the files within it, recursively.
+
+ For example:
+
+ {"README.txt": "A README file",
+ "foo": {
+ "__init__.py": "",
+ "bar": {
+ "__init__.py": "",
+ },
+ "baz.py": "# Some code",
+ }
+ }
+ """
+ for name, contents in file_defs.items():
+ full_name = os.path.join(prefix, name)
+ if isinstance(contents, dict):
+ if not os.path.exists(full_name):
+ os.makedirs(full_name)
+ build_files(contents, prefix=full_name)
+ else:
+ with open(full_name, 'w') as f:
+ f.write(contents)
diff --git a/setuptools/tests/fixtures.py b/setuptools/tests/fixtures.py
index 0b1eaf5f..c70c38cb 100644
--- a/setuptools/tests/fixtures.py
+++ b/setuptools/tests/fixtures.py
@@ -1,4 +1,7 @@
-import mock
+try:
+ from unittest import mock
+except ImportError:
+ import mock
import pytest
from . import contexts
diff --git a/setuptools/tests/py26compat.py b/setuptools/tests/py26compat.py
index c53b4809..c5680881 100644
--- a/setuptools/tests/py26compat.py
+++ b/setuptools/tests/py26compat.py
@@ -8,4 +8,7 @@ def _tarfile_open_ex(*args, **kwargs):
"""
return contextlib.closing(tarfile.open(*args, **kwargs))
-tarfile_open = _tarfile_open_ex if sys.version_info < (2,7) else tarfile.open
+if sys.version_info[:2] < (2, 7) or (3, 0) <= sys.version_info[:2] < (3, 2):
+ tarfile_open = _tarfile_open_ex
+else:
+ tarfile_open = tarfile.open
diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py
index ed1b194a..236b3aa6 100644
--- a/setuptools/tests/test_develop.py
+++ b/setuptools/tests/test_develop.py
@@ -1,13 +1,18 @@
"""develop tests
"""
import os
-import shutil
import site
import sys
-import tempfile
+import io
+
+import six
+
+import pytest
from setuptools.command.develop import develop
from setuptools.dist import Distribution
+from . import contexts
+
SETUP_PY = """\
from setuptools import setup
@@ -21,65 +26,52 @@ setup(name='foo',
INIT_PY = """print "foo"
"""
-class TestDevelopTest:
+@pytest.yield_fixture
+def temp_user(monkeypatch):
+ with contexts.tempdir() as user_base:
+ with contexts.tempdir() as user_site:
+ monkeypatch.setattr('site.USER_BASE', user_base)
+ monkeypatch.setattr('site.USER_SITE', user_site)
+ yield
- def setup_method(self, method):
- if hasattr(sys, 'real_prefix'):
- return
- # Directory structure
- self.dir = tempfile.mkdtemp()
- os.mkdir(os.path.join(self.dir, 'foo'))
- # setup.py
- setup = os.path.join(self.dir, 'setup.py')
- f = open(setup, 'w')
+@pytest.yield_fixture
+def test_env(tmpdir, temp_user):
+ target = tmpdir
+ foo = target.mkdir('foo')
+ setup = target / 'setup.py'
+ if setup.isfile():
+ raise ValueError(dir(target))
+ with setup.open('w') as f:
f.write(SETUP_PY)
- f.close()
- self.old_cwd = os.getcwd()
- # foo/__init__.py
- init = os.path.join(self.dir, 'foo', '__init__.py')
- f = open(init, 'w')
+ init = foo / '__init__.py'
+ with init.open('w') as f:
f.write(INIT_PY)
- f.close()
-
- os.chdir(self.dir)
- self.old_base = site.USER_BASE
- site.USER_BASE = tempfile.mkdtemp()
- self.old_site = site.USER_SITE
- site.USER_SITE = tempfile.mkdtemp()
-
- def teardown_method(self, method):
- if hasattr(sys, 'real_prefix') or (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix):
- return
-
- os.chdir(self.old_cwd)
- shutil.rmtree(self.dir)
- shutil.rmtree(site.USER_BASE)
- shutil.rmtree(site.USER_SITE)
- site.USER_BASE = self.old_base
- site.USER_SITE = self.old_site
-
- def test_develop(self):
- if hasattr(sys, 'real_prefix'):
- return
- dist = Distribution(
- dict(name='foo',
- packages=['foo'],
- use_2to3=True,
- version='0.0',
- ))
+ with target.as_cwd():
+ yield target
+
+
+class TestDevelop:
+ in_virtualenv = hasattr(sys, 'real_prefix')
+ in_venv = hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix
+ @pytest.mark.skipif(in_virtualenv or in_venv,
+ reason="Cannot run when invoked in a virtualenv or venv")
+ def test_2to3_user_mode(self, test_env):
+ settings = dict(
+ name='foo',
+ packages=['foo'],
+ use_2to3=True,
+ version='0.0',
+ )
+ dist = Distribution(settings)
dist.script_name = 'setup.py'
cmd = develop(dist)
cmd.user = 1
cmd.ensure_finalized()
cmd.install_dir = site.USER_SITE
cmd.user = 1
- old_stdout = sys.stdout
- #sys.stdout = StringIO()
- try:
+ with contexts.quiet():
cmd.run()
- finally:
- sys.stdout = old_stdout
# let's see if we got our egg link at the right place
content = os.listdir(site.USER_SITE)
@@ -87,17 +79,37 @@ class TestDevelopTest:
assert content == ['easy-install.pth', 'foo.egg-link']
# Check that we are using the right code.
- egg_link_file = open(os.path.join(site.USER_SITE, 'foo.egg-link'), 'rt')
- try:
+ fn = os.path.join(site.USER_SITE, 'foo.egg-link')
+ with io.open(fn) as egg_link_file:
path = egg_link_file.read().split()[0].strip()
- finally:
- egg_link_file.close()
- init_file = open(os.path.join(path, 'foo', '__init__.py'), 'rt')
- try:
+ fn = os.path.join(path, 'foo', '__init__.py')
+ with io.open(fn) as init_file:
init = init_file.read().strip()
- finally:
- init_file.close()
- if sys.version < "3":
- assert init == 'print "foo"'
- else:
- assert init == 'print("foo")'
+
+ expected = 'print("foo")' if six.PY3 else 'print "foo"'
+ assert init == expected
+
+ def test_console_scripts(self, tmpdir):
+ """
+ Test that console scripts are installed and that they reference
+ only the project by name and not the current version.
+ """
+ pytest.skip("TODO: needs a fixture to cause 'develop' "
+ "to be invoked without mutating environment.")
+ settings = dict(
+ name='foo',
+ packages=['foo'],
+ version='0.0',
+ entry_points={
+ 'console_scripts': [
+ 'foocmd = foo:foo',
+ ],
+ },
+ )
+ dist = Distribution(settings)
+ dist.script_name = 'setup.py'
+ cmd = develop(dist)
+ cmd.ensure_finalized()
+ cmd.install_dir = tmpdir
+ cmd.run()
+ #assert '0.0' not in foocmd_text
diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py
index 5d5ec16d..30220b7f 100644
--- a/setuptools/tests/test_easy_install.py
+++ b/setuptools/tests/test_easy_install.py
@@ -1,4 +1,4 @@
-#! -*- coding: utf-8 -*-
+# -*- coding: utf-8 -*-
"""Easy install Tests
"""
@@ -13,29 +13,30 @@ import contextlib
import tarfile
import logging
import itertools
+import distutils.errors
import io
import six
from six.moves import urllib
import pytest
-import mock
+try:
+ from unittest import mock
+except ImportError:
+ import mock
from setuptools import sandbox
-from setuptools.sandbox import run_setup, SandboxViolation
-from setuptools.command.easy_install import (
- easy_install, fix_jython_executable, get_script_args, nt_quote_arg,
- get_script_header, is_sh,
-)
+from setuptools.sandbox import run_setup
+import setuptools.command.easy_install as ei
from setuptools.command.easy_install import PthDistributions
from setuptools.command import easy_install as easy_install_pkg
from setuptools.dist import Distribution
-from pkg_resources import working_set, VersionConflict
+from pkg_resources import working_set
from pkg_resources import Distribution as PRDistribution
import setuptools.tests.server
import pkg_resources
from .py26compat import tarfile_open
-from . import contexts
+from . import contexts, is_ascii
from .textwrap import DALS
@@ -48,19 +49,6 @@ class FakeDist(object):
def as_requirement(self):
return 'spec'
-WANTED = DALS("""
- #!%s
- # EASY-INSTALL-ENTRY-SCRIPT: 'spec','console_scripts','name'
- __requires__ = 'spec'
- import sys
- from pkg_resources import load_entry_point
-
- if __name__ == '__main__':
- sys.exit(
- load_entry_point('spec', 'console_scripts', 'name')()
- )
- """) % nt_quote_arg(fix_jython_executable(sys.executable, ""))
-
SETUP_PY = DALS("""
from setuptools import setup
@@ -71,7 +59,7 @@ class TestEasyInstallTest:
def test_install_site_py(self):
dist = Distribution()
- cmd = easy_install(dist)
+ cmd = ei.easy_install(dist)
cmd.sitepy_installed = False
cmd.install_dir = tempfile.mkdtemp()
try:
@@ -82,18 +70,30 @@ class TestEasyInstallTest:
shutil.rmtree(cmd.install_dir)
def test_get_script_args(self):
+ header = ei.CommandSpec.best().from_environment().as_header()
+ expected = header + DALS("""
+ # EASY-INSTALL-ENTRY-SCRIPT: 'spec','console_scripts','name'
+ __requires__ = 'spec'
+ import sys
+ from pkg_resources import load_entry_point
+
+ if __name__ == '__main__':
+ sys.exit(
+ load_entry_point('spec', 'console_scripts', 'name')()
+ )
+ """)
dist = FakeDist()
- args = next(get_script_args(dist))
+ args = next(ei.ScriptWriter.get_args(dist))
name, script = itertools.islice(args, 2)
- assert script == WANTED
+ assert script == expected
def test_no_find_links(self):
# new option '--no-find-links', that blocks find-links added at
# the project level
dist = Distribution()
- cmd = easy_install(dist)
+ cmd = ei.easy_install(dist)
cmd.check_pth_processing = lambda: True
cmd.no_find_links = True
cmd.find_links = ['link1', 'link2']
@@ -103,7 +103,7 @@ class TestEasyInstallTest:
assert cmd.package_index.scanned_urls == {}
# let's try without it (default behavior)
- cmd = easy_install(dist)
+ cmd = ei.easy_install(dist)
cmd.check_pth_processing = lambda: True
cmd.find_links = ['link1', 'link2']
cmd.install_dir = os.path.join(tempfile.mkdtemp(), 'ok')
@@ -112,6 +112,16 @@ class TestEasyInstallTest:
keys = sorted(cmd.package_index.scanned_urls.keys())
assert keys == ['link1', 'link2']
+ def test_write_exception(self):
+ """
+ Test that `cant_write_to_target` is rendered as a DistutilsError.
+ """
+ dist = Distribution()
+ cmd = ei.easy_install(dist)
+ cmd.install_dir = os.getcwd()
+ with pytest.raises(distutils.errors.DistutilsError):
+ cmd.cant_write_to_target()
+
class TestPTHFileWriter:
def test_add_from_cwd_site_sets_dirty(self):
@@ -145,77 +155,74 @@ def setup_context(tmpdir):
@pytest.mark.usefixtures("setup_context")
class TestUserInstallTest:
- @mock.patch('setuptools.command.easy_install.__file__', None)
- def test_user_install_implied(self):
- easy_install_pkg.__file__ = site.USER_SITE
- site.ENABLE_USER_SITE = True # disabled sometimes
- #XXX: replace with something meaningfull
+ # prevent check that site-packages is writable. easy_install
+ # shouldn't be writing to system site-packages during finalize
+ # options, but while it does, bypass the behavior.
+ prev_sp_write = mock.patch(
+ 'setuptools.command.easy_install.easy_install.check_site_dir',
+ mock.Mock(),
+ )
+
+ # simulate setuptools installed in user site packages
+ @mock.patch('setuptools.command.easy_install.__file__', site.USER_SITE)
+ @mock.patch('site.ENABLE_USER_SITE', True)
+ @prev_sp_write
+ def test_user_install_not_implied_user_site_enabled(self):
+ self.assert_not_user_site()
+
+ @mock.patch('site.ENABLE_USER_SITE', False)
+ @prev_sp_write
+ def test_user_install_not_implied_user_site_disabled(self):
+ self.assert_not_user_site()
+
+ @staticmethod
+ def assert_not_user_site():
+ # create a finalized easy_install command
dist = Distribution()
dist.script_name = 'setup.py'
- cmd = easy_install(dist)
+ cmd = ei.easy_install(dist)
cmd.args = ['py']
cmd.ensure_finalized()
- assert cmd.user, 'user should be implied'
+ assert not cmd.user, 'user should not be implied'
def test_multiproc_atexit(self):
- try:
- __import__('multiprocessing')
- except ImportError:
- # skip the test if multiprocessing is not available
- return
+ pytest.importorskip('multiprocessing')
log = logging.getLogger('test_easy_install')
logging.basicConfig(level=logging.INFO, stream=sys.stderr)
log.info('this should not break')
- def test_user_install_not_implied_without_usersite_enabled(self):
- site.ENABLE_USER_SITE = False # usually enabled
- #XXX: replace with something meaningfull
- dist = Distribution()
- dist.script_name = 'setup.py'
- cmd = easy_install(dist)
- cmd.args = ['py']
- cmd.initialize_options()
- assert not cmd.user, 'NOT user should be implied'
-
- def test_local_index(self):
- # make sure the local index is used
- # when easy_install looks for installed
- # packages
- new_location = tempfile.mkdtemp()
- target = tempfile.mkdtemp()
- egg_file = os.path.join(new_location, 'foo-1.0.egg-info')
- with open(egg_file, 'w') as f:
+ @pytest.fixture()
+ def foo_package(self, tmpdir):
+ egg_file = tmpdir / 'foo-1.0.egg-info'
+ with egg_file.open('w') as f:
f.write('Name: foo\n')
+ return str(tmpdir)
- sys.path.append(target)
- old_ppath = os.environ.get('PYTHONPATH')
- os.environ['PYTHONPATH'] = os.path.pathsep.join(sys.path)
- try:
- dist = Distribution()
- dist.script_name = 'setup.py'
- cmd = easy_install(dist)
- cmd.install_dir = target
- cmd.args = ['foo']
- cmd.ensure_finalized()
- cmd.local_index.scan([new_location])
- res = cmd.easy_install('foo')
- actual = os.path.normcase(os.path.realpath(res.location))
- expected = os.path.normcase(os.path.realpath(new_location))
- assert actual == expected
- finally:
- sys.path.remove(target)
- for basedir in [new_location, target, ]:
- if not os.path.exists(basedir) or not os.path.isdir(basedir):
- continue
- try:
- shutil.rmtree(basedir)
- except:
- pass
- if old_ppath is not None:
- os.environ['PYTHONPATH'] = old_ppath
- else:
- del os.environ['PYTHONPATH']
+ @pytest.yield_fixture()
+ def install_target(self, tmpdir):
+ target = str(tmpdir)
+ with mock.patch('sys.path', sys.path + [target]):
+ python_path = os.path.pathsep.join(sys.path)
+ with mock.patch.dict(os.environ, PYTHONPATH=python_path):
+ yield target
+
+ def test_local_index(self, foo_package, install_target):
+ """
+ The local index must be used when easy_install locates installed
+ packages.
+ """
+ dist = Distribution()
+ dist.script_name = 'setup.py'
+ cmd = ei.easy_install(dist)
+ cmd.install_dir = install_target
+ cmd.args = ['foo']
+ cmd.ensure_finalized()
+ cmd.local_index.scan([foo_package])
+ res = cmd.easy_install('foo')
+ actual = os.path.normcase(os.path.realpath(res.location))
+ expected = os.path.normcase(os.path.realpath(foo_package))
+ assert actual == expected
@contextlib.contextmanager
def user_install_setup_context(self, *args, **kwargs):
@@ -236,28 +243,6 @@ class TestUserInstallTest:
self.user_install_setup_context,
)
- def test_setup_requires(self):
- """Regression test for Distribute issue #318
-
- Ensure that a package with setup_requires can be installed when
- setuptools is installed in the user site-packages without causing a
- SandboxViolation.
- """
-
- test_pkg = create_setup_requires_package(os.getcwd())
- test_setup_py = os.path.join(test_pkg, 'setup.py')
-
- try:
- with contexts.quiet():
- with self.patched_setup_context():
- 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
-
@pytest.yield_fixture
def distutils_package():
@@ -305,7 +290,7 @@ class TestSetupRequires:
'--install-dir', temp_install_dir,
dist_file,
]
- with contexts.argv(['easy_install']):
+ with sandbox.save_argv(['easy_install']):
# attempt to install the dist. It should fail because
# it doesn't exist.
with pytest.raises(SystemExit):
@@ -354,13 +339,9 @@ class TestSetupRequires:
test_pkg = create_setup_requires_package(temp_dir)
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 VersionConflict:
- self.fail('Installing setup.py requirements '
- 'caused a VersionConflict')
+ # Don't even need to install the package, just
+ # running the setup.py at all is sufficient
+ run_setup(test_setup_py, ['--name'])
lines = stdout.readlines()
assert len(lines) > 0
@@ -422,23 +403,31 @@ class TestScriptHeader:
exe_with_spaces = r'C:\Program Files\Python33\python.exe'
@pytest.mark.skipif(
- sys.platform.startswith('java') and is_sh(sys.executable),
+ sys.platform.startswith('java') and ei.is_sh(sys.executable),
reason="Test cannot run under java when executable is sh"
)
def test_get_script_header(self):
- expected = '#!%s\n' % nt_quote_arg(os.path.normpath(sys.executable))
- assert get_script_header('#!/usr/local/bin/python') == expected
- expected = '#!%s -x\n' % nt_quote_arg(os.path.normpath(sys.executable))
- assert get_script_header('#!/usr/bin/python -x') == expected
- candidate = get_script_header('#!/usr/bin/python',
+ expected = '#!%s\n' % ei.nt_quote_arg(os.path.normpath(sys.executable))
+ actual = ei.ScriptWriter.get_script_header('#!/usr/local/bin/python')
+ assert actual == expected
+
+ expected = '#!%s -x\n' % ei.nt_quote_arg(os.path.normpath
+ (sys.executable))
+ actual = ei.ScriptWriter.get_script_header('#!/usr/bin/python -x')
+ assert actual == expected
+
+ actual = ei.ScriptWriter.get_script_header('#!/usr/bin/python',
executable=self.non_ascii_exe)
- assert candidate == '#!%s -x\n' % self.non_ascii_exe
- candidate = get_script_header('#!/usr/bin/python',
- executable=self.exe_with_spaces)
- assert candidate == '#!"%s"\n' % self.exe_with_spaces
+ expected = '#!%s -x\n' % self.non_ascii_exe
+ assert actual == expected
+
+ actual = ei.ScriptWriter.get_script_header('#!/usr/bin/python',
+ executable='"'+self.exe_with_spaces+'"')
+ expected = '#!"%s"\n' % self.exe_with_spaces
+ assert actual == expected
@pytest.mark.xfail(
- six.PY3 and os.environ.get("LC_CTYPE") in ("C", "POSIX"),
+ 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=
@@ -453,9 +442,15 @@ class TestScriptHeader:
exe = tmpdir / 'exe.py'
with exe.open('w') as f:
f.write(header)
- exe = str(exe)
- header = get_script_header('#!/usr/local/bin/python', executable=exe)
+ 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'
@@ -463,15 +458,70 @@ class TestScriptHeader:
with contexts.quiet() as (stdout, stderr):
# When options are included, generate a broken shebang line
# with a warning emitted
- candidate = get_script_header('#!/usr/bin/python -x',
- executable=exe)
- assert candidate == '#!%s -x\n' % exe
+ 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 = get_script_header('#!/usr/bin/python',
+ 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):
+ """
+ Show how a custom CommandSpec could be used to specify a #! executable
+ which takes parameters.
+ """
+ cmd = ei.CommandSpec(['/usr/bin/env', 'python3'])
+ assert cmd.as_header() == '#!/usr/bin/env python3\n'
+
+ def test_from_param_for_CommandSpec_is_passthrough(self):
+ """
+ from_param should return an instance of a CommandSpec
+ """
+ cmd = ei.CommandSpec(['python'])
+ cmd_new = ei.CommandSpec.from_param(cmd)
+ assert cmd is cmd_new
+
+ @mock.patch('sys.executable', TestScriptHeader.exe_with_spaces)
+ @mock.patch.dict(os.environ)
+ def test_from_environment_with_spaces_in_executable(self):
+ os.environ.pop('__PYVENV_LAUNCHER__', None)
+ cmd = ei.CommandSpec.from_environment()
+ assert len(cmd) == 1
+ assert cmd.as_header().startswith('#!"')
+
+ def test_from_simple_string_uses_shlex(self):
+ """
+ In order to support `executable = /usr/bin/env my-python`, make sure
+ from_param invokes shlex on that input.
+ """
+ cmd = ei.CommandSpec.from_param('/usr/bin/env my-python')
+ assert len(cmd) == 2
+ assert '"' not in cmd.as_header()
+
+ def test_sys_executable(self):
+ """
+ CommandSpec.from_string(sys.executable) should contain just that param.
+ """
+ writer = ei.ScriptWriter.best()
+ cmd = writer.command_spec_class.from_string(sys.executable)
+ assert len(cmd) == 1
+ assert cmd[0] == sys.executable
+
+
+class TestWindowsScriptWriter:
+ def test_header(self):
+ hdr = ei.WindowsScriptWriter.get_script_header('')
+ assert hdr.startswith('#!')
+ assert hdr.endswith('\n')
+ hdr = hdr.lstrip('#!')
+ hdr = hdr.rstrip('\n')
+ # header should not start with an escaped quote
+ assert not hdr.startswith('\\"')
diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py
index a1caf9fd..333d11d6 100644
--- a/setuptools/tests/test_egg_info.py
+++ b/setuptools/tests/test_egg_info.py
@@ -4,11 +4,16 @@ import stat
import pytest
from . import environment
+from .files import build_files
from .textwrap import DALS
from . import contexts
-class TestEggInfo:
+class Environment(str):
+ pass
+
+
+class TestEggInfo(object):
setup_script = DALS("""
from setuptools import setup
@@ -22,19 +27,16 @@ class TestEggInfo:
""")
def _create_project(self):
- with open('setup.py', 'w') as f:
- f.write(self.setup_script)
-
- with open('hello.py', 'w') as f:
- f.write(DALS("""
+ build_files({
+ 'setup.py': self.setup_script,
+ 'hello.py': DALS("""
def run():
print('hello')
- """))
+ """)
+ })
@pytest.yield_fixture
def env(self):
- class Environment(str): pass
-
with contexts.tempdir(prefix='setuptools-test.') as env_dir:
env = Environment(env_dir)
os.chmod(env_dir, stat.S_IRWXU)
@@ -44,18 +46,48 @@ class TestEggInfo:
for dirname in subs
)
list(map(os.mkdir, env.paths.values()))
- config = os.path.join(env.paths['home'], '.pydistutils.cfg')
- with open(config, 'w') as f:
- f.write(DALS("""
+ build_files({
+ env.paths['home']: {
+ '.pydistutils.cfg': DALS("""
[egg_info]
egg-base = %(egg-base)s
- """ % env.paths
- ))
+ """ % env.paths)
+ }
+ })
yield env
def test_egg_base_installed_egg_info(self, tmpdir_cwd, env):
self._create_project()
+ self._run_install_command(tmpdir_cwd, env)
+ actual = self._find_egg_info_files(env.paths['lib'])
+
+ expected = [
+ 'PKG-INFO',
+ 'SOURCES.txt',
+ 'dependency_links.txt',
+ 'entry_points.txt',
+ 'not-zip-safe',
+ 'top_level.txt',
+ ]
+ assert sorted(actual) == expected
+
+ def test_manifest_template_is_read(self, tmpdir_cwd, env):
+ self._create_project()
+ build_files({
+ 'MANIFEST.in': DALS("""
+ recursive-include docs *.rst
+ """),
+ 'docs': {
+ 'usage.rst': "Run 'hi'",
+ }
+ })
+ 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')
+
+ def _run_install_command(self, tmpdir_cwd, env):
environ = os.environ.copy().update(
HOME=env.paths['home'],
)
@@ -75,21 +107,14 @@ class TestEggInfo:
if code:
raise AssertionError(data)
- actual = self._find_egg_info_files(env.paths['lib'])
-
- expected = [
- 'PKG-INFO',
- 'SOURCES.txt',
- 'dependency_links.txt',
- 'entry_points.txt',
- 'not-zip-safe',
- 'top_level.txt',
- ]
- assert sorted(actual) == expected
-
def _find_egg_info_files(self, root):
+ class DirList(list):
+ def __init__(self, files, base):
+ super(DirList, self).__init__(files)
+ self.base = base
+
results = (
- filenames
+ DirList(filenames, dirpath)
for dirpath, dirnames, filenames in os.walk(root)
if os.path.basename(dirpath) == 'EGG-INFO'
)
diff --git a/setuptools/tests/test_integration.py b/setuptools/tests/test_integration.py
index 3a6abeaa..11a6ff5a 100644
--- a/setuptools/tests/test_integration.py
+++ b/setuptools/tests/test_integration.py
@@ -7,6 +7,8 @@ import glob
import os
import sys
+from six.moves import urllib
+
import pytest
from setuptools.command.easy_install import easy_install
@@ -14,6 +16,22 @@ from setuptools.command import easy_install as easy_install_pkg
from setuptools.dist import Distribution
+def setup_module(module):
+ packages = 'stevedore', 'virtualenvwrapper', 'pbr', 'novaclient'
+ for pkg in packages:
+ try:
+ __import__(pkg)
+ tmpl = "Integration tests cannot run when {pkg} is installed"
+ pytest.skip(tmpl.format(**locals()))
+ except ImportError:
+ pass
+
+ try:
+ urllib.request.urlopen('https://pypi.python.org/pypi')
+ except Exception as exc:
+ pytest.skip(str(exc))
+
+
@pytest.fixture
def install_context(request, tmpdir, monkeypatch):
"""Fixture to set up temporary installation directory.
diff --git a/setuptools/tests/test_msvc9compiler.py b/setuptools/tests/test_msvc9compiler.py
index a0820fff..09e0460c 100644
--- a/setuptools/tests/test_msvc9compiler.py
+++ b/setuptools/tests/test_msvc9compiler.py
@@ -7,7 +7,10 @@ import contextlib
import distutils.errors
import pytest
-import mock
+try:
+ from unittest import mock
+except ImportError:
+ import mock
from . import contexts
@@ -110,7 +113,8 @@ class TestModulePatch:
Ensure user's settings are preferred.
"""
result = distutils.msvc9compiler.find_vcvarsall(9.0)
- assert user_preferred_setting == result
+ expected = os.path.join(user_preferred_setting, 'vcvarsall.bat')
+ assert expected == result
@pytest.yield_fixture
def local_machine_setting(self):
@@ -131,13 +135,14 @@ class TestModulePatch:
Ensure machine setting is honored if user settings are not present.
"""
result = distutils.msvc9compiler.find_vcvarsall(9.0)
- assert local_machine_setting == result
+ expected = os.path.join(local_machine_setting, 'vcvarsall.bat')
+ assert expected == result
@pytest.yield_fixture
def x64_preferred_setting(self):
"""
Set up environment with 64-bit and 32-bit system settings configured
- and yield the 64-bit location.
+ and yield the canonical location.
"""
with self.mock_install_dir() as x32_dir:
with self.mock_install_dir() as x64_dir:
@@ -150,14 +155,15 @@ class TestModulePatch:
},
)
with reg:
- yield x64_dir
+ yield x32_dir
def test_ensure_64_bit_preferred(self, x64_preferred_setting):
"""
Ensure 64-bit system key is preferred.
"""
result = distutils.msvc9compiler.find_vcvarsall(9.0)
- assert x64_preferred_setting == result
+ expected = os.path.join(x64_preferred_setting, 'vcvarsall.bat')
+ assert expected == result
@staticmethod
@contextlib.contextmanager
@@ -170,4 +176,4 @@ class TestModulePatch:
vcvarsall = os.path.join(result, 'vcvarsall.bat')
with open(vcvarsall, 'w'):
pass
- yield
+ yield result
diff --git a/setuptools/tests/test_packageindex.py b/setuptools/tests/test_packageindex.py
index 4eb98bb1..dca4c2aa 100644
--- a/setuptools/tests/test_packageindex.py
+++ b/setuptools/tests/test_packageindex.py
@@ -1,9 +1,13 @@
+from __future__ import absolute_import
+
import sys
+import os
import distutils.errors
import six
from six.moves import urllib, http_client
+from .textwrap import DALS
import pkg_resources
import setuptools.package_index
from setuptools.tests.server import IndexServer
@@ -16,8 +20,7 @@ class TestPackageIndex:
url = 'http://127.0.0.1:0/nonesuch/test_package_index'
try:
v = index.open_url(url)
- except Exception:
- v = sys.exc_info()[1]
+ except Exception as v:
assert url in str(v)
else:
assert isinstance(v, urllib.error.HTTPError)
@@ -33,8 +36,7 @@ class TestPackageIndex:
url = 'url:%20https://svn.plone.org/svn/collective/inquant.contentmirror.plone/trunk'
try:
v = index.open_url(url)
- except Exception:
- v = sys.exc_info()[1]
+ except Exception as v:
assert url in str(v)
else:
assert isinstance(v, urllib.error.HTTPError)
@@ -51,8 +53,7 @@ class TestPackageIndex:
url = 'http://example.com'
try:
v = index.open_url(url)
- except Exception:
- v = sys.exc_info()[1]
+ except Exception as v:
assert 'line' in str(v)
else:
raise AssertionError('Should have raise here!')
@@ -69,8 +70,7 @@ class TestPackageIndex:
url = 'http://http://svn.pythonpaste.org/Paste/wphp/trunk'
try:
index.open_url(url)
- except distutils.errors.DistutilsError:
- error = sys.exc_info()[1]
+ except distutils.errors.DistutilsError as error:
msg = six.text_type(error)
assert 'nonnumeric port' in msg or 'getaddrinfo failed' in msg or 'Name or service not known' in msg
return
@@ -206,3 +206,20 @@ class TestContentCheckers:
'http://foo/bar#md5=f12895fdffbd45007040d2e44df98478')
rep = checker.report(lambda x: x, 'My message about %s')
assert rep == 'My message about md5'
+
+
+class TestPyPIConfig:
+ def test_percent_in_password(self, tmpdir, monkeypatch):
+ monkeypatch.setitem(os.environ, 'HOME', str(tmpdir))
+ pypirc = tmpdir / '.pypirc'
+ with pypirc.open('w') as strm:
+ strm.write(DALS("""
+ [pypi]
+ repository=https://pypi.python.org
+ username=jaraco
+ password=pity%
+ """))
+ cfg = setuptools.package_index.PyPIConfig()
+ cred = cfg.creds_by_repository['https://pypi.python.org']
+ assert cred.username == 'jaraco'
+ assert cred.password == 'pity%'
diff --git a/setuptools/tests/test_sandbox.py b/setuptools/tests/test_sandbox.py
index 6e5ce04a..fefd46f7 100644
--- a/setuptools/tests/test_sandbox.py
+++ b/setuptools/tests/test_sandbox.py
@@ -7,7 +7,7 @@ import pytest
import pkg_resources
import setuptools.sandbox
-from setuptools.sandbox import DirectorySandbox, SandboxViolation
+from setuptools.sandbox import DirectorySandbox
class TestSandbox:
@@ -33,10 +33,8 @@ class TestSandbox:
target = os.path.join(gen_py, 'test_write')
sandbox = DirectorySandbox(str(tmpdir))
try:
- try:
- sandbox.run(self._file_writer(target))
- except SandboxViolation:
- self.fail("Could not create gen_py file due to SandboxViolation")
+ # attempt to create gen_py file
+ sandbox.run(self._file_writer(target))
finally:
if os.path.exists(target):
os.remove(target)
@@ -56,3 +54,88 @@ class TestSandbox:
with setup_py.open('wb') as stream:
stream.write(b'"degenerate script"\r\n')
setuptools.sandbox._execfile(str(setup_py), globals())
+
+
+class TestExceptionSaver:
+ def test_exception_trapped(self):
+ with setuptools.sandbox.ExceptionSaver():
+ raise ValueError("details")
+
+ def test_exception_resumed(self):
+ with setuptools.sandbox.ExceptionSaver() as saved_exc:
+ raise ValueError("details")
+
+ with pytest.raises(ValueError) as caught:
+ saved_exc.resume()
+
+ assert isinstance(caught.value, ValueError)
+ assert str(caught.value) == 'details'
+
+ def test_exception_reconstructed(self):
+ orig_exc = ValueError("details")
+
+ with setuptools.sandbox.ExceptionSaver() as saved_exc:
+ raise orig_exc
+
+ with pytest.raises(ValueError) as caught:
+ saved_exc.resume()
+
+ assert isinstance(caught.value, ValueError)
+ assert caught.value is not orig_exc
+
+ def test_no_exception_passes_quietly(self):
+ with setuptools.sandbox.ExceptionSaver() as saved_exc:
+ pass
+
+ saved_exc.resume()
+
+ def test_unpickleable_exception(self):
+ class CantPickleThis(Exception):
+ "This Exception is unpickleable because it's not in globals"
+
+ with setuptools.sandbox.ExceptionSaver() as saved_exc:
+ raise CantPickleThis('detail')
+
+ with pytest.raises(setuptools.sandbox.UnpickleableException) as caught:
+ saved_exc.resume()
+
+ assert str(caught.value) == "CantPickleThis('detail',)"
+
+ def test_unpickleable_exception_when_hiding_setuptools(self):
+ """
+ As revealed in #440, an infinite recursion can occur if an unpickleable
+ exception while setuptools is hidden. Ensure this doesn't happen.
+ """
+ class ExceptionUnderTest(Exception):
+ """
+ An unpickleable exception (not in globals).
+ """
+
+ with pytest.raises(setuptools.sandbox.UnpickleableException) as caught:
+ with setuptools.sandbox.save_modules():
+ setuptools.sandbox.hide_setuptools()
+ raise ExceptionUnderTest()
+
+ msg, = caught.value.args
+ assert msg == 'ExceptionUnderTest()'
+
+ def test_sandbox_violation_raised_hiding_setuptools(self, tmpdir):
+ """
+ When in a sandbox with setuptools hidden, a SandboxViolation
+ should reflect a proper exception and not be wrapped in
+ an UnpickleableException.
+ """
+ def write_file():
+ "Trigger a SandboxViolation by writing outside the sandbox"
+ with open('/etc/foo', 'w'):
+ pass
+ sandbox = DirectorySandbox(str(tmpdir))
+ with pytest.raises(setuptools.sandbox.SandboxViolation) as caught:
+ with setuptools.sandbox.save_modules():
+ setuptools.sandbox.hide_setuptools()
+ sandbox.run(write_file)
+
+ cmd, args, kwargs = caught.value.args
+ assert cmd == 'open'
+ assert args == ('/etc/foo', 'w')
+ assert kwargs == {}
diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py
index d30e21ac..c173d713 100644
--- a/setuptools/tests/test_sdist.py
+++ b/setuptools/tests/test_sdist.py
@@ -1,13 +1,13 @@
# -*- coding: utf-8 -*-
"""sdist tests"""
-import locale
import os
import shutil
import sys
import tempfile
import unicodedata
import contextlib
+import io
import six
import pytest
@@ -16,6 +16,11 @@ import pkg_resources
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
+
+
+py3_only = pytest.mark.xfail(six.PY2, reason="Test runs on Python 3 only")
+
SETUP_ATTRS = {
'name': 'sdist_test',
@@ -77,6 +82,11 @@ def decompose(path):
return path
+def read_all_bytes(filename):
+ with io.open(filename, 'rb') as fp:
+ return fp.read()
+
+
class TestSdistTest:
def setup_method(self, method):
@@ -147,6 +157,7 @@ class TestSdistTest:
assert 'setup.py' not in manifest, manifest
assert 'setup.cfg' not in manifest, manifest
+ @fail_on_ascii
def test_manifest_is_written_with_utf8_encoding(self):
# Test for #303.
dist = Distribution(SETUP_ATTRS)
@@ -167,16 +178,10 @@ class TestSdistTest:
mm.filelist.append(filename)
mm.write_manifest()
- manifest = open(mm.manifest, 'rbU')
- contents = manifest.read()
- manifest.close()
+ contents = read_all_bytes(mm.manifest)
# The manifest should be UTF-8 encoded
- try:
- u_contents = contents.decode('UTF-8')
- except UnicodeDecodeError:
- e = sys.exc_info()[1]
- self.fail(e)
+ u_contents = contents.decode('UTF-8')
# The manifest should contain the UTF-8 filename
if six.PY2:
@@ -185,89 +190,78 @@ class TestSdistTest:
assert posix(filename) in u_contents
- # Python 3 only
- if six.PY3:
+ @py3_only
+ @fail_on_ascii
+ def test_write_manifest_allows_utf8_filenames(self):
+ # Test for #303.
+ dist = Distribution(SETUP_ATTRS)
+ dist.script_name = 'setup.py'
+ mm = manifest_maker(dist)
+ mm.manifest = os.path.join('sdist_test.egg-info', 'SOURCES.txt')
+ os.mkdir('sdist_test.egg-info')
- def test_write_manifest_allows_utf8_filenames(self):
- # Test for #303.
- dist = Distribution(SETUP_ATTRS)
- dist.script_name = 'setup.py'
- mm = manifest_maker(dist)
- 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'))
-
- # Must touch the file or risk removal
- open(filename, "w").close()
-
- # Add filename and write manifest
- with quiet():
- mm.run()
- u_filename = filename.decode('utf-8')
- mm.filelist.files.append(u_filename)
- # Re-write manifest
- mm.write_manifest()
-
- manifest = open(mm.manifest, 'rbU')
- contents = manifest.read()
- manifest.close()
-
- # The manifest should be UTF-8 encoded
- try:
- contents.decode('UTF-8')
- except UnicodeDecodeError:
- e = sys.exc_info()[1]
- self.fail(e)
-
- # The manifest should contain the UTF-8 filename
- assert posix(filename) in contents
-
- # The filelist should have been updated as well
- assert u_filename in mm.filelist.files
-
- def test_write_manifest_skips_non_utf8_filenames(self):
- """
- 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)
- mm.manifest = os.path.join('sdist_test.egg-info', 'SOURCES.txt')
- os.mkdir('sdist_test.egg-info')
-
- # Latin-1 filename
- filename = os.path.join(b('sdist_test'), LATIN1_FILENAME)
-
- # Add filename with surrogates and write manifest
- with quiet():
- mm.run()
- u_filename = filename.decode('utf-8', 'surrogateescape')
- mm.filelist.append(u_filename)
- # Re-write manifest
- mm.write_manifest()
-
- manifest = open(mm.manifest, 'rbU')
- contents = manifest.read()
- manifest.close()
-
- # The manifest should be UTF-8 encoded
- try:
- contents.decode('UTF-8')
- except UnicodeDecodeError:
- e = sys.exc_info()[1]
- self.fail(e)
+ # UTF-8 filename
+ filename = os.path.join(b('sdist_test'), b('smörbröd.py'))
- # The Latin-1 filename should have been skipped
- assert posix(filename) not in contents
+ # Must touch the file or risk removal
+ open(filename, "w").close()
- # The filelist should have been updated as well
- assert u_filename not in mm.filelist.files
+ # Add filename and write manifest
+ with quiet():
+ mm.run()
+ u_filename = filename.decode('utf-8')
+ mm.filelist.files.append(u_filename)
+ # Re-write manifest
+ mm.write_manifest()
+
+ contents = read_all_bytes(mm.manifest)
+
+ # The manifest should be UTF-8 encoded
+ contents.decode('UTF-8')
+
+ # The manifest should contain the UTF-8 filename
+ assert posix(filename) in contents
+
+ # The filelist should have been updated as well
+ assert u_filename in mm.filelist.files
+ @py3_only
+ def test_write_manifest_skips_non_utf8_filenames(self):
+ """
+ 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)
+ mm.manifest = os.path.join('sdist_test.egg-info', 'SOURCES.txt')
+ os.mkdir('sdist_test.egg-info')
+
+ # Latin-1 filename
+ filename = os.path.join(b('sdist_test'), LATIN1_FILENAME)
+
+ # Add filename with surrogates and write manifest
+ with quiet():
+ mm.run()
+ u_filename = filename.decode('utf-8', 'surrogateescape')
+ mm.filelist.append(u_filename)
+ # Re-write manifest
+ mm.write_manifest()
+
+ contents = read_all_bytes(mm.manifest)
+
+ # The manifest should be UTF-8 encoded
+ contents.decode('UTF-8')
+
+ # The Latin-1 filename should have been skipped
+ assert posix(filename) not in contents
+
+ # The filelist should have been updated as well
+ assert u_filename not in mm.filelist.files
+
+ @fail_on_ascii
def test_manifest_is_read_with_utf8_encoding(self):
# Test for #303.
dist = Distribution(SETUP_ATTRS)
@@ -299,46 +293,38 @@ class TestSdistTest:
filename = filename.decode('utf-8')
assert filename in cmd.filelist.files
- # Python 3 only
- if six.PY3:
+ @py3_only
+ def test_read_manifest_skips_non_utf8_filenames(self):
+ # Test for #303.
+ dist = Distribution(SETUP_ATTRS)
+ dist.script_name = 'setup.py'
+ cmd = sdist(dist)
+ cmd.ensure_finalized()
+
+ # Create manifest
+ with quiet():
+ cmd.run()
+
+ # Add Latin-1 filename to manifest
+ filename = os.path.join(b('sdist_test'), LATIN1_FILENAME)
+ cmd.manifest = os.path.join('sdist_test.egg-info', 'SOURCES.txt')
+ manifest = open(cmd.manifest, 'ab')
+ manifest.write(b('\n') + filename)
+ manifest.close()
+
+ # The file must exist to be included in the filelist
+ open(filename, 'w').close()
+
+ # Re-read manifest
+ cmd.filelist.files = []
+ with quiet():
+ cmd.read_manifest()
+
+ # The Latin-1 filename should have been skipped
+ filename = filename.decode('latin-1')
+ assert filename not in cmd.filelist.files
- def test_read_manifest_skips_non_utf8_filenames(self):
- # Test for #303.
- dist = Distribution(SETUP_ATTRS)
- dist.script_name = 'setup.py'
- cmd = sdist(dist)
- cmd.ensure_finalized()
-
- # Create manifest
- with quiet():
- cmd.run()
-
- # Add Latin-1 filename to manifest
- filename = os.path.join(b('sdist_test'), LATIN1_FILENAME)
- cmd.manifest = os.path.join('sdist_test.egg-info', 'SOURCES.txt')
- manifest = open(cmd.manifest, 'ab')
- manifest.write(b('\n') + filename)
- manifest.close()
-
- # The file must exist to be included in the filelist
- open(filename, 'w').close()
-
- # Re-read manifest
- cmd.filelist.files = []
- with quiet():
- try:
- cmd.read_manifest()
- except UnicodeDecodeError:
- e = sys.exc_info()[1]
- self.fail(e)
-
- # The Latin-1 filename should have been skipped
- filename = filename.decode('latin-1')
- assert filename not in cmd.filelist.files
-
- @pytest.mark.skipif(six.PY3 and locale.getpreferredencoding() != 'UTF-8',
- reason='Unittest fails if locale is not utf-8 but the manifests is '
- 'recorded correctly')
+ @fail_on_ascii
def test_sdist_with_utf8_encoded_filename(self):
# Test for #303.
dist = Distribution(SETUP_ATTRS)
@@ -431,5 +417,5 @@ def test_default_revctrl():
"""
ep_def = 'svn_cvs = setuptools.command.sdist:_default_revctrl'
ep = pkg_resources.EntryPoint.parse(ep_def)
- res = ep._load()
+ res = ep.resolve()
assert hasattr(res, '__iter__')
diff --git a/setuptools/tests/test_setuptools.py b/setuptools/tests/test_setuptools.py
new file mode 100644
index 00000000..e59800d2
--- /dev/null
+++ b/setuptools/tests/test_setuptools.py
@@ -0,0 +1,48 @@
+import os
+
+import pytest
+
+import setuptools
+
+
+@pytest.fixture
+def example_source(tmpdir):
+ tmpdir.mkdir('foo')
+ (tmpdir / 'foo/bar.py').write('')
+ (tmpdir / 'readme.txt').write('')
+ return tmpdir
+
+
+def test_findall(example_source):
+ found = list(setuptools.findall(str(example_source)))
+ expected = ['readme.txt', 'foo/bar.py']
+ expected = [example_source.join(fn) for fn in expected]
+ assert found == expected
+
+
+def test_findall_curdir(example_source):
+ with example_source.as_cwd():
+ found = list(setuptools.findall())
+ expected = ['readme.txt', os.path.join('foo', 'bar.py')]
+ assert found == expected
+
+
+@pytest.fixture
+def can_symlink(tmpdir):
+ """
+ Skip if cannot create a symbolic link
+ """
+ link_fn = 'link'
+ target_fn = 'target'
+ try:
+ os.symlink(target_fn, link_fn)
+ except (OSError, NotImplementedError, AttributeError):
+ pytest.skip("Cannot create symbolic links")
+ os.remove(link_fn)
+
+
+def test_findall_missing_symlink(tmpdir, can_symlink):
+ with tmpdir.as_cwd():
+ os.symlink('foo', 'bar')
+ found = list(setuptools.findall())
+ assert found == []