aboutsummaryrefslogtreecommitdiffstats
path: root/setuptools/tests
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2019-01-27 10:02:52 -0500
committerGitHub <noreply@github.com>2019-01-27 10:02:52 -0500
commit0551421f082eea3f633bc6be23c16a04483aca98 (patch)
tree76c5b37e3a56a232b4b5b66ab7e933edbe64cd25 /setuptools/tests
parent28872fc9e7d15a1acf3bc557795c76c5e64dbad3 (diff)
parent78fd73026ad7284819936b651f7cfbe8a1ec98c8 (diff)
downloadexternal_python_setuptools-0551421f082eea3f633bc6be23c16a04483aca98.tar.gz
external_python_setuptools-0551421f082eea3f633bc6be23c16a04483aca98.tar.bz2
external_python_setuptools-0551421f082eea3f633bc6be23c16a04483aca98.zip
Merge branch 'master' into license-fix-357
Diffstat (limited to 'setuptools/tests')
-rw-r--r--setuptools/tests/files.py9
-rw-r--r--setuptools/tests/server.py14
-rw-r--r--setuptools/tests/test_build_clib.py9
-rw-r--r--setuptools/tests/test_build_meta.py72
-rw-r--r--setuptools/tests/test_config.py128
-rw-r--r--setuptools/tests/test_depends.py18
-rw-r--r--setuptools/tests/test_dist.py122
-rw-r--r--setuptools/tests/test_easy_install.py20
-rw-r--r--setuptools/tests/test_egg_info.py103
-rw-r--r--setuptools/tests/test_find_packages.py11
-rw-r--r--setuptools/tests/test_install_scripts.py6
-rw-r--r--setuptools/tests/test_integration.py23
-rw-r--r--setuptools/tests/test_manifest.py134
-rw-r--r--setuptools/tests/test_msvc.py5
-rw-r--r--setuptools/tests/test_namespaces.py3
-rw-r--r--setuptools/tests/test_packageindex.py74
-rw-r--r--setuptools/tests/test_pep425tags.py4
-rw-r--r--setuptools/tests/test_sandbox.py3
-rw-r--r--setuptools/tests/test_sdist.py48
-rw-r--r--setuptools/tests/test_setuptools.py9
-rw-r--r--setuptools/tests/test_test.py5
-rw-r--r--setuptools/tests/test_upload.py170
-rw-r--r--setuptools/tests/test_virtualenv.py14
-rw-r--r--setuptools/tests/test_wheel.py2
-rw-r--r--setuptools/tests/test_windows_wrappers.py13
25 files changed, 862 insertions, 157 deletions
diff --git a/setuptools/tests/files.py b/setuptools/tests/files.py
index 465a6b41..bad2189d 100644
--- a/setuptools/tests/files.py
+++ b/setuptools/tests/files.py
@@ -6,10 +6,13 @@ import pkg_resources.py31compat
def build_files(file_defs, prefix=""):
"""
- Build a set of files/directories, as described by the file_defs dictionary.
+ 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
+ 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:
diff --git a/setuptools/tests/server.py b/setuptools/tests/server.py
index 35312120..fc3a5975 100644
--- a/setuptools/tests/server.py
+++ b/setuptools/tests/server.py
@@ -19,10 +19,11 @@ class IndexServer(BaseHTTPServer.HTTPServer):
s.stop()
"""
- def __init__(self, server_address=('', 0),
+ def __init__(
+ self, server_address=('', 0),
RequestHandlerClass=SimpleHTTPServer.SimpleHTTPRequestHandler):
- BaseHTTPServer.HTTPServer.__init__(self, server_address,
- RequestHandlerClass)
+ BaseHTTPServer.HTTPServer.__init__(
+ self, server_address, RequestHandlerClass)
self._run = True
def start(self):
@@ -56,10 +57,11 @@ class MockServer(BaseHTTPServer.HTTPServer, threading.Thread):
A simple HTTP Server that records the requests made to it.
"""
- def __init__(self, server_address=('', 0),
+ def __init__(
+ self, server_address=('', 0),
RequestHandlerClass=RequestRecorder):
- BaseHTTPServer.HTTPServer.__init__(self, server_address,
- RequestHandlerClass)
+ BaseHTTPServer.HTTPServer.__init__(
+ self, server_address, RequestHandlerClass)
threading.Thread.__init__(self)
self.setDaemon(True)
self.requests = []
diff --git a/setuptools/tests/test_build_clib.py b/setuptools/tests/test_build_clib.py
index aebcc350..3779e679 100644
--- a/setuptools/tests/test_build_clib.py
+++ b/setuptools/tests/test_build_clib.py
@@ -1,6 +1,4 @@
import pytest
-import os
-import shutil
import mock
from distutils.errors import DistutilsSetupError
@@ -40,13 +38,14 @@ class TestBuildCLib:
# with that out of the way, let's see if the crude dependency
# system works
cmd.compiler = mock.MagicMock(spec=cmd.compiler)
- mock_newer.return_value = ([],[])
+ mock_newer.return_value = ([], [])
obj_deps = {'': ('global.h',), 'example.c': ('example.h',)}
- libs = [('example', {'sources': ['example.c'] ,'obj_deps': obj_deps})]
+ libs = [('example', {'sources': ['example.c'], 'obj_deps': obj_deps})]
cmd.build_libraries(libs)
- assert [['example.c', 'global.h', 'example.h']] in mock_newer.call_args[0]
+ assert [['example.c', 'global.h', 'example.h']] in \
+ mock_newer.call_args[0]
assert not cmd.compiler.compile.called
assert cmd.compiler.create_static_lib.call_count == 1
diff --git a/setuptools/tests/test_build_meta.py b/setuptools/tests/test_build_meta.py
index 7b195e2c..82b44c89 100644
--- a/setuptools/tests/test_build_meta.py
+++ b/setuptools/tests/test_build_meta.py
@@ -2,16 +2,20 @@ from __future__ import unicode_literals
import os
import shutil
+import tarfile
import pytest
+from setuptools.build_meta import build_sdist
from .files import build_files
from .textwrap import DALS
+from . import py2_only
__metaclass__ = type
-futures = pytest.importorskip('concurrent.futures')
-importlib = pytest.importorskip('importlib')
+# Backports on Python 2.7
+import importlib
+from concurrent import futures
class BuildBackendBase:
@@ -108,13 +112,13 @@ def build_backend(tmpdir, request):
def test_get_requires_for_build_wheel(build_backend):
actual = build_backend.get_requires_for_build_wheel()
- expected = ['six', 'setuptools', 'wheel']
+ expected = ['six', 'wheel']
assert sorted(actual) == sorted(expected)
def test_get_requires_for_build_sdist(build_backend):
actual = build_backend.get_requires_for_build_sdist()
- expected = ['six', 'setuptools']
+ expected = ['six']
assert sorted(actual) == sorted(expected)
@@ -143,7 +147,7 @@ def test_prepare_metadata_for_build_wheel(build_backend):
assert os.path.isfile(os.path.join(dist_dir, dist_info, 'METADATA'))
-@pytest.mark.skipif('sys.version_info > (3,)')
+@py2_only
def test_prepare_metadata_for_build_wheel_with_str(build_backend):
dist_dir = os.path.abspath(str('pip-dist-info'))
os.makedirs(dist_dir)
@@ -168,15 +172,67 @@ def test_build_sdist_version_change(build_backend):
sdist_name = build_backend.build_sdist(sdist_into_directory)
assert os.path.isfile(os.path.join(sdist_into_directory, sdist_name))
- # if the setup.py changes subsequent call of the build meta should still succeed, given the
+ # if the setup.py changes subsequent call of the build meta
+ # should still succeed, given the
# sdist_directory the frontend specifies is empty
with open(os.path.abspath("setup.py"), 'rt') as file_handler:
content = file_handler.read()
with open(os.path.abspath("setup.py"), 'wt') as file_handler:
- file_handler.write(content.replace("version='0.0.0'", "version='0.0.1'"))
+ file_handler.write(
+ content.replace("version='0.0.0'", "version='0.0.1'"))
shutil.rmtree(sdist_into_directory)
os.makedirs(sdist_into_directory)
sdist_name = build_backend.build_sdist("out_sdist")
- assert os.path.isfile(os.path.join(os.path.abspath("out_sdist"), sdist_name))
+ assert os.path.isfile(
+ os.path.join(os.path.abspath("out_sdist"), sdist_name))
+
+
+def test_build_sdist_setup_py_exists(tmpdir_cwd):
+ # If build_sdist is called from a script other than setup.py,
+ # ensure setup.py is include
+ build_files(defns[0])
+ targz_path = build_sdist("temp")
+ with tarfile.open(os.path.join("temp", targz_path)) as tar:
+ assert any('setup.py' in name for name in tar.getnames())
+
+
+def test_build_sdist_setup_py_manifest_excluded(tmpdir_cwd):
+ # Ensure that MANIFEST.in can exclude setup.py
+ files = {
+ 'setup.py': DALS("""
+ __import__('setuptools').setup(
+ name='foo',
+ version='0.0.0',
+ py_modules=['hello']
+ )"""),
+ 'hello.py': '',
+ 'MANIFEST.in': DALS("""
+ exclude setup.py
+ """)
+ }
+
+ build_files(files)
+ targz_path = build_sdist("temp")
+ with tarfile.open(os.path.join("temp", targz_path)) as tar:
+ assert not any('setup.py' in name for name in tar.getnames())
+
+
+def test_build_sdist_builds_targz_even_if_zip_indicated(tmpdir_cwd):
+ files = {
+ 'setup.py': DALS("""
+ __import__('setuptools').setup(
+ name='foo',
+ version='0.0.0',
+ py_modules=['hello']
+ )"""),
+ 'hello.py': '',
+ 'setup.cfg': DALS("""
+ [sdist]
+ formats=zip
+ """)
+ }
+
+ build_files(files)
+ build_sdist("temp")
diff --git a/setuptools/tests/test_config.py b/setuptools/tests/test_config.py
index 76759ec5..6b177709 100644
--- a/setuptools/tests/test_config.py
+++ b/setuptools/tests/test_config.py
@@ -1,10 +1,18 @@
+# -*- coding: UTF-8 -*-
+from __future__ import unicode_literals
+
import contextlib
import pytest
+
from distutils.errors import DistutilsOptionError, DistutilsFileError
from mock import patch
from setuptools.dist import Distribution, _Distribution
from setuptools.config import ConfigHandler, read_configuration
+from setuptools.extern.six.moves.configparser import InterpolationMissingOptionError
+from setuptools.tests import is_ascii
from . import py2_only, py3_only
+from .textwrap import DALS
+
class ErrConfigHandler(ConfigHandler):
"""Erroneous handler. Fails to implement required methods."""
@@ -16,12 +24,12 @@ def make_package_dir(name, base_dir, ns=False):
dir_package = dir_package.mkdir(dir_name)
init_file = None
if not ns:
- init_file = dir_package.join('__init__.py')
- init_file.write('')
+ init_file = dir_package.join('__init__.py')
+ init_file.write('')
return dir_package, init_file
-def fake_env(tmpdir, setup_cfg, setup_py=None, package_path='fake_package'):
+def fake_env(tmpdir, setup_cfg, setup_py=None, encoding='ascii', package_path='fake_package'):
if setup_py is None:
setup_py = (
@@ -31,7 +39,7 @@ def fake_env(tmpdir, setup_cfg, setup_py=None, package_path='fake_package'):
tmpdir.join('setup.py').write(setup_py)
config = tmpdir.join('setup.cfg')
- config.write(setup_cfg)
+ config.write(setup_cfg.encode(encoding), mode='wb')
package_dir, init_file = make_package_dir(package_path, tmpdir)
@@ -146,6 +154,24 @@ class TestMetadata:
assert metadata.download_url == 'http://test.test.com/test/'
assert metadata.maintainer_email == 'test@test.com'
+ def test_license_cfg(self, tmpdir):
+ fake_env(
+ tmpdir,
+ DALS("""
+ [metadata]
+ name=foo
+ version=0.0.1
+ license=Apache 2.0
+ """)
+ )
+
+ with get_dist(tmpdir) as dist:
+ metadata = dist.metadata
+
+ assert metadata.name == "foo"
+ assert metadata.version == "0.0.1"
+ assert metadata.license == "Apache 2.0"
+
def test_file_mixed(self, tmpdir):
fake_env(
@@ -288,7 +314,7 @@ class TestMetadata:
tmpdir.join('fake_package', 'version.txt').write('1.2.3\n4.5.6\n')
with pytest.raises(DistutilsOptionError):
with get_dist(tmpdir) as dist:
- _ = dist.metadata.version
+ dist.metadata.version
def test_version_with_package_dir_simple(self, tmpdir):
@@ -391,6 +417,89 @@ class TestMetadata:
with get_dist(tmpdir) as dist:
assert set(dist.metadata.classifiers) == expected
+ def test_deprecated_config_handlers(self, tmpdir):
+ fake_env(
+ tmpdir,
+ '[metadata]\n'
+ 'version = 10.1.1\n'
+ 'description = Some description\n'
+ 'requires = some, requirement\n'
+ )
+
+ with pytest.deprecated_call():
+ with get_dist(tmpdir) as dist:
+ metadata = dist.metadata
+
+ assert metadata.version == '10.1.1'
+ assert metadata.description == 'Some description'
+ assert metadata.requires == ['some', 'requirement']
+
+ def test_interpolation(self, tmpdir):
+ fake_env(
+ tmpdir,
+ '[metadata]\n'
+ 'description = %(message)s\n'
+ )
+ with pytest.raises(InterpolationMissingOptionError):
+ with get_dist(tmpdir):
+ pass
+
+ skip_if_not_ascii = pytest.mark.skipif(not is_ascii, reason='Test not supported with this locale')
+
+ @skip_if_not_ascii
+ def test_non_ascii_1(self, tmpdir):
+ fake_env(
+ tmpdir,
+ '[metadata]\n'
+ 'description = éàïôñ\n',
+ encoding='utf-8'
+ )
+ with pytest.raises(UnicodeDecodeError):
+ with get_dist(tmpdir):
+ pass
+
+ def test_non_ascii_2(self, tmpdir):
+ fake_env(
+ tmpdir,
+ '# -*- coding: invalid\n'
+ )
+ with pytest.raises(LookupError):
+ with get_dist(tmpdir):
+ pass
+
+ def test_non_ascii_3(self, tmpdir):
+ fake_env(
+ tmpdir,
+ '\n'
+ '# -*- coding: invalid\n'
+ )
+ with get_dist(tmpdir):
+ pass
+
+ @skip_if_not_ascii
+ def test_non_ascii_4(self, tmpdir):
+ fake_env(
+ tmpdir,
+ '# -*- coding: utf-8\n'
+ '[metadata]\n'
+ 'description = éàïôñ\n',
+ encoding='utf-8'
+ )
+ with get_dist(tmpdir) as dist:
+ assert dist.metadata.description == 'éàïôñ'
+
+ @skip_if_not_ascii
+ def test_non_ascii_5(self, tmpdir):
+ fake_env(
+ tmpdir,
+ '# vim: set fileencoding=iso-8859-15 :\n'
+ '[metadata]\n'
+ 'description = éàïôñ\n',
+ encoding='iso-8859-15'
+ )
+ with get_dist(tmpdir) as dist:
+ assert dist.metadata.description == 'éàïôñ'
+
class TestOptions:
@@ -414,7 +523,7 @@ class TestOptions:
'tests_require = mock==0.7.2; pytest\n'
'setup_requires = docutils>=0.3; spack ==1.1, ==1.3; there\n'
'dependency_links = http://some.com/here/1, '
- 'http://some.com/there/2\n'
+ 'http://some.com/there/2\n'
'python_requires = >=1.0, !=2.8\n'
'py_modules = module1, module2\n'
)
@@ -622,7 +731,7 @@ class TestOptions:
dir_sub_two, _ = make_package_dir('sub_two', dir_package, ns=True)
with get_dist(tmpdir) as dist:
- assert set(dist.packages) == {
+ assert set(dist.packages) == {
'fake_package', 'fake_package.sub_two', 'fake_package.sub_one'
}
@@ -674,7 +783,7 @@ class TestOptions:
tmpdir,
'[options.entry_points]\n'
'group1 = point1 = pack.module:func, '
- '.point2 = pack.module2:func_rest [rest]\n'
+ '.point2 = pack.module2:func_rest [rest]\n'
'group2 = point3 = pack.module:func2\n'
)
@@ -720,7 +829,10 @@ class TestOptions:
]
assert sorted(dist.data_files) == sorted(expected)
+
saved_dist_init = _Distribution.__init__
+
+
class TestExternalSetters:
# During creation of the setuptools Distribution() object, we call
# the init of the parent distutils Distribution object via
diff --git a/setuptools/tests/test_depends.py b/setuptools/tests/test_depends.py
index e0cfa880..bff1dfb1 100644
--- a/setuptools/tests/test_depends.py
+++ b/setuptools/tests/test_depends.py
@@ -5,12 +5,12 @@ from setuptools import depends
class TestGetModuleConstant:
- def test_basic(self):
- """
- Invoke get_module_constant on a module in
- the test package.
- """
- mod_name = 'setuptools.tests.mod_with_constant'
- val = depends.get_module_constant(mod_name, 'value')
- assert val == 'three, sir!'
- assert 'setuptools.tests.mod_with_constant' not in sys.modules
+ def test_basic(self):
+ """
+ Invoke get_module_constant on a module in
+ the test package.
+ """
+ mod_name = 'setuptools.tests.mod_with_constant'
+ val = depends.get_module_constant(mod_name, 'value')
+ assert val == 'three, sir!'
+ assert 'setuptools.tests.mod_with_constant' not in sys.modules
diff --git a/setuptools/tests/test_dist.py b/setuptools/tests/test_dist.py
index 5162e1c9..390c3dfc 100644
--- a/setuptools/tests/test_dist.py
+++ b/setuptools/tests/test_dist.py
@@ -3,10 +3,11 @@
from __future__ import unicode_literals
import io
-
+from setuptools.dist import DistDeprecationWarning, _get_unpatched
from setuptools import Distribution
from setuptools.extern.six.moves.urllib.request import pathname2url
from setuptools.extern.six.moves.urllib_parse import urljoin
+from setuptools.extern import six
from .textwrap import DALS
from .test_easy_install import make_nspkg_sdist
@@ -56,6 +57,125 @@ def test_dist_fetch_build_egg(tmpdir):
assert [dist.key for dist in resolved_dists if dist] == reqs
+def test_dist__get_unpatched_deprecated():
+ pytest.warns(DistDeprecationWarning, _get_unpatched, [""])
+
+
+def __read_test_cases():
+ # Metadata version 1.0
+ base_attrs = {
+ "name": "package",
+ "version": "0.0.1",
+ "author": "Foo Bar",
+ "author_email": "foo@bar.net",
+ "long_description": "Long\ndescription",
+ "description": "Short description",
+ "keywords": ["one", "two"]
+ }
+
+ def merge_dicts(d1, d2):
+ d1 = d1.copy()
+ d1.update(d2)
+
+ return d1
+
+ test_cases = [
+ ('Metadata version 1.0', base_attrs.copy()),
+ ('Metadata version 1.1: Provides', merge_dicts(base_attrs, {
+ 'provides': ['package']
+ })),
+ ('Metadata version 1.1: Obsoletes', merge_dicts(base_attrs, {
+ 'obsoletes': ['foo']
+ })),
+ ('Metadata version 1.1: Classifiers', merge_dicts(base_attrs, {
+ 'classifiers': [
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.7',
+ 'License :: OSI Approved :: MIT License',
+ ]})),
+ ('Metadata version 1.1: Download URL', merge_dicts(base_attrs, {
+ 'download_url': 'https://example.com'
+ })),
+ ('Metadata Version 1.2: Requires-Python', merge_dicts(base_attrs, {
+ 'python_requires': '>=3.7'
+ })),
+ pytest.param(
+ 'Metadata Version 1.2: Project-Url',
+ merge_dicts(base_attrs, {
+ 'project_urls': {
+ 'Foo': 'https://example.bar'
+ }
+ }), marks=pytest.mark.xfail(
+ reason="Issue #1578: project_urls not read"
+ )),
+ ('Metadata Version 2.1: Long Description Content Type',
+ merge_dicts(base_attrs, {
+ 'long_description_content_type': 'text/x-rst; charset=UTF-8'
+ })),
+ pytest.param(
+ 'Metadata Version 2.1: Provides Extra',
+ merge_dicts(base_attrs, {
+ 'provides_extras': ['foo', 'bar']
+ }), marks=pytest.mark.xfail(reason="provides_extras not read")),
+ ('Missing author, missing author e-mail',
+ {'name': 'foo', 'version': '1.0.0'}),
+ ('Missing author',
+ {'name': 'foo',
+ 'version': '1.0.0',
+ 'author_email': 'snorri@sturluson.name'}),
+ ('Missing author e-mail',
+ {'name': 'foo',
+ 'version': '1.0.0',
+ 'author': 'Snorri Sturluson'}),
+ ('Missing author',
+ {'name': 'foo',
+ 'version': '1.0.0',
+ 'author': 'Snorri Sturluson'}),
+ ]
+
+ return test_cases
+
+
+@pytest.mark.parametrize('name,attrs', __read_test_cases())
+def test_read_metadata(name, attrs):
+ dist = Distribution(attrs)
+ metadata_out = dist.metadata
+ dist_class = metadata_out.__class__
+
+ # Write to PKG_INFO and then load into a new metadata object
+ if six.PY2:
+ PKG_INFO = io.BytesIO()
+ else:
+ PKG_INFO = io.StringIO()
+
+ metadata_out.write_pkg_file(PKG_INFO)
+
+ PKG_INFO.seek(0)
+ metadata_in = dist_class()
+ metadata_in.read_pkg_file(PKG_INFO)
+
+ tested_attrs = [
+ ('name', dist_class.get_name),
+ ('version', dist_class.get_version),
+ ('author', dist_class.get_contact),
+ ('author_email', dist_class.get_contact_email),
+ ('metadata_version', dist_class.get_metadata_version),
+ ('provides', dist_class.get_provides),
+ ('description', dist_class.get_description),
+ ('download_url', dist_class.get_download_url),
+ ('keywords', dist_class.get_keywords),
+ ('platforms', dist_class.get_platforms),
+ ('obsoletes', dist_class.get_obsoletes),
+ ('requires', dist_class.get_requires),
+ ('classifiers', dist_class.get_classifiers),
+ ('project_urls', lambda s: getattr(s, 'project_urls', {})),
+ ('provides_extras', lambda s: getattr(s, 'provides_extras', set())),
+ ]
+
+ for attr, getter in tested_attrs:
+ assert getter(metadata_in) == getter(metadata_out)
+
+
def __maintainer_test_cases():
attrs = {"name": "package",
"version": "1.0",
diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py
index b0cc4c9f..c3fd1c6e 100644
--- a/setuptools/tests/test_easy_install.py
+++ b/setuptools/tests/test_easy_install.py
@@ -15,7 +15,9 @@ import distutils.errors
import io
import zipfile
import mock
-
+from setuptools.command.easy_install import (
+ EasyInstallDeprecationWarning, ScriptWriter, WindowsScriptWriter,
+)
import time
from setuptools.extern import six
from setuptools.extern.six.moves import urllib
@@ -287,6 +289,22 @@ class TestEasyInstallTest:
cmd.easy_install(sdist_script)
assert (target / 'mypkg_script').exists()
+ def test_dist_get_script_args_deprecated(self):
+ with pytest.warns(EasyInstallDeprecationWarning):
+ ScriptWriter.get_script_args(None, None)
+
+ def test_dist_get_script_header_deprecated(self):
+ with pytest.warns(EasyInstallDeprecationWarning):
+ ScriptWriter.get_script_header("")
+
+ def test_dist_get_writer_deprecated(self):
+ with pytest.warns(EasyInstallDeprecationWarning):
+ ScriptWriter.get_writer(None)
+
+ def test_dist_WindowsScriptWriter_get_writer_deprecated(self):
+ with pytest.warns(EasyInstallDeprecationWarning):
+ WindowsScriptWriter.get_writer()
+
@pytest.mark.filterwarnings('ignore:Unbuilt egg')
class TestPTHFileWriter:
diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py
index 7c862e61..db9c3873 100644
--- a/setuptools/tests/test_egg_info.py
+++ b/setuptools/tests/test_egg_info.py
@@ -1,4 +1,3 @@
-import datetime
import sys
import ast
import os
@@ -7,7 +6,9 @@ import re
import stat
import time
-from setuptools.command.egg_info import egg_info, manifest_maker
+from setuptools.command.egg_info import (
+ egg_info, manifest_maker, EggInfoDeprecationWarning, get_pkg_info_revision,
+)
from setuptools.dist import Distribution
from setuptools.extern.six.moves import map
@@ -148,6 +149,37 @@ class TestEggInfo:
]
assert sorted(actual) == expected
+ def test_license_is_a_string(self, tmpdir_cwd, env):
+ setup_config = DALS("""
+ [metadata]
+ name=foo
+ version=0.0.1
+ license=file:MIT
+ """)
+
+ setup_script = DALS("""
+ from setuptools import setup
+
+ setup()
+ """)
+
+ build_files({'setup.py': setup_script,
+ 'setup.cfg': setup_config})
+
+ # This command should fail with a ValueError, but because it's
+ # currently configured to use a subprocess, the actual traceback
+ # object is lost and we need to parse it from stderr
+ with pytest.raises(AssertionError) as exc:
+ self._run_egg_info_command(tmpdir_cwd, env)
+
+ # Hopefully this is not too fragile: the only argument to the
+ # assertion error should be a traceback, ending with:
+ # ValueError: ....
+ #
+ # assert not 1
+ tb = exc.value.args[0].split('\n')
+ assert tb[-3].lstrip().startswith('ValueError')
+
def test_rebuilt(self, tmpdir_cwd, env):
"""Ensure timestamps are updated when the command is re-run."""
self._create_project()
@@ -618,6 +650,20 @@ class TestEggInfo:
for msg in fixtures:
assert manifest_maker._should_suppress_warning(msg)
+ def test_egg_info_includes_setup_py(self, tmpdir_cwd):
+ self._create_project()
+ dist = Distribution({"name": "foo", "version": "0.0.1"})
+ dist.script_name = "non_setup.py"
+ egg_info_instance = egg_info(dist)
+ egg_info_instance.finalize_options()
+ egg_info_instance.run()
+
+ assert 'setup.py' in egg_info_instance.filelist.files
+
+ with open(egg_info_instance.egg_info + "/SOURCES.txt") as f:
+ sources = f.read().split('\n')
+ assert 'setup.py' in sources
+
def _run_egg_info_command(self, tmpdir_cwd, env, cmd=None, output=None):
environ = os.environ.copy().update(
HOME=env.paths['home'],
@@ -632,8 +678,8 @@ class TestEggInfo:
data_stream=1,
env=environ,
)
- if code:
- raise AssertionError(data)
+ assert not code, data
+
if output:
assert output in data
@@ -652,3 +698,52 @@ class TestEggInfo:
with open(os.path.join(egg_info_dir, 'PKG-INFO')) as pkginfo_file:
pkg_info_lines = pkginfo_file.read().split('\n')
assert 'Version: 0.0.0.dev0' in pkg_info_lines
+
+ def test_get_pkg_info_revision_deprecated(self):
+ pytest.warns(EggInfoDeprecationWarning, get_pkg_info_revision)
+
+ EGG_INFO_TESTS = (
+ # Check for issue #1136: invalid string type when
+ # reading declarative `setup.cfg` under Python 2.
+ {
+ 'setup.py': DALS(
+ """
+ from setuptools import setup
+ setup(
+ name="foo",
+ )
+ """),
+ 'setup.cfg': DALS(
+ """
+ [options]
+ package_dir =
+ = src
+ """),
+ 'src': {},
+ },
+ # Check Unicode can be used in `setup.py` under Python 2.
+ {
+ 'setup.py': DALS(
+ """
+ # -*- coding: utf-8 -*-
+ from __future__ import unicode_literals
+ from setuptools import setup, find_packages
+ setup(
+ name="foo",
+ package_dir={'': 'src'},
+ )
+ """),
+ 'src': {},
+ }
+ )
+
+ @pytest.mark.parametrize('package_files', EGG_INFO_TESTS)
+ def test_egg_info(self, tmpdir_cwd, env, package_files):
+ """
+ """
+ build_files(package_files)
+ code, data = environment.run_setup_py(
+ cmd=['egg_info'],
+ data_stream=1,
+ )
+ assert not code, data
diff --git a/setuptools/tests/test_find_packages.py b/setuptools/tests/test_find_packages.py
index b08f91c7..ab26b4f1 100644
--- a/setuptools/tests/test_find_packages.py
+++ b/setuptools/tests/test_find_packages.py
@@ -12,10 +12,10 @@ from . import py3_only
from setuptools.extern.six import PY3
from setuptools import find_packages
if PY3:
- from setuptools import find_namespace_packages
+ from setuptools import find_namespace_packages
-# modeled after CPython's test.support.can_symlink
+# modeled after CPython's test.support.can_symlink
def can_symlink():
TESTFN = tempfile.mktemp()
symlink_path = TESTFN + "can_symlink"
@@ -164,12 +164,14 @@ class TestFindPackages:
def test_pep420_ns_package_no_includes(self):
packages = find_namespace_packages(
self.dist_dir, exclude=['pkg.subpkg.assets'])
- self._assert_packages(packages, ['docs', 'pkg', 'pkg.nspkg', 'pkg.subpkg'])
+ self._assert_packages(
+ packages, ['docs', 'pkg', 'pkg.nspkg', 'pkg.subpkg'])
@py3_only
def test_pep420_ns_package_no_includes_or_excludes(self):
packages = find_namespace_packages(self.dist_dir)
- expected = ['docs', 'pkg', 'pkg.nspkg', 'pkg.subpkg', 'pkg.subpkg.assets']
+ expected = [
+ 'docs', 'pkg', 'pkg.nspkg', 'pkg.subpkg', 'pkg.subpkg.assets']
self._assert_packages(packages, expected)
@py3_only
@@ -185,4 +187,3 @@ class TestFindPackages:
shutil.rmtree(os.path.join(self.dist_dir, 'pkg/subpkg/assets'))
packages = find_namespace_packages(self.dist_dir)
self._assert_packages(packages, ['pkg', 'pkg.nspkg', 'pkg.subpkg'])
-
diff --git a/setuptools/tests/test_install_scripts.py b/setuptools/tests/test_install_scripts.py
index 727ad65b..4338c792 100644
--- a/setuptools/tests/test_install_scripts.py
+++ b/setuptools/tests/test_install_scripts.py
@@ -64,7 +64,8 @@ class TestInstallScripts:
@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
+ 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
@@ -77,7 +78,8 @@ class TestInstallScripts:
@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
+ 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
diff --git a/setuptools/tests/test_integration.py b/setuptools/tests/test_integration.py
index 3a9a6c50..e54f3209 100644
--- a/setuptools/tests/test_integration.py
+++ b/setuptools/tests/test_integration.py
@@ -6,6 +6,11 @@ Try to install a few packages.
import glob
import os
import sys
+import re
+import subprocess
+import functools
+import tarfile
+import zipfile
from setuptools.extern.six.moves import urllib
import pytest
@@ -114,15 +119,12 @@ def test_pyuri(install_context):
assert os.path.exists(os.path.join(pyuri.location, 'pyuri', 'uri.regex'))
-import re
-import subprocess
-import functools
-import tarfile, zipfile
+build_deps = ['appdirs', 'packaging', 'pyparsing', 'six']
-build_deps = ['appdirs', 'packaging', 'pyparsing', 'six']
@pytest.mark.parametrize("build_dep", build_deps)
-@pytest.mark.skipif(sys.version_info < (3, 6), reason='run only on late versions')
+@pytest.mark.skipif(
+ sys.version_info < (3, 6), reason='run only on late versions')
def test_build_deps_on_distutils(request, tmpdir_factory, build_dep):
"""
All setuptools build dependencies must build without
@@ -149,13 +151,16 @@ def install(pkg_dir, install_dir):
breaker.write('raise ImportError()')
cmd = [sys.executable, 'setup.py', 'install', '--prefix', install_dir]
env = dict(os.environ, PYTHONPATH=pkg_dir)
- output = subprocess.check_output(cmd, cwd=pkg_dir, env=env, stderr=subprocess.STDOUT)
+ output = subprocess.check_output(
+ cmd, cwd=pkg_dir, env=env, stderr=subprocess.STDOUT)
return output.decode('utf-8')
def download_and_extract(request, req, target):
- cmd = [sys.executable, '-m', 'pip', 'download', '--no-deps',
- '--no-binary', ':all:', req]
+ cmd = [
+ sys.executable, '-m', 'pip', 'download', '--no-deps',
+ '--no-binary', ':all:', req,
+ ]
output = subprocess.check_output(cmd, encoding='utf-8')
filename = re.search('Saved (.*)', output).group(1)
request.addfinalizer(functools.partial(os.remove, filename))
diff --git a/setuptools/tests/test_manifest.py b/setuptools/tests/test_manifest.py
index c9533dda..2a0e9c86 100644
--- a/setuptools/tests/test_manifest.py
+++ b/setuptools/tests/test_manifest.py
@@ -20,8 +20,6 @@ import pytest
__metaclass__ = type
-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"""
@@ -75,7 +73,9 @@ translate_specs = [
# Glob matching
('*.txt', ['foo.txt', 'bar.txt'], ['foo/foo.txt']),
- ('dir/*.txt', ['dir/foo.txt', 'dir/bar.txt', 'dir/.txt'], ['notdir/foo.txt']),
+ (
+ 'dir/*.txt',
+ ['dir/foo.txt', 'dir/bar.txt', 'dir/.txt'], ['notdir/foo.txt']),
('*/*.py', ['bin/start.py'], []),
('docs/page-?.txt', ['docs/page-9.txt'], ['docs/page-10.txt']),
@@ -244,77 +244,77 @@ class TestManifestTest(TempDirTestCase):
def test_exclude(self):
"""Include everything in app/ except the text files"""
- l = make_local_path
+ ml = make_local_path
self.make_manifest(
"""
include app/*
exclude app/*.txt
""")
- files = default_files | set([l('app/c.rst')])
+ files = default_files | set([ml('app/c.rst')])
assert files == self.get_files()
def test_include_multiple(self):
"""Include with multiple patterns."""
- l = make_local_path
+ ml = 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')])
+ ml('app/a.txt'), ml('app/b.txt'),
+ ml('app/static/app.js'), ml('app/static/app.js.map'),
+ ml('app/static/app.css'), ml('app/static/app.css.map')])
assert files == self.get_files()
def test_graft(self):
"""Include the whole app/static/ directory."""
- l = make_local_path
+ ml = 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')])
+ ml('app/static/app.js'), ml('app/static/app.js.map'),
+ ml('app/static/app.css'), ml('app/static/app.css.map')])
assert files == self.get_files()
def test_graft_glob_syntax(self):
"""Include the whole app/static/ directory."""
- l = make_local_path
+ ml = make_local_path
self.make_manifest("graft */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')])
+ ml('app/static/app.js'), ml('app/static/app.js.map'),
+ ml('app/static/app.css'), ml('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
+ ml = 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')])
+ ml('app/static/app.js'), ml('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
+ ml = 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')])
+ '.hidden.rst', 'testing.rst', ml('app/c.rst'),
+ ml('app/static/app.js'), ml('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
+ ml = 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')])
+ ml('app/a.txt'), ml('app/b.txt'), ml('app/c.rst')])
assert files == self.get_files()
@@ -370,7 +370,7 @@ class TestFileListTest(TempDirTestCase):
def test_process_template_line(self):
# testing all MANIFEST.in template patterns
file_list = FileList()
- l = make_local_path
+ ml = make_local_path
# simulated file list
self.make_files([
@@ -378,16 +378,16 @@ class TestFileListTest(TempDirTestCase):
'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'),
+ ml('.hg/last-message.txt'),
+ ml('global/one.txt'),
+ ml('global/two.txt'),
+ ml('global/files.x'),
+ ml('global/here.tmp'),
+ ml('f/o/f.oo'),
+ ml('dir/graft-one'),
+ ml('dir/dir2/graft2'),
+ ml('dir3/ok'),
+ ml('dir3/sub/ok.txt'),
])
MANIFEST_IN = DALS("""\
@@ -414,12 +414,12 @@ class TestFileListTest(TempDirTestCase):
'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'),
+ ml('.hg/last-message.txt'),
+ ml('dir/graft-one'),
+ ml('dir/dir2/graft2'),
+ ml('f/o/f.oo'),
+ ml('global/one.txt'),
+ ml('global/two.txt'),
]
file_list.sort()
@@ -476,10 +476,10 @@ class TestFileListTest(TempDirTestCase):
assert False, "Should have thrown an error"
def test_include(self):
- l = make_local_path
+ ml = make_local_path
# include
file_list = FileList()
- self.make_files(['a.py', 'b.txt', l('d/c.py')])
+ self.make_files(['a.py', 'b.txt', ml('d/c.py')])
file_list.process_template_line('include *.py')
file_list.sort()
@@ -492,42 +492,42 @@ class TestFileListTest(TempDirTestCase):
self.assertWarnings()
def test_exclude(self):
- l = make_local_path
+ ml = make_local_path
# exclude
file_list = FileList()
- file_list.files = ['a.py', 'b.txt', l('d/c.py')]
+ file_list.files = ['a.py', 'b.txt', ml('d/c.py')]
file_list.process_template_line('exclude *.py')
file_list.sort()
- assert file_list.files == ['b.txt', l('d/c.py')]
+ assert file_list.files == ['b.txt', ml('d/c.py')]
self.assertNoWarnings()
file_list.process_template_line('exclude *.rb')
file_list.sort()
- assert file_list.files == ['b.txt', l('d/c.py')]
+ assert file_list.files == ['b.txt', ml('d/c.py')]
self.assertWarnings()
def test_global_include(self):
- l = make_local_path
+ ml = make_local_path
# global-include
file_list = FileList()
- self.make_files(['a.py', 'b.txt', l('d/c.py')])
+ self.make_files(['a.py', 'b.txt', ml('d/c.py')])
file_list.process_template_line('global-include *.py')
file_list.sort()
- assert file_list.files == ['a.py', l('d/c.py')]
+ assert file_list.files == ['a.py', ml('d/c.py')]
self.assertNoWarnings()
file_list.process_template_line('global-include *.rb')
file_list.sort()
- assert file_list.files == ['a.py', l('d/c.py')]
+ assert file_list.files == ['a.py', ml('d/c.py')]
self.assertWarnings()
def test_global_exclude(self):
- l = make_local_path
+ ml = make_local_path
# global-exclude
file_list = FileList()
- file_list.files = ['a.py', 'b.txt', l('d/c.py')]
+ file_list.files = ['a.py', 'b.txt', ml('d/c.py')]
file_list.process_template_line('global-exclude *.py')
file_list.sort()
@@ -540,65 +540,65 @@ class TestFileListTest(TempDirTestCase):
self.assertWarnings()
def test_recursive_include(self):
- l = make_local_path
+ ml = make_local_path
# recursive-include
file_list = FileList()
- self.make_files(['a.py', l('d/b.py'), l('d/c.txt'), l('d/d/e.py')])
+ self.make_files(['a.py', ml('d/b.py'), ml('d/c.txt'), ml('d/d/e.py')])
file_list.process_template_line('recursive-include d *.py')
file_list.sort()
- assert file_list.files == [l('d/b.py'), l('d/d/e.py')]
+ assert file_list.files == [ml('d/b.py'), ml('d/d/e.py')]
self.assertNoWarnings()
file_list.process_template_line('recursive-include e *.py')
file_list.sort()
- assert file_list.files == [l('d/b.py'), l('d/d/e.py')]
+ assert file_list.files == [ml('d/b.py'), ml('d/d/e.py')]
self.assertWarnings()
def test_recursive_exclude(self):
- l = make_local_path
+ ml = make_local_path
# 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.files = ['a.py', ml('d/b.py'), ml('d/c.txt'), ml('d/d/e.py')]
file_list.process_template_line('recursive-exclude d *.py')
file_list.sort()
- assert file_list.files == ['a.py', l('d/c.txt')]
+ assert file_list.files == ['a.py', ml('d/c.txt')]
self.assertNoWarnings()
file_list.process_template_line('recursive-exclude e *.py')
file_list.sort()
- assert file_list.files == ['a.py', l('d/c.txt')]
+ assert file_list.files == ['a.py', ml('d/c.txt')]
self.assertWarnings()
def test_graft(self):
- l = make_local_path
+ ml = make_local_path
# graft
file_list = FileList()
- self.make_files(['a.py', l('d/b.py'), l('d/d/e.py'), l('f/f.py')])
+ self.make_files(['a.py', ml('d/b.py'), ml('d/d/e.py'), ml('f/f.py')])
file_list.process_template_line('graft d')
file_list.sort()
- assert file_list.files == [l('d/b.py'), l('d/d/e.py')]
+ assert file_list.files == [ml('d/b.py'), ml('d/d/e.py')]
self.assertNoWarnings()
file_list.process_template_line('graft e')
file_list.sort()
- assert file_list.files == [l('d/b.py'), l('d/d/e.py')]
+ assert file_list.files == [ml('d/b.py'), ml('d/d/e.py')]
self.assertWarnings()
def test_prune(self):
- l = make_local_path
+ ml = make_local_path
# prune
file_list = FileList()
- file_list.files = ['a.py', l('d/b.py'), l('d/d/e.py'), l('f/f.py')]
+ file_list.files = ['a.py', ml('d/b.py'), ml('d/d/e.py'), ml('f/f.py')]
file_list.process_template_line('prune d')
file_list.sort()
- assert file_list.files == ['a.py', l('f/f.py')]
+ assert file_list.files == ['a.py', ml('f/f.py')]
self.assertNoWarnings()
file_list.process_template_line('prune e')
file_list.sort()
- assert file_list.files == ['a.py', l('f/f.py')]
+ assert file_list.files == ['a.py', ml('f/f.py')]
self.assertWarnings()
diff --git a/setuptools/tests/test_msvc.py b/setuptools/tests/test_msvc.py
index 32d7a907..24e38ea8 100644
--- a/setuptools/tests/test_msvc.py
+++ b/setuptools/tests/test_msvc.py
@@ -49,7 +49,8 @@ def mock_reg(hkcu=None, hklm=None):
for k in hive if k.startswith(key.lower())
)
- return mock.patch.multiple(distutils.msvc9compiler.Reg,
+ return mock.patch.multiple(
+ distutils.msvc9compiler.Reg,
read_keys=read_keys, read_values=read_values)
@@ -61,7 +62,7 @@ class TestModulePatch:
"""
key_32 = r'software\microsoft\devdiv\vcforpython\9.0\installdir'
- key_64 = r'software\wow6432node\microsoft\devdiv\vcforpython\9.0\installdir'
+ key_64 = key_32.replace(r'\microsoft', r'\wow6432node\microsoft')
def test_patched(self):
"Test the module is actually patched"
diff --git a/setuptools/tests/test_namespaces.py b/setuptools/tests/test_namespaces.py
index da19bd79..f937d981 100644
--- a/setuptools/tests/test_namespaces.py
+++ b/setuptools/tests/test_namespaces.py
@@ -1,6 +1,5 @@
from __future__ import absolute_import, unicode_literals
-import os
import sys
import subprocess
@@ -12,7 +11,7 @@ from setuptools.command import test
class TestNamespaces:
- @pytest.mark.xfail(
+ @pytest.mark.skipif(
sys.version_info < (3, 5),
reason="Requires importlib.util.module_from_spec",
)
diff --git a/setuptools/tests/test_packageindex.py b/setuptools/tests/test_packageindex.py
index 63b92946..ab371884 100644
--- a/setuptools/tests/test_packageindex.py
+++ b/setuptools/tests/test_packageindex.py
@@ -6,6 +6,8 @@ import distutils.errors
from setuptools.extern import six
from setuptools.extern.six.moves import urllib, http_client
+import mock
+import pytest
import pkg_resources
import setuptools.package_index
@@ -42,7 +44,10 @@ class TestPackageIndex:
hosts=('www.example.com',)
)
- url = 'url:%20https://svn.plone.org/svn/collective/inquant.contentmirror.plone/trunk'
+ url = (
+ 'url:%20https://svn.plone.org/svn'
+ '/collective/inquant.contentmirror.plone/trunk'
+ )
try:
v = index.open_url(url)
except Exception as v:
@@ -61,9 +66,9 @@ class TestPackageIndex:
index.opener = _urlopen
url = 'http://example.com'
try:
- v = index.open_url(url)
- except Exception as v:
- assert 'line' in str(v)
+ index.open_url(url)
+ except Exception as exc:
+ assert 'line' in str(exc)
else:
raise AssertionError('Should have raise here!')
@@ -81,7 +86,11 @@ class TestPackageIndex:
index.open_url(url)
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
+ assert (
+ 'nonnumeric port' in msg
+ or 'getaddrinfo failed' in msg
+ or 'Name or service not known' in msg
+ )
return
raise RuntimeError("Did not raise")
@@ -223,6 +232,61 @@ class TestPackageIndex:
assert dists[0].version == ''
assert dists[1].version == vc
+ def test_download_git_with_rev(self, tmpdir):
+ url = 'git+https://github.example/group/project@master#egg=foo'
+ index = setuptools.package_index.PackageIndex()
+
+ with mock.patch("os.system") as os_system_mock:
+ result = index.download(url, str(tmpdir))
+
+ os_system_mock.assert_called()
+
+ expected_dir = str(tmpdir / 'project@master')
+ expected = (
+ 'git clone --quiet '
+ 'https://github.example/group/project {expected_dir}'
+ ).format(**locals())
+ first_call_args = os_system_mock.call_args_list[0][0]
+ assert first_call_args == (expected,)
+
+ tmpl = '(cd {expected_dir} && git checkout --quiet master)'
+ expected = tmpl.format(**locals())
+ assert os_system_mock.call_args_list[1][0] == (expected,)
+ assert result == expected_dir
+
+ def test_download_git_no_rev(self, tmpdir):
+ url = 'git+https://github.example/group/project#egg=foo'
+ index = setuptools.package_index.PackageIndex()
+
+ with mock.patch("os.system") as os_system_mock:
+ result = index.download(url, str(tmpdir))
+
+ os_system_mock.assert_called()
+
+ expected_dir = str(tmpdir / 'project')
+ expected = (
+ 'git clone --quiet '
+ 'https://github.example/group/project {expected_dir}'
+ ).format(**locals())
+ os_system_mock.assert_called_once_with(expected)
+
+ def test_download_svn(self, tmpdir):
+ url = 'svn+https://svn.example/project#egg=foo'
+ index = setuptools.package_index.PackageIndex()
+
+ with pytest.warns(UserWarning):
+ with mock.patch("os.system") as os_system_mock:
+ result = index.download(url, str(tmpdir))
+
+ os_system_mock.assert_called()
+
+ expected_dir = str(tmpdir / 'project')
+ expected = (
+ 'svn checkout -q '
+ 'svn+https://svn.example/project {expected_dir}'
+ ).format(**locals())
+ os_system_mock.assert_called_once_with(expected)
+
class TestContentCheckers:
def test_md5(self):
diff --git a/setuptools/tests/test_pep425tags.py b/setuptools/tests/test_pep425tags.py
index f558a0d8..30afdec7 100644
--- a/setuptools/tests/test_pep425tags.py
+++ b/setuptools/tests/test_pep425tags.py
@@ -32,7 +32,9 @@ class TestPEP425Tags:
if sys.version_info < (3, 3):
config_vars.update({'Py_UNICODE_SIZE': 2})
mock_gcf = self.mock_get_config_var(**config_vars)
- with patch('setuptools.pep425tags.sysconfig.get_config_var', mock_gcf):
+ with patch(
+ 'setuptools.pep425tags.sysconfig.get_config_var',
+ mock_gcf):
abi_tag = pep425tags.get_abi_tag()
assert abi_tag == base + flags
diff --git a/setuptools/tests/test_sandbox.py b/setuptools/tests/test_sandbox.py
index d8675422..99398cdb 100644
--- a/setuptools/tests/test_sandbox.py
+++ b/setuptools/tests/test_sandbox.py
@@ -26,7 +26,8 @@ class TestSandbox:
"""
It should be possible to execute a setup.py with a Byte Order Mark
"""
- target = pkg_resources.resource_filename(__name__,
+ target = pkg_resources.resource_filename(
+ __name__,
'script-with-bom.py')
namespace = types.ModuleType('namespace')
setuptools.sandbox._execfile(target, vars(namespace))
diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py
index 02222da5..d2c4e0cf 100644
--- a/setuptools/tests/test_sdist.py
+++ b/setuptools/tests/test_sdist.py
@@ -20,8 +20,8 @@ from setuptools.command.egg_info import manifest_maker
from setuptools.dist import Distribution
from setuptools.tests import fail_on_ascii
from .text import Filenames
+from . import py3_only
-py3_only = pytest.mark.xfail(six.PY2, reason="Test runs on Python 3 only")
SETUP_ATTRS = {
'name': 'sdist_test',
@@ -92,9 +92,8 @@ fail_on_latin1_encoded_filenames = pytest.mark.xfail(
class TestSdistTest:
def setup_method(self, method):
self.temp_dir = tempfile.mkdtemp()
- f = open(os.path.join(self.temp_dir, 'setup.py'), 'w')
- f.write(SETUP_PY)
- f.close()
+ with open(os.path.join(self.temp_dir, 'setup.py'), 'w') as f:
+ f.write(SETUP_PY)
# Set up the rest of the test package
test_pkg = os.path.join(self.temp_dir, 'sdist_test')
@@ -135,6 +134,47 @@ class TestSdistTest:
assert os.path.join('sdist_test', 'c.rst') not in manifest
assert os.path.join('d', 'e.dat') in manifest
+ def test_setup_py_exists(self):
+ dist = Distribution(SETUP_ATTRS)
+ dist.script_name = 'foo.py'
+ cmd = sdist(dist)
+ cmd.ensure_finalized()
+
+ with quiet():
+ cmd.run()
+
+ manifest = cmd.filelist.files
+ assert 'setup.py' in manifest
+
+ def test_setup_py_missing(self):
+ dist = Distribution(SETUP_ATTRS)
+ dist.script_name = 'foo.py'
+ cmd = sdist(dist)
+ cmd.ensure_finalized()
+
+ if os.path.exists("setup.py"):
+ os.remove("setup.py")
+ with quiet():
+ cmd.run()
+
+ manifest = cmd.filelist.files
+ assert 'setup.py' not in manifest
+
+ def test_setup_py_excluded(self):
+ with open("MANIFEST.in", "w") as manifest_file:
+ manifest_file.write("exclude setup.py")
+
+ dist = Distribution(SETUP_ATTRS)
+ dist.script_name = 'foo.py'
+ cmd = sdist(dist)
+ cmd.ensure_finalized()
+
+ with quiet():
+ cmd.run()
+
+ manifest = cmd.filelist.files
+ assert 'setup.py' not in manifest
+
def test_defaults_case_sensitivity(self):
"""
Make sure default files (README.*, etc.) are added in a case-sensitive
diff --git a/setuptools/tests/test_setuptools.py b/setuptools/tests/test_setuptools.py
index 7aae3a16..5896a69a 100644
--- a/setuptools/tests/test_setuptools.py
+++ b/setuptools/tests/test_setuptools.py
@@ -77,7 +77,8 @@ class TestDepends:
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__
+ assert dep.get_module_constant(
+ 'setuptools.tests.test_setuptools', '__doc__') == __doc__
@needs_bytecode
def testRequire(self):
@@ -216,7 +217,8 @@ class TestFeatures:
self.req = Require('Distutils', '1.0.3', 'distutils')
self.dist = makeSetup(
features={
- 'foo': Feature("foo", standard=True, require_features=['baz', self.req]),
+ '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'],
),
@@ -252,7 +254,8 @@ class TestFeatures:
('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
diff --git a/setuptools/tests/test_test.py b/setuptools/tests/test_test.py
index 960527bc..faaa6ba9 100644
--- a/setuptools/tests/test_test.py
+++ b/setuptools/tests/test_test.py
@@ -4,7 +4,6 @@ from __future__ import unicode_literals
from distutils import log
import os
-import sys
import pytest
@@ -93,10 +92,6 @@ def test_test(capfd):
assert out == 'Foo\n'
-@pytest.mark.xfail(
- sys.version_info < (2, 7),
- reason="No discover support for unittest on Python 2.6",
-)
@pytest.mark.usefixtures('tmpdir_cwd', 'quiet_log')
def test_tests_are_run_once(capfd):
params = dict(
diff --git a/setuptools/tests/test_upload.py b/setuptools/tests/test_upload.py
index 95a8d16b..320c6959 100644
--- a/setuptools/tests/test_upload.py
+++ b/setuptools/tests/test_upload.py
@@ -1,13 +1,100 @@
import mock
+import os
+import re
+
from distutils import log
+from distutils.errors import DistutilsError
import pytest
from setuptools.command.upload import upload
from setuptools.dist import Distribution
+from setuptools.extern import six
+
+
+def _parse_upload_body(body):
+ boundary = u'\r\n----------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
+ entries = []
+ name_re = re.compile(u'^Content-Disposition: form-data; name="([^\"]+)"')
+
+ for entry in body.split(boundary):
+ pair = entry.split(u'\r\n\r\n')
+ if not len(pair) == 2:
+ continue
+
+ key, value = map(six.text_type.strip, pair)
+ m = name_re.match(key)
+ if m is not None:
+ key = m.group(1)
+
+ entries.append((key, value))
+
+ return entries
+
+
+@pytest.fixture
+def patched_upload(tmpdir):
+ class Fix:
+ def __init__(self, cmd, urlopen):
+ self.cmd = cmd
+ self.urlopen = urlopen
+
+ def __iter__(self):
+ return iter((self.cmd, self.urlopen))
+
+ def get_uploaded_metadata(self):
+ request = self.urlopen.call_args_list[0][0][0]
+ body = request.data.decode('utf-8')
+ entries = dict(_parse_upload_body(body))
+
+ return entries
+
+ class ResponseMock(mock.Mock):
+ def getheader(self, name, default=None):
+ """Mocked getheader method for response object"""
+ return {
+ 'content-type': 'text/plain; charset=utf-8',
+ }.get(name.lower(), default)
+
+ with mock.patch('setuptools.command.upload.urlopen') as urlopen:
+ urlopen.return_value = ResponseMock()
+ urlopen.return_value.getcode.return_value = 200
+ urlopen.return_value.read.return_value = b''
+
+ content = os.path.join(str(tmpdir), "content_data")
+
+ with open(content, 'w') as f:
+ f.write("Some content")
+
+ dist = Distribution()
+ dist.dist_files = [('sdist', '3.7.0', content)]
+
+ cmd = upload(dist)
+ cmd.announce = mock.Mock()
+ cmd.username = 'user'
+ cmd.password = 'hunter2'
+
+ yield Fix(cmd, urlopen)
class TestUploadTest:
+ def test_upload_metadata(self, patched_upload):
+ cmd, patch = patched_upload
+
+ # Set the metadata version to 2.1
+ cmd.distribution.metadata.metadata_version = '2.1'
+
+ # Run the command
+ cmd.ensure_finalized()
+ cmd.run()
+
+ # Make sure we did the upload
+ patch.assert_called_once()
+
+ # Make sure the metadata version is correct in the headers
+ entries = patched_upload.get_uploaded_metadata()
+ assert entries['metadata_version'] == '2.1'
+
def test_warns_deprecation(self):
dist = Distribution()
dist.dist_files = [(mock.Mock(), mock.Mock(), mock.Mock())]
@@ -41,3 +128,86 @@ class TestUploadTest:
"upload instead (https://pypi.org/p/twine/)",
log.WARN
)
+
+ @pytest.mark.parametrize('url', [
+ 'https://example.com/a;parameter', # Has parameters
+ 'https://example.com/a?query', # Has query
+ 'https://example.com/a#fragment', # Has fragment
+ 'ftp://example.com', # Invalid scheme
+
+ ])
+ def test_upload_file_invalid_url(self, url, patched_upload):
+ patched_upload.urlopen.side_effect = Exception("Should not be reached")
+
+ cmd = patched_upload.cmd
+ cmd.repository = url
+
+ cmd.ensure_finalized()
+ with pytest.raises(AssertionError):
+ cmd.run()
+
+ def test_upload_file_http_error(self, patched_upload):
+ patched_upload.urlopen.side_effect = six.moves.urllib.error.HTTPError(
+ 'https://example.com',
+ 404,
+ 'File not found',
+ None,
+ None
+ )
+
+ cmd = patched_upload.cmd
+ cmd.ensure_finalized()
+
+ with pytest.raises(DistutilsError):
+ cmd.run()
+
+ cmd.announce.assert_any_call(
+ 'Upload failed (404): File not found',
+ log.ERROR)
+
+ def test_upload_file_os_error(self, patched_upload):
+ patched_upload.urlopen.side_effect = OSError("Invalid")
+
+ cmd = patched_upload.cmd
+ cmd.ensure_finalized()
+
+ with pytest.raises(OSError):
+ cmd.run()
+
+ cmd.announce.assert_any_call('Invalid', log.ERROR)
+
+ @mock.patch('setuptools.command.upload.spawn')
+ def test_upload_file_gpg(self, spawn, patched_upload):
+ cmd, urlopen = patched_upload
+
+ cmd.sign = True
+ cmd.identity = "Alice"
+ cmd.dry_run = True
+ content_fname = cmd.distribution.dist_files[0][2]
+ signed_file = content_fname + '.asc'
+
+ with open(signed_file, 'wb') as f:
+ f.write("signed-data".encode('utf-8'))
+
+ cmd.ensure_finalized()
+ cmd.run()
+
+ # Make sure that GPG was called
+ spawn.assert_called_once_with([
+ "gpg", "--detach-sign", "--local-user", "Alice", "-a",
+ content_fname
+ ], dry_run=True)
+
+ # Read the 'signed' data that was transmitted
+ entries = patched_upload.get_uploaded_metadata()
+ assert entries['gpg_signature'] == 'signed-data'
+
+ def test_show_response_no_error(self, patched_upload):
+ # This test is just that show_response doesn't throw an error
+ # It is not really important what the printed response looks like
+ # in a deprecated command, but we don't want to introduce new
+ # errors when importing this function from distutils
+
+ patched_upload.cmd.show_response = True
+ patched_upload.cmd.ensure_finalized()
+ patched_upload.cmd.run()
diff --git a/setuptools/tests/test_virtualenv.py b/setuptools/tests/test_virtualenv.py
index b66a311d..3d5c84b0 100644
--- a/setuptools/tests/test_virtualenv.py
+++ b/setuptools/tests/test_virtualenv.py
@@ -57,9 +57,6 @@ def test_pip_upgrade_from_source(virtualenv):
Check pip can upgrade setuptools from source.
"""
dist_dir = virtualenv.workspace
- if sys.version_info < (2, 7):
- # Python 2.6 support was dropped in wheel 0.30.0.
- virtualenv.run('pip install -U "wheel<0.30.0"')
# Generate source distribution / wheel.
virtualenv.run(' && '.join((
'cd {source}',
@@ -137,3 +134,14 @@ def test_test_command_install_requirements(bare_virtualenv, tmpdir):
'python setup.py test -s test',
)).format(tmpdir=tmpdir))
assert tmpdir.join('success').check()
+
+
+def test_no_missing_dependencies(bare_virtualenv):
+ """
+ Quick and dirty test to ensure all external dependencies are vendored.
+ """
+ for command in ('upload',): # sorted(distutils.command.__all__):
+ bare_virtualenv.run(' && '.join((
+ 'cd {source}',
+ 'python setup.py {command} -h',
+ )).format(command=command, source=SOURCE_DIR))
diff --git a/setuptools/tests/test_wheel.py b/setuptools/tests/test_wheel.py
index 6db5fa11..e85a4a7e 100644
--- a/setuptools/tests/test_wheel.py
+++ b/setuptools/tests/test_wheel.py
@@ -63,6 +63,7 @@ WHEEL_INFO_TESTS = (
}),
)
+
@pytest.mark.parametrize(
('filename', 'info'), WHEEL_INFO_TESTS,
ids=[t[0] for t in WHEEL_INFO_TESTS]
@@ -487,6 +488,7 @@ WHEEL_INSTALL_TESTS = (
)
+
@pytest.mark.parametrize(
'params', WHEEL_INSTALL_TESTS,
ids=list(params['id'] for params in WHEEL_INSTALL_TESTS),
diff --git a/setuptools/tests/test_windows_wrappers.py b/setuptools/tests/test_windows_wrappers.py
index d2871c0f..2553394a 100644
--- a/setuptools/tests/test_windows_wrappers.py
+++ b/setuptools/tests/test_windows_wrappers.py
@@ -97,7 +97,8 @@ class TestCLI(WrapperTester):
'arg 4\\',
'arg5 a\\\\b',
]
- proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
+ proc = subprocess.Popen(
+ cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
stdout, stderr = proc.communicate('hello\nworld\n'.encode('ascii'))
actual = stdout.decode('ascii').replace('\r\n', '\n')
expected = textwrap.dedent(r"""
@@ -134,7 +135,11 @@ class TestCLI(WrapperTester):
with (tmpdir / 'foo-script.py').open('w') as f:
f.write(self.prep_script(tmpl))
cmd = [str(tmpdir / 'foo.exe')]
- proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT)
+ proc = subprocess.Popen(
+ cmd,
+ stdout=subprocess.PIPE,
+ stdin=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
stdout, stderr = proc.communicate()
actual = stdout.decode('ascii').replace('\r\n', '\n')
expected = textwrap.dedent(r"""
@@ -172,7 +177,9 @@ class TestGUI(WrapperTester):
str(tmpdir / 'test_output.txt'),
'Test Argument',
]
- proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT)
+ proc = subprocess.Popen(
+ cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
stdout, stderr = proc.communicate()
assert not stdout
assert not stderr