From e0e02ba96d8ee3b7be76adeec1ec9b9c3c004516 Mon Sep 17 00:00:00 2001 From: Erik Bray Date: Thu, 31 Dec 2015 13:36:36 -0500 Subject: Adds the regression test for distribute issue 323 that I attached to #207. This is to ensure that any fix to #207 does not introduce another regression. --- setuptools/tests/contexts.py | 13 +++ setuptools/tests/test_easy_install.py | 189 ++++++++++++++++++++++++++++------ 2 files changed, 173 insertions(+), 29 deletions(-) (limited to 'setuptools/tests') diff --git a/setuptools/tests/contexts.py b/setuptools/tests/contexts.py index 8c9a2d3e..ae28c7c3 100644 --- a/setuptools/tests/contexts.py +++ b/setuptools/tests/contexts.py @@ -6,6 +6,7 @@ import contextlib import site from setuptools.extern import six +import pkg_resources @contextlib.contextmanager @@ -77,6 +78,18 @@ def save_user_site_setting(): site.ENABLE_USER_SITE = saved +@contextlib.contextmanager +def save_pkg_resources_state(): + pr_state = pkg_resources.__getstate__() + # also save sys.path + sys_path = sys.path[:] + try: + yield pr_state, sys_path + finally: + sys.path[:] = sys_path + pkg_resources.__setstate__(pr_state) + + @contextlib.contextmanager def suppress_exceptions(*excs): try: diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 94e317b3..4f9e52d1 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -18,6 +18,7 @@ import io from setuptools.extern import six from setuptools.extern.six.moves import urllib +import time import pytest try: @@ -310,32 +311,32 @@ class TestSetupRequires: """ with contexts.tempdir() as dir: dist_path = os.path.join(dir, 'setuptools-test-fetcher-1.0.tar.gz') - script = DALS(""" - import setuptools - setuptools.setup( - name="setuptools-test-fetcher", - version="1.0", - setup_requires = ['does-not-exist'], - ) - """) - make_trivial_sdist(dist_path, script) + make_sdist(dist_path, [ + ('setup.py', DALS(""" + import setuptools + setuptools.setup( + name="setuptools-test-fetcher", + version="1.0", + setup_requires = ['does-not-exist'], + ) + """))]) yield dist_path def test_setup_requires_overrides_version_conflict(self): """ - Regression test for issue #323. + Regression test for distribution issue 323: + https://bitbucket.org/tarek/distribute/issues/323 Ensures that a distribution's setup_requires requirements can still be installed and used locally even if a conflicting version of that requirement is already on the path. """ - pr_state = pkg_resources.__getstate__() fake_dist = PRDistribution('does-not-matter', project_name='foobar', version='0.0') working_set.add(fake_dist) - try: + with contexts.save_pkg_resources_state(): with contexts.tempdir() as temp_dir: test_pkg = create_setup_requires_package(temp_dir) test_setup_py = os.path.join(test_pkg, 'setup.py') @@ -347,19 +348,154 @@ class TestSetupRequires: lines = stdout.readlines() assert len(lines) > 0 assert lines[-1].strip(), 'test_pkg' - finally: - pkg_resources.__setstate__(pr_state) + def test_setup_requires_override_nspkg(self): + """ + Like ``test_setup_requires_overrides_version_conflict`` but where the + ``setup_requires`` package is part of a namespace package that has + *already* been imported. + """ + + with contexts.save_pkg_resources_state(): + with contexts.tempdir() as temp_dir: + foobar_1_archive = os.path.join(temp_dir, 'foo.bar-0.1.tar.gz') + make_nspkg_sdist(foobar_1_archive, 'foo.bar', '0.1') + # Now actually go ahead an extract to the temp dir and add the + # extracted path to sys.path so foo.bar v0.1 is importable + foobar_1_dir = os.path.join(temp_dir, 'foo.bar-0.1') + os.mkdir(foobar_1_dir) + with tarfile.open(foobar_1_archive) as tf: + tf.extractall(foobar_1_dir) + sys.path.insert(1, foobar_1_dir) + + dist = PRDistribution(foobar_1_dir, project_name='foo.bar', + version='0.1') + working_set.add(dist) + + template = DALS("""\ + import foo # Even with foo imported first the + # setup_requires package should override + import setuptools + setuptools.setup(**%r) + + if not (hasattr(foo, '__path__') and + len(foo.__path__) == 2): + print('FAIL') + + if 'foo.bar-0.2' not in foo.__path__[0]: + print('FAIL') + """) + + test_pkg = create_setup_requires_package( + temp_dir, 'foo.bar', '0.2', make_nspkg_sdist, template) + + test_setup_py = os.path.join(test_pkg, 'setup.py') -def create_setup_requires_package(path): + with contexts.quiet() as (stdout, stderr): + try: + # Don't even need to install the package, just + # running the setup.py at all is sufficient + run_setup(test_setup_py, ['--name']) + except VersionConflict: + self.fail('Installing setup.py requirements ' + 'caused a VersionConflict') + + assert 'FAIL' not in stdout.getvalue() + lines = stdout.readlines() + assert len(lines) > 0 + assert lines[-1].strip() == 'test_pkg' + + +def make_trivial_sdist(dist_path, distname, version): + """ + Create a simple sdist tarball at dist_path, containing just a simple + setup.py. + """ + + make_sdist(dist_path, [ + ('setup.py', + DALS("""\ + import setuptools + setuptools.setup( + name=%r, + version=%r + ) + """ % (distname, version)))]) + + +def make_nspkg_sdist(dist_path, distname, version): + """ + Make an sdist tarball with distname and version which also contains one + package with the same name as distname. The top-level package is + designated a namespace package). + """ + + parts = distname.split('.') + nspackage = parts[0] + + packages = ['.'.join(parts[:idx]) for idx in range(1, len(parts) + 1)] + + setup_py = DALS("""\ + import setuptools + setuptools.setup( + name=%r, + version=%r, + packages=%r, + namespace_packages=[%r] + ) + """ % (distname, version, packages, nspackage)) + + init = "__import__('pkg_resources').declare_namespace(__name__)" + + files = [('setup.py', setup_py), + (os.path.join(nspackage, '__init__.py'), init)] + for package in packages[1:]: + filename = os.path.join(*(package.split('.') + ['__init__.py'])) + files.append((filename, '')) + + make_sdist(dist_path, files) + + +def make_sdist(dist_path, files): + """ + Create a simple sdist tarball at dist_path, containing the files + listed in ``files`` as ``(filename, content)`` tuples. + """ + + dist = tarfile.open(dist_path, 'w:gz') + + try: + # Python 3 (StringIO gets converted to io module) + MemFile = BytesIO + except AttributeError: + MemFile = StringIO + + try: + for filename, content in files: + file_bytes = MemFile(content.encode('utf-8')) + file_info = tarfile.TarInfo(name=filename) + file_info.size = len(file_bytes.getvalue()) + file_info.mtime = int(time.time()) + dist.addfile(file_info, fileobj=file_bytes) + finally: + dist.close() + + +def create_setup_requires_package(path, distname='foobar', version='0.1', + make_package=make_trivial_sdist, + setup_py_template=None): """Creates a source tree under path for a trivial test package that has a single requirement in setup_requires--a tarball for that requirement is also created and added to the dependency_links argument. + + ``distname`` and ``version`` refer to the name/version of the package that + the test package requires via ``setup_requires``. The name of the test + package itself is just 'test_pkg'. """ test_setup_attrs = { 'name': 'test_pkg', 'version': '0.0', - 'setup_requires': ['foobar==0.1'], + 'setup_requires': ['%s==%s' % (distname, version)], 'dependency_links': [os.path.abspath(path)] } @@ -367,22 +503,17 @@ def create_setup_requires_package(path): test_setup_py = os.path.join(test_pkg, 'setup.py') os.mkdir(test_pkg) - with open(test_setup_py, 'w') as f: - f.write(DALS(""" + if setup_py_template is None: + setup_py_template = DALS("""\ import setuptools setuptools.setup(**%r) - """ % test_setup_attrs)) + """) - foobar_path = os.path.join(path, 'foobar-0.1.tar.gz') - make_trivial_sdist( - foobar_path, - DALS(""" - import setuptools - setuptools.setup( - name='foobar', - version='0.1' - ) - """)) + with open(test_setup_py, 'w') as f: + f.write(setup_py_template % test_setup_attrs) + + foobar_path = os.path.join(path, '%s-%s.tar.gz' % (distname, version)) + make_package(foobar_path, distname, version) return test_pkg -- cgit v1.2.3 From 2b3cf9b12b23ac6beca6808c4c7620aa77f168e3 Mon Sep 17 00:00:00 2001 From: Darjus Loktevic Date: Mon, 11 Jan 2016 23:23:36 +1100 Subject: Remove JythonCommandSpec as it's not required on Jython 2.7 and setuptools no longer supports anything 2.5, but had to test for 'Jython on Windows' in two other places --- setuptools/tests/test_easy_install.py | 45 ----------------------------------- 1 file changed, 45 deletions(-) (limited to 'setuptools/tests') diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 94e317b3..93f94b85 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -427,51 +427,6 @@ class TestScriptHeader: expected = '#!"%s"\n' % self.exe_with_spaces assert actual == expected - @pytest.mark.xfail( - six.PY3 and is_ascii, - reason="Test fails in this locale on Python 3" - ) - @mock.patch.dict(sys.modules, java=mock.Mock(lang=mock.Mock(System= - mock.Mock(getProperty=mock.Mock(return_value=""))))) - @mock.patch('sys.platform', 'java1.5.0_13') - def test_get_script_header_jython_workaround(self, tmpdir): - # Create a mock sys.executable that uses a shebang line - header = DALS(""" - #!/usr/bin/python - # -*- coding: utf-8 -*- - """) - exe = tmpdir / 'exe.py' - with exe.open('w') as f: - f.write(header) - - exe = ei.nt_quote_arg(os.path.normpath(str(exe))) - - # Make sure Windows paths are quoted properly before they're sent - # through shlex.split by get_script_header - executable = '"%s"' % exe if os.path.splitdrive(exe)[0] else exe - - header = ei.ScriptWriter.get_script_header('#!/usr/local/bin/python', - executable=executable) - assert header == '#!/usr/bin/env %s\n' % exe - - expect_out = 'stdout' if sys.version_info < (2,7) else 'stderr' - - with contexts.quiet() as (stdout, stderr): - # When options are included, generate a broken shebang line - # with a warning emitted - candidate = ei.ScriptWriter.get_script_header('#!/usr/bin/python -x', - executable=executable) - assert candidate == '#!%s -x\n' % exe - output = locals()[expect_out] - assert 'Unable to adapt shebang line' in output.getvalue() - - with contexts.quiet() as (stdout, stderr): - candidate = ei.ScriptWriter.get_script_header('#!/usr/bin/python', - executable=self.non_ascii_exe) - assert candidate == '#!%s -x\n' % self.non_ascii_exe - output = locals()[expect_out] - assert 'Unable to adapt shebang line' in output.getvalue() - class TestCommandSpec: def test_custom_launch_command(self): -- cgit v1.2.3 From 8af3b6ef5b4173a0d0d6735147c98c882ae98344 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 16 Jan 2016 06:54:00 -0500 Subject: Always use Python 3 version of map --- setuptools/tests/test_dist_info.py | 2 ++ setuptools/tests/test_egg_info.py | 2 ++ setuptools/tests/test_sdist.py | 1 + 3 files changed, 5 insertions(+) (limited to 'setuptools/tests') diff --git a/setuptools/tests/test_dist_info.py b/setuptools/tests/test_dist_info.py index 6d0ab587..abd0a763 100644 --- a/setuptools/tests/test_dist_info.py +++ b/setuptools/tests/test_dist_info.py @@ -4,6 +4,8 @@ import os import shutil import tempfile +from setuptools.extern.six.moves import map + import pytest import pkg_resources diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index 333d11d6..7d51585b 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -1,6 +1,8 @@ import os import stat +from setuptools.extern.six.moves import map + import pytest from . import environment diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py index 753b507d..d2a1f1bb 100644 --- a/setuptools/tests/test_sdist.py +++ b/setuptools/tests/test_sdist.py @@ -10,6 +10,7 @@ import contextlib import io from setuptools.extern import six +from setuptools.extern.six.moves import map import pytest -- cgit v1.2.3 From efb37fc9c2e20f79f742e976e1bcd7fa2a27c5f0 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 16 Jan 2016 17:23:18 -0500 Subject: Just use BytesIO --- setuptools/tests/test_easy_install.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'setuptools/tests') diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 4f9e52d1..77cf8da1 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -464,15 +464,9 @@ def make_sdist(dist_path, files): dist = tarfile.open(dist_path, 'w:gz') - try: - # Python 3 (StringIO gets converted to io module) - MemFile = BytesIO - except AttributeError: - MemFile = StringIO - try: for filename, content in files: - file_bytes = MemFile(content.encode('utf-8')) + file_bytes = io.BytesIO(content.encode('utf-8')) file_info = tarfile.TarInfo(name=filename) file_info.size = len(file_bytes.getvalue()) file_info.mtime = int(time.time()) -- cgit v1.2.3 From d716b3c03b111512133126a5f42c7553bfb43174 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 16 Jan 2016 17:32:19 -0500 Subject: Re-use tarfile_open for Python 2.6 compatibilty. --- setuptools/tests/test_easy_install.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'setuptools/tests') diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 77cf8da1..895ce7aa 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -364,7 +364,7 @@ class TestSetupRequires: # extracted path to sys.path so foo.bar v0.1 is importable foobar_1_dir = os.path.join(temp_dir, 'foo.bar-0.1') os.mkdir(foobar_1_dir) - with tarfile.open(foobar_1_archive) as tf: + with tarfile_open(foobar_1_archive) as tf: tf.extractall(foobar_1_dir) sys.path.insert(1, foobar_1_dir) @@ -462,17 +462,13 @@ def make_sdist(dist_path, files): listed in ``files`` as ``(filename, content)`` tuples. """ - dist = tarfile.open(dist_path, 'w:gz') - - try: + with tarfile_open(dist_path, 'w:gz') as dist: for filename, content in files: file_bytes = io.BytesIO(content.encode('utf-8')) file_info = tarfile.TarInfo(name=filename) file_info.size = len(file_bytes.getvalue()) file_info.mtime = int(time.time()) dist.addfile(file_info, fileobj=file_bytes) - finally: - dist.close() def create_setup_requires_package(path, distname='foobar', version='0.1', -- cgit v1.2.3 From 670a9c895e6180e72a069f5208f0ed2ae38b9728 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 16 Jan 2016 17:38:00 -0500 Subject: Get VersionConflict from pkg_resources. --- setuptools/tests/test_easy_install.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'setuptools/tests') diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 895ce7aa..99ac7317 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -396,7 +396,7 @@ class TestSetupRequires: # Don't even need to install the package, just # running the setup.py at all is sufficient run_setup(test_setup_py, ['--name']) - except VersionConflict: + except pkg_resources.VersionConflict: self.fail('Installing setup.py requirements ' 'caused a VersionConflict') -- cgit v1.2.3 From 3d018c03405ecb21dfb717311f176c6586df343a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 23 Jan 2016 19:02:08 -0500 Subject: Add test capturing failure. Ref #486. --- setuptools/tests/test_unicode_utils.py | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 setuptools/tests/test_unicode_utils.py (limited to 'setuptools/tests') diff --git a/setuptools/tests/test_unicode_utils.py b/setuptools/tests/test_unicode_utils.py new file mode 100644 index 00000000..a24a9bd5 --- /dev/null +++ b/setuptools/tests/test_unicode_utils.py @@ -0,0 +1,10 @@ +from setuptools import unicode_utils + + +def test_filesys_decode_fs_encoding_is_None(monkeypatch): + """ + Test filesys_decode does not raise TypeError when + getfilesystemencoding returns None. + """ + monkeypatch.setattr('sys.getfilesystemencoding', lambda: None) + unicode_utils.filesys_decode(b'test') -- cgit v1.2.3