diff options
Diffstat (limited to 'setuptools/tests')
21 files changed, 902 insertions, 142 deletions
diff --git a/setuptools/tests/__init__.py b/setuptools/tests/__init__.py index 32447356..53bd836c 100644 --- a/setuptools/tests/__init__.py +++ b/setuptools/tests/__init__.py @@ -27,7 +27,7 @@ def makeSetup(**args): distutils.core._setup_stop_after = "commandline" # Don't let system command line leak into tests! - args.setdefault('script_args',['install']) + args.setdefault('script_args', ['install']) try: return setuptools.setup(**args) @@ -40,6 +40,7 @@ needs_bytecode = pytest.mark.skipif( reason="bytecode support not available", ) + class TestDepends: def testExtractConst(self): @@ -55,35 +56,35 @@ class TestDepends: fc = six.get_function_code(f1) # unrecognized name - assert dep.extract_constant(fc,'q', -1) is None + assert dep.extract_constant(fc, 'q', -1) is None # constant assigned - dep.extract_constant(fc,'x', -1) == "test" + dep.extract_constant(fc, 'x', -1) == "test" # expression assigned - dep.extract_constant(fc,'y', -1) == -1 + dep.extract_constant(fc, 'y', -1) == -1 # recognized name, not assigned - dep.extract_constant(fc,'z', -1) is None + 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, 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__ + 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') + req = Require('Email', '1.0.3', 'email') assert req.name == 'Email' assert req.module == 'email' @@ -100,12 +101,12 @@ class TestDepends: assert req.is_present() assert req.is_current() - req = Require('Email 3000','03000','email',format=LooseVersion) + 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') + req = Require('Do-what-I-mean', '1.0', 'd-w-i-m') assert not req.is_present() assert not req.is_current() @@ -124,22 +125,22 @@ class TestDepends: class TestDistro: def setup_method(self, method): - self.e1 = Extension('bar.ext',['bar.c']) + 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 = {}, + py_modules=['b.d', 'x'], + ext_modules=(self.e1, self.e2), + package_dir={}, ) def testDistroType(self): - assert isinstance(self.dist,setuptools.dist.Distribution) + assert isinstance(self.dist, setuptools.dist.Distribution) def testExcludePackage(self): self.dist.exclude_package('a') - assert self.dist.packages == ['b','c'] + assert self.dist.packages == ['b', 'c'] self.dist.exclude_package('b') assert self.dist.packages == ['c'] @@ -168,7 +169,7 @@ class TestDistro: assert self.dist.ext_modules == [self.e2, self.e1] def testExcludePackages(self): - self.dist.exclude(packages=['c','b','a']) + self.dist.exclude(packages=['c', 'b', 'a']) assert self.dist.packages == [] assert self.dist.py_modules == ['x'] assert self.dist.ext_modules == [self.e1] @@ -198,13 +199,13 @@ class TestDistro: with pytest.raises(DistutilsSetupError): self.dist.exclude(nonexistent_option='x') with pytest.raises(DistutilsSetupError): - self.dist.include(packages={'x':'y'}) + self.dist.include(packages={'x': 'y'}) with pytest.raises(DistutilsSetupError): - self.dist.exclude(packages={'x':'y'}) + self.dist.exclude(packages={'x': 'y'}) with pytest.raises(DistutilsSetupError): - self.dist.include(ext_modules={'x':'y'}) + self.dist.include(ext_modules={'x': 'y'}) with pytest.raises(DistutilsSetupError): - self.dist.exclude(ext_modules={'x':'y'}) + self.dist.exclude(ext_modules={'x': 'y'}) with pytest.raises(DistutilsSetupError): self.dist.include(package_dir=['q']) @@ -215,31 +216,31 @@ class TestDistro: class TestFeatures: def setup_method(self, method): - self.req = Require('Distutils','1.0.3','distutils') + 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'], + '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')] + 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'])] + 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 + "test", standard=True, remove='x', available=False ).include_by_default() - assert Feature("test",standard=True,remove='x').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") @@ -251,32 +252,32 @@ class TestFeatures: def testFeatureOptions(self): dist = self.dist assert ( - ('with-dwim',None,'include DWIM') in dist.feature_options + ('with-dwim', None, 'include DWIM') in dist.feature_options ) assert ( - ('without-dwim',None,'exclude DWIM (default)') in dist.feature_options + ('without-dwim', None, 'exclude DWIM (default)') in dist.feature_options ) assert ( - ('with-bar',None,'include bar (default)') in dist.feature_options + ('with-bar', None, 'include bar (default)') in dist.feature_options ) assert ( - ('without-bar',None,'exclude bar') in dist.feature_options + ('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 (not 'without-baz' in dist.feature_negopt) + 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 (not 'bar_et' in dist.py_modules) - assert (not 'pkg.bar' in dist.packages) + 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 (('libfoo', 'foo/foofoo.c') in dist.libraries) assert dist.ext_modules == [] assert dist.require_features == [self.req] @@ -287,7 +288,8 @@ class TestFeatures: def testFeatureWithInvalidRemove(self): with pytest.raises(SystemExit): - makeSetup(features={'x':Feature('x', remove='y')}) + makeSetup(features={'x': Feature('x', remove='y')}) + class TestCommandTests: @@ -296,7 +298,7 @@ class TestCommandTests: assert (isinstance(test_cmd, distutils.cmd.Command)) def testLongOptSuiteWNoDefault(self): - ts1 = makeSetup(script_args=['test','--test-suite=foo.tests.suite']) + 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' @@ -309,7 +311,7 @@ class TestCommandTests: def testDefaultWModuleOnCmdLine(self): ts3 = makeSetup( test_suite='bar.tests', - script_args=['test','-m','foo.tests'] + script_args=['test', '-m', 'foo.tests'] ).get_command_obj('test') ts3.ensure_finalized() assert ts3.test_module == 'foo.tests' @@ -317,7 +319,7 @@ class TestCommandTests: def testConflictingOptions(self): ts4 = makeSetup( - script_args=['test','-m','bar.tests', '-s','foo.tests.suite'] + script_args=['test', '-m', 'bar.tests', '-s', 'foo.tests.suite'] ).get_command_obj('test') with pytest.raises(DistutilsOptionError): ts4.ensure_finalized() @@ -325,4 +327,4 @@ class TestCommandTests: def testNoSuite(self): ts5 = makeSetup().get_command_obj('test') ts5.ensure_finalized() - assert ts5.test_suite == None + assert ts5.test_suite is None diff --git a/setuptools/tests/contexts.py b/setuptools/tests/contexts.py index ae28c7c3..535ae107 100644 --- a/setuptools/tests/contexts.py +++ b/setuptools/tests/contexts.py @@ -10,7 +10,7 @@ import pkg_resources @contextlib.contextmanager -def tempdir(cd=lambda dir:None, **kwargs): +def tempdir(cd=lambda dir: None, **kwargs): temp_dir = tempfile.mkdtemp(**kwargs) orig_dir = os.getcwd() try: diff --git a/setuptools/tests/environment.py b/setuptools/tests/environment.py index a23c0504..b0e3bd36 100644 --- a/setuptools/tests/environment.py +++ b/setuptools/tests/environment.py @@ -25,11 +25,11 @@ def run_setup_py(cmd, pypath=None, path=None, for envname in os.environ: env[envname] = os.environ[envname] - #override the python path if needed + # override the python path if needed if pypath is not None: env["PYTHONPATH"] = pypath - #overide the execution path if needed + # overide the execution path if needed if path is not None: env["PATH"] = path if not env.get("PATH", ""): @@ -50,11 +50,11 @@ def run_setup_py(cmd, pypath=None, path=None, except OSError: return 1, '' - #decode the console string if needed - if hasattr(data, "decode"): + # decode the console string if needed + if hasattr(data, "decode"): # use the default encoding data = data.decode() data = unicodedata.normalize('NFC', data) - #communciate calls wait() + # communciate calls wait() return proc.returncode, data diff --git a/setuptools/tests/fixtures.py b/setuptools/tests/fixtures.py index c70c38cb..5204c8d1 100644 --- a/setuptools/tests/fixtures.py +++ b/setuptools/tests/fixtures.py @@ -1,24 +1,20 @@ -try: - from unittest import mock -except ImportError: - import mock import pytest from . import contexts @pytest.yield_fixture -def user_override(): +def user_override(monkeypatch): """ Override site.USER_BASE and site.USER_SITE with temporary directories in a context. """ with contexts.tempdir() as user_base: - with mock.patch('site.USER_BASE', user_base): - with contexts.tempdir() as user_site: - with mock.patch('site.USER_SITE', user_site): - with contexts.save_user_site_setting(): - yield + monkeypatch.setattr('site.USER_BASE', user_base) + with contexts.tempdir() as user_site: + monkeypatch.setattr('site.USER_SITE', user_site) + with contexts.save_user_site_setting(): + yield @pytest.yield_fixture diff --git a/setuptools/tests/py26compat.py b/setuptools/tests/py26compat.py index 7211f275..18cece05 100644 --- a/setuptools/tests/py26compat.py +++ b/setuptools/tests/py26compat.py @@ -2,12 +2,14 @@ import sys import tarfile import contextlib + def _tarfile_open_ex(*args, **kwargs): """ Extend result as a context manager. """ return contextlib.closing(tarfile.open(*args, **kwargs)) + if sys.version_info[:2] < (2, 7) or (3, 0) <= sys.version_info[:2] < (3, 2): tarfile_open = _tarfile_open_ex else: diff --git a/setuptools/tests/server.py b/setuptools/tests/server.py index 6a687937..9e5fefb7 100644 --- a/setuptools/tests/server.py +++ b/setuptools/tests/server.py @@ -18,6 +18,7 @@ class IndexServer(BaseHTTPServer.HTTPServer): # The index files should be located in setuptools/tests/indexes s.stop() """ + def __init__(self, server_address=('', 0), RequestHandlerClass=SimpleHTTPServer.SimpleHTTPRequestHandler): BaseHTTPServer.HTTPServer.__init__(self, server_address, @@ -42,16 +43,20 @@ class IndexServer(BaseHTTPServer.HTTPServer): port = self.server_port return 'http://127.0.0.1:%s/setuptools/tests/indexes/' % port + class RequestRecorder(BaseHTTPServer.BaseHTTPRequestHandler): + def do_GET(self): requests = vars(self.server).setdefault('requests', []) requests.append(self) self.send_response(200, 'OK') + class MockServer(BaseHTTPServer.HTTPServer, threading.Thread): """ A simple HTTP Server that records the requests made to it. """ + def __init__(self, server_address=('', 0), RequestHandlerClass=RequestRecorder): BaseHTTPServer.HTTPServer.__init__(self, server_address, diff --git a/setuptools/tests/test_archive_util.py b/setuptools/tests/test_archive_util.py new file mode 100644 index 00000000..b789e9ac --- /dev/null +++ b/setuptools/tests/test_archive_util.py @@ -0,0 +1,42 @@ +# coding: utf-8 + +import tarfile +import io + +from setuptools.extern import six + +import pytest + +from setuptools import archive_util + + +@pytest.fixture +def tarfile_with_unicode(tmpdir): + """ + Create a tarfile containing only a file whose name is + a zero byte file called testimäge.png. + """ + tarobj = io.BytesIO() + + with tarfile.open(fileobj=tarobj, mode="w:gz") as tgz: + data = b"" + + filename = "testimäge.png" + if six.PY2: + filename = filename.decode('utf-8') + + t = tarfile.TarInfo(filename) + t.size = len(data) + + tgz.addfile(t, io.BytesIO(data)) + + target = tmpdir / 'unicode-pkg-1.0.tar.gz' + with open(str(target), mode='wb') as tf: + tf.write(tarobj.getvalue()) + return str(target) + + +@pytest.mark.xfail(reason="#710 and #712") +def test_unicode_files(tarfile_with_unicode, tmpdir): + target = tmpdir / 'out' + archive_util.unpack_archive(tarfile_with_unicode, six.text_type(target)) diff --git a/setuptools/tests/test_bdist_egg.py b/setuptools/tests/test_bdist_egg.py index ccfb2ea7..c77aa226 100644 --- a/setuptools/tests/test_bdist_egg.py +++ b/setuptools/tests/test_bdist_egg.py @@ -9,30 +9,33 @@ from setuptools.dist import Distribution from . import contexts + SETUP_PY = """\ from setuptools import setup setup(name='foo', py_modules=['hi']) """ + @pytest.yield_fixture def setup_context(tmpdir): - with (tmpdir/'setup.py').open('w') as f: + with (tmpdir / 'setup.py').open('w') as f: f.write(SETUP_PY) - with (tmpdir/'hi.py').open('w') as f: + with (tmpdir / 'hi.py').open('w') as f: f.write('1\n') with tmpdir.as_cwd(): yield tmpdir class Test: + def test_bdist_egg(self, setup_context, user_override): dist = Distribution(dict( script_name='setup.py', script_args=['bdist_egg'], name='foo', py_modules=['hi'] - )) + )) os.makedirs(os.path.join('build', 'src')) with contexts.quiet(): dist.parse_command_line() diff --git a/setuptools/tests/test_build_ext.py b/setuptools/tests/test_build_ext.py index 0719ba44..ac002f44 100644 --- a/setuptools/tests/test_build_ext.py +++ b/setuptools/tests/test_build_ext.py @@ -1,9 +1,16 @@ +import sys import distutils.command.build_ext as orig +from distutils.sysconfig import get_config_var -from setuptools.command.build_ext import build_ext +from setuptools.extern import six + +from setuptools.command.build_ext import build_ext, get_abi3_suffix from setuptools.dist import Distribution +from setuptools.extension import Extension + class TestBuildExt: + def test_get_ext_filename(self): """ Setuptools needs to give back the same @@ -16,3 +23,24 @@ class TestBuildExt: res = cmd.get_ext_filename('foo') wanted = orig.build_ext.get_ext_filename(cmd, 'foo') assert res == wanted + + def test_abi3_filename(self): + """ + Filename needs to be loadable by several versions + of Python 3 if 'is_abi3' is truthy on Extension() + """ + print(get_abi3_suffix()) + + extension = Extension('spam.eggs', ['eggs.c'], py_limited_api=True) + dist = Distribution(dict(ext_modules=[extension])) + cmd = build_ext(dist) + cmd.finalize_options() + assert 'spam.eggs' in cmd.ext_map + res = cmd.get_ext_filename('spam.eggs') + + if six.PY2 or not get_abi3_suffix(): + assert res.endswith(get_config_var('SO')) + elif sys.platform == 'win32': + assert res.endswith('eggs.pyd') + else: + assert 'abi3' in res diff --git a/setuptools/tests/test_build_py.py b/setuptools/tests/test_build_py.py index ed1703ac..cc701ae6 100644 --- a/setuptools/tests/test_build_py.py +++ b/setuptools/tests/test_build_py.py @@ -26,6 +26,5 @@ def test_directories_in_package_data_glob(tmpdir_as_cwd): package_data={'': ['path/*']}, )) os.makedirs('path/subpath') - #with contexts.quiet(): dist.parse_command_line() dist.run_commands() diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py index 1b844499..f1580785 100644 --- a/setuptools/tests/test_develop.py +++ b/setuptools/tests/test_develop.py @@ -26,6 +26,7 @@ setup(name='foo', INIT_PY = """print "foo" """ + @pytest.yield_fixture def temp_user(monkeypatch): with contexts.tempdir() as user_base: @@ -54,6 +55,7 @@ def test_env(tmpdir, temp_user): 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): @@ -112,4 +114,4 @@ class TestDevelop: cmd.ensure_finalized() cmd.install_dir = tmpdir cmd.run() - #assert '0.0' not in foocmd_text + # assert '0.0' not in foocmd_text diff --git a/setuptools/tests/test_dist_info.py b/setuptools/tests/test_dist_info.py index 9f226a55..f7e7d2bf 100644 --- a/setuptools/tests/test_dist_info.py +++ b/setuptools/tests/test_dist_info.py @@ -1,8 +1,7 @@ """Test .dist-info style distributions. """ -import os -import shutil -import tempfile + +from __future__ import unicode_literals from setuptools.extern.six.moves import map @@ -14,10 +13,48 @@ from .textwrap import DALS class TestDistInfo: - def test_distinfo(self): + metadata_base = DALS(""" + Metadata-Version: 1.2 + Requires-Dist: splort (==4) + Provides-Extra: baz + Requires-Dist: quux (>=1.1); extra == 'baz' + """) + + @classmethod + def build_metadata(cls, **kwargs): + lines = ( + '{key}: {value}\n'.format(**locals()) + for key, value in kwargs.items() + ) + return cls.metadata_base + ''.join(lines) + + @pytest.fixture + def metadata(self, tmpdir): + dist_info_name = 'VersionedDistribution-2.718.dist-info' + versioned = tmpdir / dist_info_name + versioned.mkdir() + filename = versioned / 'METADATA' + content = self.build_metadata( + Name='VersionedDistribution', + ) + filename.write_text(content, encoding='utf-8') + + dist_info_name = 'UnversionedDistribution.dist-info' + unversioned = tmpdir / dist_info_name + unversioned.mkdir() + filename = unversioned / 'METADATA' + content = self.build_metadata( + Name='UnversionedDistribution', + Version='0.3', + ) + filename.write_text(content, encoding='utf-8') + + return str(tmpdir) + + def test_distinfo(self, metadata): dists = dict( (d.project_name, d) - for d in pkg_resources.find_distributions(self.tmpdir) + for d in pkg_resources.find_distributions(metadata) ) assert len(dists) == 2, dists @@ -25,49 +62,17 @@ class TestDistInfo: unversioned = dists['UnversionedDistribution'] versioned = dists['VersionedDistribution'] - assert versioned.version == '2.718' # from filename - assert unversioned.version == '0.3' # from METADATA + assert versioned.version == '2.718' # from filename + assert unversioned.version == '0.3' # from METADATA - def test_conditional_dependencies(self): + def test_conditional_dependencies(self, metadata): specs = 'splort==4', 'quux>=1.1' requires = list(map(pkg_resources.Requirement.parse, specs)) - for d in pkg_resources.find_distributions(self.tmpdir): + for d in pkg_resources.find_distributions(metadata): assert d.requires() == requires[:1] assert d.requires(extras=('baz',)) == [ requires[0], - pkg_resources.Requirement.parse('quux>=1.1;extra=="baz"')] + pkg_resources.Requirement.parse('quux>=1.1;extra=="baz"'), + ] assert d.extras == ['baz'] - - metadata_template = DALS(""" - Metadata-Version: 1.2 - Name: {name} - {version} - Requires-Dist: splort (==4) - Provides-Extra: baz - Requires-Dist: quux (>=1.1); extra == 'baz' - """) - - def setup_method(self, method): - self.tmpdir = tempfile.mkdtemp() - dist_info_name = 'VersionedDistribution-2.718.dist-info' - versioned = os.path.join(self.tmpdir, dist_info_name) - os.mkdir(versioned) - with open(os.path.join(versioned, 'METADATA'), 'w+') as metadata_file: - metadata = self.metadata_template.format( - name='VersionedDistribution', - version='', - ).replace('\n\n', '\n') - metadata_file.write(metadata) - dist_info_name = 'UnversionedDistribution.dist-info' - unversioned = os.path.join(self.tmpdir, dist_info_name) - os.mkdir(unversioned) - with open(os.path.join(unversioned, 'METADATA'), 'w+') as metadata_file: - metadata = self.metadata_template.format( - name='UnversionedDistribution', - version='Version: 0.3', - ) - metadata_file.write(metadata) - - def teardown_method(self, method): - shutil.rmtree(self.tmpdir) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index fd06b6ef..82e1d7e8 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -14,9 +14,10 @@ import logging import itertools import distutils.errors import io +import zipfile -from setuptools.extern.six.moves import urllib import time +from setuptools.extern.six.moves import urllib import pytest try: @@ -30,7 +31,7 @@ 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 +from pkg_resources import normalize_path, working_set from pkg_resources import Distribution as PRDistribution import setuptools.tests.server import pkg_resources @@ -41,6 +42,7 @@ from .textwrap import DALS class FakeDist(object): + def get_entry_map(self, group): if group != 'console_scripts': return {} @@ -49,12 +51,14 @@ class FakeDist(object): def as_requirement(self): return 'spec' + SETUP_PY = DALS(""" from setuptools import setup setup(name='foo') """) + class TestEasyInstallTest: def test_install_site_py(self, tmpdir): @@ -70,10 +74,12 @@ class TestEasyInstallTest: expected = header + DALS(""" # EASY-INSTALL-ENTRY-SCRIPT: 'spec','console_scripts','name' __requires__ = 'spec' + import re import sys from pkg_resources import load_entry_point if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) sys.exit( load_entry_point('spec', 'console_scripts', 'name')() ) @@ -123,16 +129,72 @@ class TestEasyInstallTest: get_site_dirs should always return site dirs reported by site.getsitepackages. """ - mock_gsp = lambda: ['/setuptools/test/site-packages'] + path = normalize_path('/setuptools/test/site-packages') + mock_gsp = lambda: [path] monkeypatch.setattr(site, 'getsitepackages', mock_gsp, raising=False) - assert '/setuptools/test/site-packages' in ei.get_site_dirs() + assert path in ei.get_site_dirs() def test_all_site_dirs_works_without_getsitepackages(self, monkeypatch): monkeypatch.delattr(site, 'getsitepackages', raising=False) assert ei.get_site_dirs() + @pytest.fixture + def sdist_unicode(self, tmpdir): + files = [ + ( + 'setup.py', + DALS(""" + import setuptools + setuptools.setup( + name="setuptools-test-unicode", + version="1.0", + packages=["mypkg"], + include_package_data=True, + ) + """), + ), + ( + 'mypkg/__init__.py', + "", + ), + ( + u'mypkg/\u2603.txt', + "", + ), + ] + sdist_name = 'setuptools-test-unicode-1.0.zip' + sdist = tmpdir / sdist_name + # can't use make_sdist, because the issue only occurs + # with zip sdists. + sdist_zip = zipfile.ZipFile(str(sdist), 'w') + for filename, content in files: + sdist_zip.writestr(filename, content) + sdist_zip.close() + return str(sdist) + + @pytest.mark.xfail(reason="#709 and #710") + # also + #@pytest.mark.xfail(setuptools.tests.is_ascii, + # reason="https://github.com/pypa/setuptools/issues/706") + def test_unicode_filename_in_sdist(self, sdist_unicode, tmpdir, monkeypatch): + """ + The install command should execute correctly even if + the package has unicode filenames. + """ + dist = Distribution({'script_args': ['easy_install']}) + target = (tmpdir / 'target').ensure_dir() + cmd = ei.easy_install( + dist, + install_dir=str(target), + args=['x'], + ) + monkeypatch.setitem(os.environ, 'PYTHONPATH', str(target)) + cmd.ensure_finalized() + cmd.easy_install(sdist_unicode) + class TestPTHFileWriter: + def test_add_from_cwd_site_sets_dirty(self): '''a pth file manager should set dirty if a distribution is in site but also the cwd @@ -154,7 +216,7 @@ class TestPTHFileWriter: @pytest.yield_fixture def setup_context(tmpdir): - with (tmpdir/'setup.py').open('w') as f: + with (tmpdir / 'setup.py').open('w') as f: f.write(SETUP_PY) with tmpdir.as_cwd(): yield tmpdir @@ -266,6 +328,7 @@ def distutils_package(): class TestDistutilsPackage: + def test_bdist_egg_available_on_distutils_pkg(self, distutils_package): run_setup('setup.py', ['bdist_egg']) @@ -527,36 +590,40 @@ def make_trivial_sdist(dist_path, setup_py): dist.addfile(setup_py_file, fileobj=setup_py_bytes) +@pytest.mark.skipif( + sys.platform.startswith('java') and ei.is_sh(sys.executable), + reason="Test cannot run under java when executable is sh" +) class TestScriptHeader: non_ascii_exe = '/Users/José/bin/python' exe_with_spaces = r'C:\Program Files\Python33\python.exe' - @pytest.mark.skipif( - 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' % ei.nt_quote_arg(os.path.normpath(sys.executable)) actual = ei.ScriptWriter.get_script_header('#!/usr/local/bin/python') assert actual == expected + def test_get_script_header_args(self): 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 + def test_get_script_header_non_ascii_exe(self): actual = ei.ScriptWriter.get_script_header('#!/usr/bin/python', executable=self.non_ascii_exe) expected = '#!%s -x\n' % self.non_ascii_exe assert actual == expected + def test_get_script_header_exe_with_spaces(self): actual = ei.ScriptWriter.get_script_header('#!/usr/bin/python', - executable='"'+self.exe_with_spaces+'"') + executable='"' + self.exe_with_spaces + '"') expected = '#!"%s"\n' % self.exe_with_spaces assert actual == expected class TestCommandSpec: + def test_custom_launch_command(self): """ Show how a custom CommandSpec could be used to specify a #! executable @@ -590,17 +657,9 @@ class TestCommandSpec: 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('#!') diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index 3a0db58f..dff2a8c8 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -179,7 +179,7 @@ class TestEggInfo(object): """ % requires_line) build_files({ 'setup.py': setup_script, - }) + }) def test_install_requires_with_markers(self, tmpdir_cwd, env): self._setup_script_with_requires( @@ -210,6 +210,32 @@ class TestEggInfo(object): self._run_install_command(tmpdir_cwd, env) assert glob.glob(os.path.join(env.paths['lib'], 'barbazquux*')) == [] + def test_python_requires_egg_info(self, tmpdir_cwd, env): + self._setup_script_with_requires( + """python_requires='>=2.7.12',""") + environ = os.environ.copy().update( + HOME=env.paths['home'], + ) + code, data = environment.run_setup_py( + cmd=['egg_info'], + pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]), + data_stream=1, + env=environ, + ) + egg_info_dir = os.path.join('.', 'foo.egg-info') + with open(os.path.join(egg_info_dir, 'PKG-INFO')) as pkginfo_file: + pkg_info_lines = pkginfo_file.read().split('\n') + assert 'Requires-Python: >=2.7.12' in pkg_info_lines + assert 'Metadata-Version: 1.2' in pkg_info_lines + + def test_python_requires_install(self, tmpdir_cwd, env): + self._setup_script_with_requires( + """python_requires='>=1.2.3',""") + 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') + def _run_install_command(self, tmpdir_cwd, env, cmd=None, output=None): environ = os.environ.copy().update( HOME=env.paths['home'], @@ -235,6 +261,7 @@ class TestEggInfo(object): def _find_egg_info_files(self, root): class DirList(list): + def __init__(self, files, base): super(DirList, self).__init__(files) self.base = base diff --git a/setuptools/tests/test_find_packages.py b/setuptools/tests/test_find_packages.py index 06a7c02e..9d31ccd7 100644 --- a/setuptools/tests/test_find_packages.py +++ b/setuptools/tests/test_find_packages.py @@ -13,6 +13,8 @@ from setuptools import find_packages find_420_packages = setuptools.PEP420PackageFinder.find # modeled after CPython's test.support.can_symlink + + def can_symlink(): TESTFN = tempfile.mktemp() symlink_path = TESTFN + "can_symlink" @@ -26,13 +28,15 @@ def can_symlink(): globals().update(can_symlink=lambda: can) return can + def has_symlink(): bad_symlink = ( # Windows symlink directory detection is broken on Python 3.2 - platform.system() == 'Windows' and sys.version_info[:2] == (3,2) + platform.system() == 'Windows' and sys.version_info[:2] == (3, 2) ) return can_symlink() and not bad_symlink + class TestFindPackages: def setup_method(self, method): @@ -94,6 +98,15 @@ class TestFindPackages: packages = find_packages(self.dist_dir, exclude=('pkg.*',)) assert packages == ['pkg'] + def test_exclude_recursive(self): + """ + Excluding a parent package should exclude all child packages as well. + """ + self._touch('__init__.py', self.pkg_dir) + self._touch('__init__.py', self.sub_pkg_dir) + packages = find_packages(self.dist_dir, exclude=('pkg',)) + assert packages == [] + def test_include_excludes_other(self): """ If include is specified, other packages should be excluded. diff --git a/setuptools/tests/test_install_scripts.py b/setuptools/tests/test_install_scripts.py new file mode 100644 index 00000000..7393241f --- /dev/null +++ b/setuptools/tests/test_install_scripts.py @@ -0,0 +1,88 @@ +"""install_scripts tests +""" + +import io +import sys + +import pytest + +from setuptools.command.install_scripts import install_scripts +from setuptools.dist import Distribution +from . import contexts + + +class TestInstallScripts: + settings = dict( + name='foo', + entry_points={'console_scripts': ['foo=foo:foo']}, + version='0.0', + ) + unix_exe = '/usr/dummy-test-path/local/bin/python' + unix_spaces_exe = '/usr/bin/env dummy-test-python' + win32_exe = 'C:\\Dummy Test Path\\Program Files\\Python 3.3\\python.exe' + + def _run_install_scripts(self, install_dir, executable=None): + dist = Distribution(self.settings) + dist.script_name = 'setup.py' + cmd = install_scripts(dist) + cmd.install_dir = install_dir + if executable is not None: + bs = cmd.get_finalized_command('build_scripts') + bs.executable = executable + cmd.ensure_finalized() + with contexts.quiet(): + cmd.run() + + @pytest.mark.skipif(sys.platform == 'win32', reason='non-Windows only') + def test_sys_executable_escaping_unix(self, tmpdir, monkeypatch): + """ + Ensure that shebang is not quoted on Unix when getting the Python exe + from sys.executable. + """ + expected = '#!%s\n' % self.unix_exe + monkeypatch.setattr('sys.executable', self.unix_exe) + with tmpdir.as_cwd(): + self._run_install_scripts(str(tmpdir)) + with io.open(str(tmpdir.join('foo')), 'r') as f: + actual = f.readline() + assert actual == expected + + @pytest.mark.skipif(sys.platform != 'win32', reason='Windows only') + def test_sys_executable_escaping_win32(self, tmpdir, monkeypatch): + """ + Ensure that shebang is quoted on Windows when getting the Python exe + from sys.executable and it contains a space. + """ + expected = '#!"%s"\n' % self.win32_exe + monkeypatch.setattr('sys.executable', self.win32_exe) + with tmpdir.as_cwd(): + self._run_install_scripts(str(tmpdir)) + with io.open(str(tmpdir.join('foo-script.py')), 'r') as f: + actual = f.readline() + assert actual == expected + + @pytest.mark.skipif(sys.platform == 'win32', reason='non-Windows only') + def test_executable_with_spaces_escaping_unix(self, tmpdir): + """ + Ensure that shebang on Unix is not quoted, even when a value with spaces + is specified using --executable. + """ + expected = '#!%s\n' % self.unix_spaces_exe + with tmpdir.as_cwd(): + self._run_install_scripts(str(tmpdir), self.unix_spaces_exe) + with io.open(str(tmpdir.join('foo')), 'r') as f: + actual = f.readline() + assert actual == expected + + @pytest.mark.skipif(sys.platform != 'win32', reason='Windows only') + def test_executable_arg_escaping_win32(self, tmpdir): + """ + Ensure that shebang on Windows is quoted when getting a path with spaces + from --executable, that is itself properly quoted. + """ + expected = '#!"%s"\n' % self.win32_exe + with tmpdir.as_cwd(): + self._run_install_scripts(str(tmpdir), '"' + self.win32_exe + '"') + with io.open(str(tmpdir.join('foo-script.py')), 'r') as f: + actual = f.readline() + assert actual == expected diff --git a/setuptools/tests/test_manifest.py b/setuptools/tests/test_manifest.py new file mode 100644 index 00000000..6360270d --- /dev/null +++ b/setuptools/tests/test_manifest.py @@ -0,0 +1,476 @@ +# -*- coding: utf-8 -*- +"""sdist tests""" + +import contextlib +import os +import shutil +import sys +import tempfile +from distutils import log +from distutils.errors import DistutilsTemplateError + +from setuptools.command.egg_info import FileList, egg_info +from setuptools.dist import Distribution +from setuptools.extern import six +from setuptools.tests.textwrap import DALS + +import pytest + +py3_only = pytest.mark.xfail(six.PY2, reason="Test runs on Python 3 only") + + +def make_local_path(s): + """Converts '/' in a string to os.sep""" + return s.replace('/', os.sep) + + +SETUP_ATTRS = { + 'name': 'app', + 'version': '0.0', + 'packages': ['app'], +} + + +SETUP_PY = """\ +from setuptools import setup + +setup(**%r) +""" % SETUP_ATTRS + + +@contextlib.contextmanager +def quiet(): + old_stdout, old_stderr = sys.stdout, sys.stderr + sys.stdout, sys.stderr = six.StringIO(), six.StringIO() + try: + yield + finally: + sys.stdout, sys.stderr = old_stdout, old_stderr + + +def touch(filename): + open(filename, 'w').close() + + +# The set of files always in the manifest, including all files in the +# .egg-info directory +default_files = frozenset(map(make_local_path, [ + 'README.rst', + 'MANIFEST.in', + 'setup.py', + 'app.egg-info/PKG-INFO', + 'app.egg-info/SOURCES.txt', + 'app.egg-info/dependency_links.txt', + 'app.egg-info/top_level.txt', + 'app/__init__.py', +])) + + +class TempDirTestCase(object): + + def setup_method(self, method): + self.temp_dir = tempfile.mkdtemp() + self.old_cwd = os.getcwd() + os.chdir(self.temp_dir) + + def teardown_method(self, method): + os.chdir(self.old_cwd) + shutil.rmtree(self.temp_dir) + + +class TestManifestTest(TempDirTestCase): + + def setup_method(self, method): + super(TestManifestTest, self).setup_method(method) + + f = open(os.path.join(self.temp_dir, 'setup.py'), 'w') + f.write(SETUP_PY) + f.close() + + """ + Create a file tree like: + - LICENSE + - README.rst + - testing.rst + - .hidden.rst + - app/ + - __init__.py + - a.txt + - b.txt + - c.rst + - static/ + - app.js + - app.js.map + - app.css + - app.css.map + """ + + for fname in ['README.rst', '.hidden.rst', 'testing.rst', 'LICENSE']: + touch(os.path.join(self.temp_dir, fname)) + + # Set up the rest of the test package + test_pkg = os.path.join(self.temp_dir, 'app') + os.mkdir(test_pkg) + for fname in ['__init__.py', 'a.txt', 'b.txt', 'c.rst']: + touch(os.path.join(test_pkg, fname)) + + # Some compiled front-end assets to include + static = os.path.join(test_pkg, 'static') + os.mkdir(static) + for fname in ['app.js', 'app.js.map', 'app.css', 'app.css.map']: + touch(os.path.join(static, fname)) + + def make_manifest(self, contents): + """Write a MANIFEST.in.""" + with open(os.path.join(self.temp_dir, 'MANIFEST.in'), 'w') as f: + f.write(DALS(contents)) + + def get_files(self): + """Run egg_info and get all the files to include, as a set""" + dist = Distribution(SETUP_ATTRS) + dist.script_name = 'setup.py' + cmd = egg_info(dist) + cmd.ensure_finalized() + + cmd.run() + + return set(cmd.filelist.files) + + def test_no_manifest(self): + """Check a missing MANIFEST.in includes only the standard files.""" + assert (default_files - set(['MANIFEST.in'])) == self.get_files() + + def test_empty_files(self): + """Check an empty MANIFEST.in includes only the standard files.""" + self.make_manifest("") + assert default_files == self.get_files() + + def test_include(self): + """Include extra rst files in the project root.""" + self.make_manifest("include *.rst") + files = default_files | set([ + 'testing.rst', '.hidden.rst']) + assert files == self.get_files() + + def test_exclude(self): + """Include everything in app/ except the text files""" + l = make_local_path + self.make_manifest( + """ + include app/* + exclude app/*.txt + """) + files = default_files | set([l('app/c.rst')]) + assert files == self.get_files() + + def test_include_multiple(self): + """Include with multiple patterns.""" + l = make_local_path + self.make_manifest("include app/*.txt app/static/*") + files = default_files | set([ + l('app/a.txt'), l('app/b.txt'), + l('app/static/app.js'), l('app/static/app.js.map'), + l('app/static/app.css'), l('app/static/app.css.map')]) + assert files == self.get_files() + + def test_graft(self): + """Include the whole app/static/ directory.""" + l = make_local_path + self.make_manifest("graft app/static") + files = default_files | set([ + l('app/static/app.js'), l('app/static/app.js.map'), + l('app/static/app.css'), l('app/static/app.css.map')]) + assert files == self.get_files() + + def test_graft_global_exclude(self): + """Exclude all *.map files in the project.""" + l = make_local_path + self.make_manifest( + """ + graft app/static + global-exclude *.map + """) + files = default_files | set([ + l('app/static/app.js'), l('app/static/app.css')]) + assert files == self.get_files() + + def test_global_include(self): + """Include all *.rst, *.js, and *.css files in the whole tree.""" + l = make_local_path + self.make_manifest( + """ + global-include *.rst *.js *.css + """) + files = default_files | set([ + '.hidden.rst', 'testing.rst', l('app/c.rst'), + l('app/static/app.js'), l('app/static/app.css')]) + assert files == self.get_files() + + def test_graft_prune(self): + """Include all files in app/, except for the whole app/static/ dir.""" + l = make_local_path + self.make_manifest( + """ + graft app + prune app/static + """) + files = default_files | set([ + l('app/a.txt'), l('app/b.txt'), l('app/c.rst')]) + assert files == self.get_files() + + +class TestFileListTest(TempDirTestCase): + """ + A copy of the relevant bits of distutils/tests/test_filelist.py, + to ensure setuptools' version of FileList keeps parity with distutils. + """ + + def setup_method(self, method): + super(TestFileListTest, self).setup_method(method) + self.threshold = log.set_threshold(log.FATAL) + self._old_log = log.Log._log + log.Log._log = self._log + self.logs = [] + + def teardown_method(self, method): + log.set_threshold(self.threshold) + log.Log._log = self._old_log + super(TestFileListTest, self).teardown_method(method) + + def _log(self, level, msg, args): + if level not in (log.DEBUG, log.INFO, log.WARN, log.ERROR, log.FATAL): + raise ValueError('%s wrong log level' % str(level)) + self.logs.append((level, msg, args)) + + def get_logs(self, *levels): + def _format(msg, args): + if len(args) == 0: + return msg + return msg % args + return [_format(msg, args) for level, msg, args + in self.logs if level in levels] + + def clear_logs(self): + self.logs = [] + + def assertNoWarnings(self): + assert self.get_logs(log.WARN) == [] + self.clear_logs() + + def assertWarnings(self): + assert len(self.get_logs(log.WARN)) > 0 + self.clear_logs() + + def make_files(self, files): + for file in files: + file = os.path.join(self.temp_dir, file) + dirname, basename = os.path.split(file) + if not os.path.exists(dirname): + os.makedirs(dirname) + open(file, 'w').close() + + def test_process_template_line(self): + # testing all MANIFEST.in template patterns + file_list = FileList() + l = make_local_path + + # simulated file list + self.make_files([ + 'foo.tmp', 'ok', 'xo', 'four.txt', + 'buildout.cfg', + # filelist does not filter out VCS directories, + # it's sdist that does + l('.hg/last-message.txt'), + l('global/one.txt'), + l('global/two.txt'), + l('global/files.x'), + l('global/here.tmp'), + l('f/o/f.oo'), + l('dir/graft-one'), + l('dir/dir2/graft2'), + l('dir3/ok'), + l('dir3/sub/ok.txt'), + ]) + + MANIFEST_IN = DALS("""\ + include ok + include xo + exclude xo + include foo.tmp + include buildout.cfg + global-include *.x + global-include *.txt + global-exclude *.tmp + recursive-include f *.oo + recursive-exclude global *.x + graft dir + prune dir3 + """) + + for line in MANIFEST_IN.split('\n'): + if not line: + continue + file_list.process_template_line(line) + + wanted = [ + 'buildout.cfg', + 'four.txt', + 'ok', + l('.hg/last-message.txt'), + l('dir/graft-one'), + l('dir/dir2/graft2'), + l('f/o/f.oo'), + l('global/one.txt'), + l('global/two.txt'), + ] + file_list.sort() + + assert file_list.files == wanted + + def test_exclude_pattern(self): + # return False if no match + file_list = FileList() + assert not file_list.exclude_pattern('*.py') + + # return True if files match + file_list = FileList() + file_list.files = ['a.py', 'b.py'] + assert file_list.exclude_pattern('*.py') + + # test excludes + file_list = FileList() + file_list.files = ['a.py', 'a.txt'] + file_list.exclude_pattern('*.py') + assert file_list.files == ['a.txt'] + + def test_include_pattern(self): + # return False if no match + file_list = FileList() + file_list.set_allfiles([]) + assert not file_list.include_pattern('*.py') + + # return True if files match + file_list = FileList() + file_list.set_allfiles(['a.py', 'b.txt']) + assert file_list.include_pattern('*.py') + + # test * matches all files + file_list = FileList() + assert file_list.allfiles is None + file_list.set_allfiles(['a.py', 'b.txt']) + file_list.include_pattern('*') + assert file_list.allfiles == ['a.py', 'b.txt'] + + def test_process_template(self): + l = make_local_path + # invalid lines + file_list = FileList() + for action in ('include', 'exclude', 'global-include', + 'global-exclude', 'recursive-include', + 'recursive-exclude', 'graft', 'prune', 'blarg'): + try: + file_list.process_template_line(action) + except DistutilsTemplateError: + pass + except Exception: + assert False, "Incorrect error thrown" + else: + assert False, "Should have thrown an error" + + # include + file_list = FileList() + file_list.set_allfiles(['a.py', 'b.txt', l('d/c.py')]) + + file_list.process_template_line('include *.py') + assert file_list.files == ['a.py'] + self.assertNoWarnings() + + file_list.process_template_line('include *.rb') + assert file_list.files == ['a.py'] + self.assertWarnings() + + # exclude + file_list = FileList() + file_list.files = ['a.py', 'b.txt', l('d/c.py')] + + file_list.process_template_line('exclude *.py') + assert file_list.files == ['b.txt', l('d/c.py')] + self.assertNoWarnings() + + file_list.process_template_line('exclude *.rb') + assert file_list.files == ['b.txt', l('d/c.py')] + self.assertWarnings() + + # global-include + file_list = FileList() + file_list.set_allfiles(['a.py', 'b.txt', l('d/c.py')]) + + file_list.process_template_line('global-include *.py') + assert file_list.files == ['a.py', l('d/c.py')] + self.assertNoWarnings() + + file_list.process_template_line('global-include *.rb') + assert file_list.files == ['a.py', l('d/c.py')] + self.assertWarnings() + + # global-exclude + file_list = FileList() + file_list.files = ['a.py', 'b.txt', l('d/c.py')] + + file_list.process_template_line('global-exclude *.py') + assert file_list.files == ['b.txt'] + self.assertNoWarnings() + + file_list.process_template_line('global-exclude *.rb') + assert file_list.files == ['b.txt'] + self.assertWarnings() + + # recursive-include + file_list = FileList() + file_list.set_allfiles(['a.py', l('d/b.py'), l('d/c.txt'), + l('d/d/e.py')]) + + file_list.process_template_line('recursive-include d *.py') + assert file_list.files == [l('d/b.py'), l('d/d/e.py')] + self.assertNoWarnings() + + file_list.process_template_line('recursive-include e *.py') + assert file_list.files == [l('d/b.py'), l('d/d/e.py')] + self.assertWarnings() + + # recursive-exclude + file_list = FileList() + file_list.files = ['a.py', l('d/b.py'), l('d/c.txt'), l('d/d/e.py')] + + file_list.process_template_line('recursive-exclude d *.py') + assert file_list.files == ['a.py', l('d/c.txt')] + self.assertNoWarnings() + + file_list.process_template_line('recursive-exclude e *.py') + assert file_list.files == ['a.py', l('d/c.txt')] + self.assertWarnings() + + # graft + file_list = FileList() + file_list.set_allfiles(['a.py', l('d/b.py'), l('d/d/e.py'), + l('f/f.py')]) + + file_list.process_template_line('graft d') + assert file_list.files == [l('d/b.py'), l('d/d/e.py')] + self.assertNoWarnings() + + file_list.process_template_line('graft e') + assert file_list.files == [l('d/b.py'), l('d/d/e.py')] + self.assertWarnings() + + # prune + file_list = FileList() + file_list.files = ['a.py', l('d/b.py'), l('d/d/e.py'), l('f/f.py')] + + file_list.process_template_line('prune d') + assert file_list.files == ['a.py', l('f/f.py')] + self.assertNoWarnings() + + file_list.process_template_line('prune e') + assert file_list.files == ['a.py', l('f/f.py')] + self.assertWarnings() diff --git a/setuptools/tests/test_msvc9compiler.py b/setuptools/tests/test_msvc.py index 09e0460c..a0c76ea0 100644 --- a/setuptools/tests/test_msvc9compiler.py +++ b/setuptools/tests/test_msvc.py @@ -1,5 +1,5 @@ """ -Tests for msvc9compiler. +Tests for msvc support module. """ import os @@ -69,9 +69,9 @@ class TestModulePatch: def test_patched(self): "Test the module is actually patched" mod_name = distutils.msvc9compiler.find_vcvarsall.__module__ - assert mod_name == "setuptools.msvc9_support", "find_vcvarsall unpatched" + assert mod_name == "setuptools.msvc", "find_vcvarsall unpatched" - def test_no_registry_entryies_means_nothing_found(self): + def test_no_registry_entries_means_nothing_found(self): """ No registry entries or environment variable should lead to an error directing the user to download vcpython27. @@ -83,10 +83,12 @@ class TestModulePatch: with mock_reg(): assert find_vcvarsall(9.0) is None - expected = distutils.errors.DistutilsPlatformError - with pytest.raises(expected) as exc: + try: query_vcvarsall(9.0) - assert 'aka.ms/vcpython27' in str(exc) + except Exception as exc: + expected = distutils.errors.DistutilsPlatformError + assert isinstance(exc, expected) + assert 'aka.ms/vcpython27' in str(exc) @pytest.yield_fixture def user_preferred_setting(self): diff --git a/setuptools/tests/test_packageindex.py b/setuptools/tests/test_packageindex.py index 6a76b5fc..f9bf895b 100644 --- a/setuptools/tests/test_packageindex.py +++ b/setuptools/tests/test_packageindex.py @@ -7,14 +7,24 @@ import distutils.errors from setuptools.extern import six from setuptools.extern.six.moves import urllib, http_client -from .textwrap import DALS import pkg_resources import setuptools.package_index from setuptools.tests.server import IndexServer +from .textwrap import DALS class TestPackageIndex: + def test_regex(self): + hash_url = 'http://other_url?:action=show_md5&' + hash_url += 'digest=0123456789abcdef0123456789abcdef' + doc = """ + <a href="http://some_url">Name</a> + (<a title="MD5 hash" + href="{hash_url}">md5</a>) + """.lstrip().format(**locals()) + assert setuptools.package_index.PYPI_MD5.match(doc) + def test_bad_url_bad_port(self): index = setuptools.package_index.PackageIndex() url = 'http://127.0.0.1:0/nonesuch/test_package_index' @@ -129,7 +139,7 @@ class TestPackageIndex: # the distribution has been found assert 'foobar' in pi # we have only one link, because links are compared without md5 - assert len(pi['foobar'])==1 + assert len(pi['foobar']) == 1 # the link should be from the index assert 'correct_md5' in pi['foobar'][0].location @@ -209,6 +219,7 @@ class TestContentCheckers: class TestPyPIConfig: + def test_percent_in_password(self, tmpdir, monkeypatch): monkeypatch.setitem(os.environ, 'HOME', str(tmpdir)) pypirc = tmpdir / '.pypirc' diff --git a/setuptools/tests/test_sandbox.py b/setuptools/tests/test_sandbox.py index fefd46f7..aa6138e4 100644 --- a/setuptools/tests/test_sandbox.py +++ b/setuptools/tests/test_sandbox.py @@ -57,6 +57,7 @@ class TestSandbox: class TestExceptionSaver: + def test_exception_trapped(self): with setuptools.sandbox.ExceptionSaver(): raise ValueError("details") diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py index d2a1f1bb..16d0eb07 100644 --- a/setuptools/tests/test_sdist.py +++ b/setuptools/tests/test_sdist.py @@ -132,7 +132,6 @@ class TestSdistTest: assert os.path.join('sdist_test', 'b.txt') in manifest assert os.path.join('sdist_test', 'c.rst') not in manifest - def test_defaults_case_sensitivity(self): """ Make sure default files (README.*, etc.) are added in a case-sensitive |