aboutsummaryrefslogtreecommitdiffstats
path: root/setuptools/tests
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2017-11-09 20:16:07 -0500
committerJason R. Coombs <jaraco@jaraco.com>2017-11-09 20:16:07 -0500
commit76fefe982d4445248c1933030619eedc764e695b (patch)
treede1507d2944422d2f75e716429c0d2fcae387035 /setuptools/tests
parenta5add17b554709e6b808e85a9cdbb1785717d2d5 (diff)
parentff9bc4902f32c331d917e8bae9136607e48c2738 (diff)
downloadexternal_python_setuptools-76fefe982d4445248c1933030619eedc764e695b.tar.gz
external_python_setuptools-76fefe982d4445248c1933030619eedc764e695b.tar.bz2
external_python_setuptools-76fefe982d4445248c1933030619eedc764e695b.zip
Merge branch 'master' into pr1145
Diffstat (limited to 'setuptools/tests')
-rw-r--r--setuptools/tests/__init__.py320
-rw-r--r--setuptools/tests/test_build_meta.py93
-rw-r--r--setuptools/tests/test_develop.py4
-rw-r--r--setuptools/tests/test_egg_info.py6
-rw-r--r--setuptools/tests/test_namespaces.py12
-rw-r--r--setuptools/tests/test_sdist.py67
-rw-r--r--setuptools/tests/test_setuptools.py320
-rw-r--r--setuptools/tests/text.py9
8 files changed, 474 insertions, 357 deletions
diff --git a/setuptools/tests/__init__.py b/setuptools/tests/__init__.py
index 8ae4402d..54dd7d2b 100644
--- a/setuptools/tests/__init__.py
+++ b/setuptools/tests/__init__.py
@@ -1,326 +1,6 @@
-"""Tests for the 'setuptools' package"""
import locale
-import sys
-import os
-import distutils.core
-import distutils.cmd
-from distutils.errors import DistutilsOptionError, DistutilsPlatformError
-from distutils.errors import DistutilsSetupError
-from distutils.core import Extension
-from distutils.version import LooseVersion
-from setuptools.extern import six
import pytest
-import setuptools.dist
-import setuptools.depends as dep
-from setuptools import Feature
-from setuptools.depends import Require
-
is_ascii = locale.getpreferredencoding() == 'ANSI_X3.4-1968'
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"""
-
- distutils.core._setup_stop_after = "commandline"
-
- # Don't let system command line leak into tests!
- args.setdefault('script_args', ['install'])
-
- try:
- return setuptools.setup(**args)
- finally:
- distutils.core._setup_stop_after = None
-
-
-needs_bytecode = pytest.mark.skipif(
- not hasattr(dep, 'get_module_constant'),
- reason="bytecode support not available",
-)
-
-
-class TestDepends:
- def testExtractConst(self):
- if not hasattr(dep, 'extract_constant'):
- # skip on non-bytecode platforms
- return
-
- def f1():
- global x, y, z
- x = "test"
- y = z
-
- fc = six.get_function_code(f1)
-
- # unrecognized name
- assert dep.extract_constant(fc, 'q', -1) is None
-
- # constant assigned
- dep.extract_constant(fc, 'x', -1) == "test"
-
- # expression assigned
- dep.extract_constant(fc, 'y', -1) == -1
-
- # recognized name, not assigned
- dep.extract_constant(fc, 'z', -1) is None
-
- def testFindModule(self):
- with pytest.raises(ImportError):
- dep.find_module('no-such.-thing')
- with pytest.raises(ImportError):
- dep.find_module('setuptools.non-existent')
- f, p, i = dep.find_module('setuptools.tests')
- f.close()
-
- @needs_bytecode
- def testModuleExtract(self):
- from email import __version__
- assert dep.get_module_constant('email', '__version__') == __version__
- assert dep.get_module_constant('sys', 'version') == sys.version
- assert dep.get_module_constant('setuptools.tests', '__doc__') == __doc__
-
- @needs_bytecode
- def testRequire(self):
- req = Require('Email', '1.0.3', 'email')
-
- assert req.name == 'Email'
- assert req.module == 'email'
- assert req.requested_version == '1.0.3'
- assert req.attribute == '__version__'
- assert req.full_name() == 'Email-1.0.3'
-
- from email import __version__
- assert req.get_version() == __version__
- assert req.version_ok('1.0.9')
- assert not req.version_ok('0.9.1')
- assert not req.version_ok('unknown')
-
- assert req.is_present()
- assert req.is_current()
-
- req = Require('Email 3000', '03000', 'email', format=LooseVersion)
- assert req.is_present()
- assert not req.is_current()
- assert not req.version_ok('unknown')
-
- req = Require('Do-what-I-mean', '1.0', 'd-w-i-m')
- assert not req.is_present()
- assert not req.is_current()
-
- req = Require('Tests', None, 'tests', homepage="http://example.com")
- assert req.format is None
- assert req.attribute is None
- assert req.requested_version is None
- assert req.full_name() == 'Tests'
- assert req.homepage == 'http://example.com'
-
- paths = [os.path.dirname(p) for p in __path__]
- assert req.is_present(paths)
- assert req.is_current(paths)
-
-
-class TestDistro:
- def setup_method(self, method):
- self.e1 = Extension('bar.ext', ['bar.c'])
- self.e2 = Extension('c.y', ['y.c'])
-
- self.dist = makeSetup(
- packages=['a', 'a.b', 'a.b.c', 'b', 'c'],
- py_modules=['b.d', 'x'],
- ext_modules=(self.e1, self.e2),
- package_dir={},
- )
-
- def testDistroType(self):
- assert isinstance(self.dist, setuptools.dist.Distribution)
-
- def testExcludePackage(self):
- self.dist.exclude_package('a')
- assert self.dist.packages == ['b', 'c']
-
- self.dist.exclude_package('b')
- assert self.dist.packages == ['c']
- assert self.dist.py_modules == ['x']
- assert self.dist.ext_modules == [self.e1, self.e2]
-
- self.dist.exclude_package('c')
- assert self.dist.packages == []
- assert self.dist.py_modules == ['x']
- assert self.dist.ext_modules == [self.e1]
-
- # test removals from unspecified options
- makeSetup().exclude_package('x')
-
- def testIncludeExclude(self):
- # remove an extension
- self.dist.exclude(ext_modules=[self.e1])
- assert self.dist.ext_modules == [self.e2]
-
- # add it back in
- self.dist.include(ext_modules=[self.e1])
- assert self.dist.ext_modules == [self.e2, self.e1]
-
- # should not add duplicate
- self.dist.include(ext_modules=[self.e1])
- assert self.dist.ext_modules == [self.e2, self.e1]
-
- def testExcludePackages(self):
- self.dist.exclude(packages=['c', 'b', 'a'])
- assert self.dist.packages == []
- assert self.dist.py_modules == ['x']
- assert self.dist.ext_modules == [self.e1]
-
- def testEmpty(self):
- dist = makeSetup()
- dist.include(packages=['a'], py_modules=['b'], ext_modules=[self.e2])
- dist = makeSetup()
- dist.exclude(packages=['a'], py_modules=['b'], ext_modules=[self.e2])
-
- def testContents(self):
- assert self.dist.has_contents_for('a')
- self.dist.exclude_package('a')
- assert not self.dist.has_contents_for('a')
-
- assert self.dist.has_contents_for('b')
- self.dist.exclude_package('b')
- assert not self.dist.has_contents_for('b')
-
- assert self.dist.has_contents_for('c')
- self.dist.exclude_package('c')
- assert not self.dist.has_contents_for('c')
-
- def testInvalidIncludeExclude(self):
- with pytest.raises(DistutilsSetupError):
- self.dist.include(nonexistent_option='x')
- with pytest.raises(DistutilsSetupError):
- self.dist.exclude(nonexistent_option='x')
- with pytest.raises(DistutilsSetupError):
- self.dist.include(packages={'x': 'y'})
- with pytest.raises(DistutilsSetupError):
- self.dist.exclude(packages={'x': 'y'})
- with pytest.raises(DistutilsSetupError):
- self.dist.include(ext_modules={'x': 'y'})
- with pytest.raises(DistutilsSetupError):
- self.dist.exclude(ext_modules={'x': 'y'})
-
- with pytest.raises(DistutilsSetupError):
- self.dist.include(package_dir=['q'])
- with pytest.raises(DistutilsSetupError):
- self.dist.exclude(package_dir=['q'])
-
-
-class TestFeatures:
- def setup_method(self, method):
- self.req = Require('Distutils', '1.0.3', 'distutils')
- self.dist = makeSetup(
- features={
- 'foo': Feature("foo", standard=True, require_features=['baz', self.req]),
- 'bar': Feature("bar", standard=True, packages=['pkg.bar'],
- py_modules=['bar_et'], remove=['bar.ext'],
- ),
- 'baz': Feature(
- "baz", optional=False, packages=['pkg.baz'],
- scripts=['scripts/baz_it'],
- libraries=[('libfoo', 'foo/foofoo.c')]
- ),
- 'dwim': Feature("DWIM", available=False, remove='bazish'),
- },
- script_args=['--without-bar', 'install'],
- packages=['pkg.bar', 'pkg.foo'],
- py_modules=['bar_et', 'bazish'],
- ext_modules=[Extension('bar.ext', ['bar.c'])]
- )
-
- def testDefaults(self):
- assert not Feature(
- "test", standard=True, remove='x', available=False
- ).include_by_default()
- assert Feature("test", standard=True, remove='x').include_by_default()
- # Feature must have either kwargs, removes, or require_features
- with pytest.raises(DistutilsSetupError):
- Feature("test")
-
- def testAvailability(self):
- with pytest.raises(DistutilsPlatformError):
- self.dist.features['dwim'].include_in(self.dist)
-
- def testFeatureOptions(self):
- dist = self.dist
- assert (
- ('with-dwim', None, 'include DWIM') in dist.feature_options
- )
- assert (
- ('without-dwim', None, 'exclude DWIM (default)') in dist.feature_options
- )
- assert (
- ('with-bar', None, 'include bar (default)') in dist.feature_options
- )
- assert (
- ('without-bar', None, 'exclude bar') in dist.feature_options
- )
- assert dist.feature_negopt['without-foo'] == 'with-foo'
- assert dist.feature_negopt['without-bar'] == 'with-bar'
- assert dist.feature_negopt['without-dwim'] == 'with-dwim'
- assert ('without-baz' not in dist.feature_negopt)
-
- def testUseFeatures(self):
- dist = self.dist
- assert dist.with_foo == 1
- assert dist.with_bar == 0
- assert dist.with_baz == 1
- assert ('bar_et' not in dist.py_modules)
- assert ('pkg.bar' not in dist.packages)
- assert ('pkg.baz' in dist.packages)
- assert ('scripts/baz_it' in dist.scripts)
- assert (('libfoo', 'foo/foofoo.c') in dist.libraries)
- assert dist.ext_modules == []
- assert dist.require_features == [self.req]
-
- # If we ask for bar, it should fail because we explicitly disabled
- # it on the command line
- with pytest.raises(DistutilsOptionError):
- dist.include_feature('bar')
-
- def testFeatureWithInvalidRemove(self):
- with pytest.raises(SystemExit):
- makeSetup(features={'x': Feature('x', remove='y')})
-
-
-class TestCommandTests:
- def testTestIsCommand(self):
- test_cmd = makeSetup().get_command_obj('test')
- assert (isinstance(test_cmd, distutils.cmd.Command))
-
- def testLongOptSuiteWNoDefault(self):
- ts1 = makeSetup(script_args=['test', '--test-suite=foo.tests.suite'])
- ts1 = ts1.get_command_obj('test')
- ts1.ensure_finalized()
- assert ts1.test_suite == 'foo.tests.suite'
-
- def testDefaultSuite(self):
- ts2 = makeSetup(test_suite='bar.tests.suite').get_command_obj('test')
- ts2.ensure_finalized()
- assert ts2.test_suite == 'bar.tests.suite'
-
- def testDefaultWModuleOnCmdLine(self):
- ts3 = makeSetup(
- test_suite='bar.tests',
- script_args=['test', '-m', 'foo.tests']
- ).get_command_obj('test')
- ts3.ensure_finalized()
- assert ts3.test_module == 'foo.tests'
- assert ts3.test_suite == 'foo.tests.test_suite'
-
- def testConflictingOptions(self):
- ts4 = makeSetup(
- script_args=['test', '-m', 'bar.tests', '-s', 'foo.tests.suite']
- ).get_command_obj('test')
- with pytest.raises(DistutilsOptionError):
- ts4.ensure_finalized()
-
- def testNoSuite(self):
- ts5 = makeSetup().get_command_obj('test')
- ts5.ensure_finalized()
- assert ts5.test_suite is None
diff --git a/setuptools/tests/test_build_meta.py b/setuptools/tests/test_build_meta.py
new file mode 100644
index 00000000..69a700c2
--- /dev/null
+++ b/setuptools/tests/test_build_meta.py
@@ -0,0 +1,93 @@
+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'))
diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py
index ad7cfa05..cb4ff4b4 100644
--- a/setuptools/tests/test_develop.py
+++ b/setuptools/tests/test_develop.py
@@ -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),
diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py
index e454694d..1411f93c 100644
--- a/setuptools/tests/test_egg_info.py
+++ b/setuptools/tests/test_egg_info.py
@@ -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 = [
diff --git a/setuptools/tests/test_namespaces.py b/setuptools/tests/test_namespaces.py
index 721cad1e..1ac1b35e 100644
--- a/setuptools/tests/test_namespaces.py
+++ b/setuptools/tests/test_namespaces.py
@@ -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),
diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py
index f34068dc..02222da5 100644
--- a/setuptools/tests/test_sdist.py
+++ b/setuptools/tests/test_sdist.py
@@ -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:
diff --git a/setuptools/tests/test_setuptools.py b/setuptools/tests/test_setuptools.py
index e59800d2..26e37a6c 100644
--- a/setuptools/tests/test_setuptools.py
+++ b/setuptools/tests/test_setuptools.py
@@ -1,8 +1,328 @@
+"""Tests for the 'setuptools' package"""
+
+import sys
import os
+import distutils.core
+import distutils.cmd
+from distutils.errors import DistutilsOptionError, DistutilsPlatformError
+from distutils.errors import DistutilsSetupError
+from distutils.core import Extension
+from distutils.version import LooseVersion
import pytest
import setuptools
+import setuptools.dist
+import setuptools.depends as dep
+from setuptools import Feature
+from setuptools.depends import Require
+from setuptools.extern import six
+
+
+def makeSetup(**args):
+ """Return distribution from 'setup(**args)', without executing commands"""
+
+ distutils.core._setup_stop_after = "commandline"
+
+ # Don't let system command line leak into tests!
+ args.setdefault('script_args', ['install'])
+
+ try:
+ return setuptools.setup(**args)
+ finally:
+ distutils.core._setup_stop_after = None
+
+
+needs_bytecode = pytest.mark.skipif(
+ not hasattr(dep, 'get_module_constant'),
+ reason="bytecode support not available",
+)
+
+
+class TestDepends:
+ def testExtractConst(self):
+ if not hasattr(dep, 'extract_constant'):
+ # skip on non-bytecode platforms
+ return
+
+ def f1():
+ global x, y, z
+ x = "test"
+ y = z
+
+ fc = six.get_function_code(f1)
+
+ # unrecognized name
+ assert dep.extract_constant(fc, 'q', -1) is None
+
+ # constant assigned
+ dep.extract_constant(fc, 'x', -1) == "test"
+
+ # expression assigned
+ dep.extract_constant(fc, 'y', -1) == -1
+
+ # recognized name, not assigned
+ dep.extract_constant(fc, 'z', -1) is None
+
+ def testFindModule(self):
+ with pytest.raises(ImportError):
+ dep.find_module('no-such.-thing')
+ with pytest.raises(ImportError):
+ dep.find_module('setuptools.non-existent')
+ f, p, i = dep.find_module('setuptools.tests')
+ f.close()
+
+ @needs_bytecode
+ def testModuleExtract(self):
+ from json import __version__
+ assert dep.get_module_constant('json', '__version__') == __version__
+ assert dep.get_module_constant('sys', 'version') == sys.version
+ assert dep.get_module_constant('setuptools.tests.test_setuptools', '__doc__') == __doc__
+
+ @needs_bytecode
+ def testRequire(self):
+ req = Require('Json', '1.0.3', 'json')
+
+ assert req.name == 'Json'
+ assert req.module == 'json'
+ assert req.requested_version == '1.0.3'
+ assert req.attribute == '__version__'
+ assert req.full_name() == 'Json-1.0.3'
+
+ from json import __version__
+ assert req.get_version() == __version__
+ assert req.version_ok('1.0.9')
+ assert not req.version_ok('0.9.1')
+ assert not req.version_ok('unknown')
+
+ assert req.is_present()
+ assert req.is_current()
+
+ req = Require('Json 3000', '03000', 'json', format=LooseVersion)
+ assert req.is_present()
+ assert not req.is_current()
+ assert not req.version_ok('unknown')
+
+ req = Require('Do-what-I-mean', '1.0', 'd-w-i-m')
+ assert not req.is_present()
+ assert not req.is_current()
+
+ req = Require('Tests', None, 'tests', homepage="http://example.com")
+ assert req.format is None
+ assert req.attribute is None
+ assert req.requested_version is None
+ assert req.full_name() == 'Tests'
+ assert req.homepage == 'http://example.com'
+
+ from setuptools.tests import __path__
+ paths = [os.path.dirname(p) for p in __path__]
+ assert req.is_present(paths)
+ assert req.is_current(paths)
+
+
+class TestDistro:
+ def setup_method(self, method):
+ self.e1 = Extension('bar.ext', ['bar.c'])
+ self.e2 = Extension('c.y', ['y.c'])
+
+ self.dist = makeSetup(
+ packages=['a', 'a.b', 'a.b.c', 'b', 'c'],
+ py_modules=['b.d', 'x'],
+ ext_modules=(self.e1, self.e2),
+ package_dir={},
+ )
+
+ def testDistroType(self):
+ assert isinstance(self.dist, setuptools.dist.Distribution)
+
+ def testExcludePackage(self):
+ self.dist.exclude_package('a')
+ assert self.dist.packages == ['b', 'c']
+
+ self.dist.exclude_package('b')
+ assert self.dist.packages == ['c']
+ assert self.dist.py_modules == ['x']
+ assert self.dist.ext_modules == [self.e1, self.e2]
+
+ self.dist.exclude_package('c')
+ assert self.dist.packages == []
+ assert self.dist.py_modules == ['x']
+ assert self.dist.ext_modules == [self.e1]
+
+ # test removals from unspecified options
+ makeSetup().exclude_package('x')
+
+ def testIncludeExclude(self):
+ # remove an extension
+ self.dist.exclude(ext_modules=[self.e1])
+ assert self.dist.ext_modules == [self.e2]
+
+ # add it back in
+ self.dist.include(ext_modules=[self.e1])
+ assert self.dist.ext_modules == [self.e2, self.e1]
+
+ # should not add duplicate
+ self.dist.include(ext_modules=[self.e1])
+ assert self.dist.ext_modules == [self.e2, self.e1]
+
+ def testExcludePackages(self):
+ self.dist.exclude(packages=['c', 'b', 'a'])
+ assert self.dist.packages == []
+ assert self.dist.py_modules == ['x']
+ assert self.dist.ext_modules == [self.e1]
+
+ def testEmpty(self):
+ dist = makeSetup()
+ dist.include(packages=['a'], py_modules=['b'], ext_modules=[self.e2])
+ dist = makeSetup()
+ dist.exclude(packages=['a'], py_modules=['b'], ext_modules=[self.e2])
+
+ def testContents(self):
+ assert self.dist.has_contents_for('a')
+ self.dist.exclude_package('a')
+ assert not self.dist.has_contents_for('a')
+
+ assert self.dist.has_contents_for('b')
+ self.dist.exclude_package('b')
+ assert not self.dist.has_contents_for('b')
+
+ assert self.dist.has_contents_for('c')
+ self.dist.exclude_package('c')
+ assert not self.dist.has_contents_for('c')
+
+ def testInvalidIncludeExclude(self):
+ with pytest.raises(DistutilsSetupError):
+ self.dist.include(nonexistent_option='x')
+ with pytest.raises(DistutilsSetupError):
+ self.dist.exclude(nonexistent_option='x')
+ with pytest.raises(DistutilsSetupError):
+ self.dist.include(packages={'x': 'y'})
+ with pytest.raises(DistutilsSetupError):
+ self.dist.exclude(packages={'x': 'y'})
+ with pytest.raises(DistutilsSetupError):
+ self.dist.include(ext_modules={'x': 'y'})
+ with pytest.raises(DistutilsSetupError):
+ self.dist.exclude(ext_modules={'x': 'y'})
+
+ with pytest.raises(DistutilsSetupError):
+ self.dist.include(package_dir=['q'])
+ with pytest.raises(DistutilsSetupError):
+ self.dist.exclude(package_dir=['q'])
+
+
+class TestFeatures:
+ def setup_method(self, method):
+ self.req = Require('Distutils', '1.0.3', 'distutils')
+ self.dist = makeSetup(
+ features={
+ 'foo': Feature("foo", standard=True, require_features=['baz', self.req]),
+ 'bar': Feature("bar", standard=True, packages=['pkg.bar'],
+ py_modules=['bar_et'], remove=['bar.ext'],
+ ),
+ 'baz': Feature(
+ "baz", optional=False, packages=['pkg.baz'],
+ scripts=['scripts/baz_it'],
+ libraries=[('libfoo', 'foo/foofoo.c')]
+ ),
+ 'dwim': Feature("DWIM", available=False, remove='bazish'),
+ },
+ script_args=['--without-bar', 'install'],
+ packages=['pkg.bar', 'pkg.foo'],
+ py_modules=['bar_et', 'bazish'],
+ ext_modules=[Extension('bar.ext', ['bar.c'])]
+ )
+
+ def testDefaults(self):
+ assert not Feature(
+ "test", standard=True, remove='x', available=False
+ ).include_by_default()
+ assert Feature("test", standard=True, remove='x').include_by_default()
+ # Feature must have either kwargs, removes, or require_features
+ with pytest.raises(DistutilsSetupError):
+ Feature("test")
+
+ def testAvailability(self):
+ with pytest.raises(DistutilsPlatformError):
+ self.dist.features['dwim'].include_in(self.dist)
+
+ def testFeatureOptions(self):
+ dist = self.dist
+ assert (
+ ('with-dwim', None, 'include DWIM') in dist.feature_options
+ )
+ assert (
+ ('without-dwim', None, 'exclude DWIM (default)') in dist.feature_options
+ )
+ assert (
+ ('with-bar', None, 'include bar (default)') in dist.feature_options
+ )
+ assert (
+ ('without-bar', None, 'exclude bar') in dist.feature_options
+ )
+ assert dist.feature_negopt['without-foo'] == 'with-foo'
+ assert dist.feature_negopt['without-bar'] == 'with-bar'
+ assert dist.feature_negopt['without-dwim'] == 'with-dwim'
+ assert ('without-baz' not in dist.feature_negopt)
+
+ def testUseFeatures(self):
+ dist = self.dist
+ assert dist.with_foo == 1
+ assert dist.with_bar == 0
+ assert dist.with_baz == 1
+ assert ('bar_et' not in dist.py_modules)
+ assert ('pkg.bar' not in dist.packages)
+ assert ('pkg.baz' in dist.packages)
+ assert ('scripts/baz_it' in dist.scripts)
+ assert (('libfoo', 'foo/foofoo.c') in dist.libraries)
+ assert dist.ext_modules == []
+ assert dist.require_features == [self.req]
+
+ # If we ask for bar, it should fail because we explicitly disabled
+ # it on the command line
+ with pytest.raises(DistutilsOptionError):
+ dist.include_feature('bar')
+
+ def testFeatureWithInvalidRemove(self):
+ with pytest.raises(SystemExit):
+ makeSetup(features={'x': Feature('x', remove='y')})
+
+
+class TestCommandTests:
+ def testTestIsCommand(self):
+ test_cmd = makeSetup().get_command_obj('test')
+ assert (isinstance(test_cmd, distutils.cmd.Command))
+
+ def testLongOptSuiteWNoDefault(self):
+ ts1 = makeSetup(script_args=['test', '--test-suite=foo.tests.suite'])
+ ts1 = ts1.get_command_obj('test')
+ ts1.ensure_finalized()
+ assert ts1.test_suite == 'foo.tests.suite'
+
+ def testDefaultSuite(self):
+ ts2 = makeSetup(test_suite='bar.tests.suite').get_command_obj('test')
+ ts2.ensure_finalized()
+ assert ts2.test_suite == 'bar.tests.suite'
+
+ def testDefaultWModuleOnCmdLine(self):
+ ts3 = makeSetup(
+ test_suite='bar.tests',
+ script_args=['test', '-m', 'foo.tests']
+ ).get_command_obj('test')
+ ts3.ensure_finalized()
+ assert ts3.test_module == 'foo.tests'
+ assert ts3.test_suite == 'foo.tests.test_suite'
+
+ def testConflictingOptions(self):
+ ts4 = makeSetup(
+ script_args=['test', '-m', 'bar.tests', '-s', 'foo.tests.suite']
+ ).get_command_obj('test')
+ with pytest.raises(DistutilsOptionError):
+ ts4.ensure_finalized()
+
+ def testNoSuite(self):
+ ts5 = makeSetup().get_command_obj('test')
+ ts5.ensure_finalized()
+ assert ts5.test_suite is None
@pytest.fixture
diff --git a/setuptools/tests/text.py b/setuptools/tests/text.py
new file mode 100644
index 00000000..ad2c6249
--- /dev/null
+++ b/setuptools/tests/text.py
@@ -0,0 +1,9 @@
+# -*- 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')