From 3f6df3dbcd1dd6130a433672d3d6a78cb774eaed Mon Sep 17 00:00:00 2001 From: DongHun Kwak Date: Mon, 14 Jan 2019 10:42:43 +0900 Subject: [PATCH] Imported Upstream version 40.0.0 --- CHANGES.rst | 15 +- README.rst | 4 +- changelog.d/1364.rst | 1 - conftest.py | 17 ++ docs/developer-guide.txt | 27 +-- docs/easy_install.txt | 2 +- docs/history.txt | 7 +- docs/releases.txt | 6 +- docs/roadmap.txt | 8 +- docs/setuptools.txt | 37 +--- pkg_resources/__init__.py | 17 +- pkg_resources/extern/__init__.py | 2 +- pkg_resources/py31compat.py | 3 +- pkg_resources/tests/test_pkg_resources.py | 16 +- pkg_resources/tests/test_resources.py | 6 +- pkg_resources/tests/test_working_set.py | 8 +- pyproject.toml | 3 + pytest.ini | 3 +- setup.cfg | 2 +- setup.py | 5 +- setuptools/__init__.py | 4 +- setuptools/command/bdist_egg.py | 2 +- setuptools/command/build_ext.py | 12 +- setuptools/command/develop.py | 4 +- setuptools/command/easy_install.py | 7 +- setuptools/command/test.py | 4 +- setuptools/config.py | 5 +- setuptools/extern/__init__.py | 2 +- setuptools/monkey.py | 2 - setuptools/package_index.py | 24 ++- setuptools/pep425tags.py | 4 +- setuptools/py31compat.py | 15 +- setuptools/py33compat.py | 3 +- setuptools/script (dev).tmpl | 3 +- setuptools/site-patch.py | 2 +- setuptools/tests/test_build_meta.py | 4 +- setuptools/tests/test_easy_install.py | 6 +- setuptools/tests/test_egg_info.py | 8 +- setuptools/tests/test_glibc.py | 71 +++++--- setuptools/tests/test_install_scripts.py | 2 +- setuptools/tests/test_manifest.py | 4 +- setuptools/tests/test_pep425tags.py | 6 +- setuptools/tests/test_wheel.py | 4 +- setuptools/wheel.py | 203 +++++++++++++--------- tests/manual_test.py | 6 +- tests/requirements.txt | 6 +- tests/test_pypi.py | 82 --------- tox.ini | 2 +- 48 files changed, 333 insertions(+), 353 deletions(-) delete mode 100644 changelog.d/1364.rst delete mode 100644 tests/test_pypi.py diff --git a/CHANGES.rst b/CHANGES.rst index d3d661c..2f96af9 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,14 @@ +v40.0.0 +------- +* #1342: Drop support for Python 3.3. +* #1366: In package_index, fixed handling of encoded entities in URLs. +* #1383: In pkg_resources VendorImporter, avoid removing packages imported from the root. +* #1379: Minor doc fixes after actually using the new release process. +* #1385: Removed section on non-package data files. +* #1403: Fix developer's guide. +* #1404: Fix PEP 518 configuration: set build requirements in ``pyproject.toml`` to ``["wheel"]``. + + v39.2.0 ------- @@ -5,6 +16,8 @@ v39.2.0 a text file. * #1360: Fixed issue with a mismatch between the name of the package and the name of the .dist-info file in wheel files +* #1364: Add `__dir__()` implementation to `pkg_resources.Distribution()` that + includes the attributes in the `_provider` instance variable. * #1365: Take the package_dir option into account when loading the version from a module attribute. * #1353: Added coverage badge to README. @@ -17,7 +30,7 @@ v39.2.0 after any ``distutils`` ``setup_keywords`` calls, allowing them to override values. * #1352: Added ``tox`` environment for documentation builds. -* #1354: Added ``towncrier`` for changelog managment. +* #1354: Added ``towncrier`` for changelog management. * #1355: Add PR template. * #1368: Fixed tests which failed without network connectivity. * #1369: Added unit tests for PEP 425 compatibility tags support. diff --git a/README.rst b/README.rst index 2c008cc..8505c55 100755 --- a/README.rst +++ b/README.rst @@ -20,7 +20,9 @@ See the `Installation Instructions User's Guide for instructions on installing, upgrading, and uninstalling Setuptools. -The project is `maintained at GitHub `_. +The project is `maintained at GitHub `_ +by the `Setuptools Developers +`_. Questions and comments should be directed to the `distutils-sig mailing list `_. diff --git a/changelog.d/1364.rst b/changelog.d/1364.rst deleted file mode 100644 index f7b4c01..0000000 --- a/changelog.d/1364.rst +++ /dev/null @@ -1 +0,0 @@ -Add `__dir__()` implementation to `pkg_resources.Distribution()` that includes the attributes in the `_provider` instance variable. \ No newline at end of file diff --git a/conftest.py b/conftest.py index 3cccfe1..0d7b274 100644 --- a/conftest.py +++ b/conftest.py @@ -1,3 +1,6 @@ +import sys + + pytest_plugins = 'setuptools.tests.fixtures' @@ -6,3 +9,17 @@ def pytest_addoption(parser): "--package_name", action="append", default=[], help="list of package_name to pass to test functions", ) + + +collect_ignore = [ + 'tests/manual_test.py', + 'setuptools/tests/mod_with_constant.py', +] + + +if sys.version_info < (3,): + collect_ignore.append('setuptools/lib2to3_ex.py') + + +if sys.version_info < (3, 6): + collect_ignore.append('pavement.py') diff --git a/docs/developer-guide.txt b/docs/developer-guide.txt index 6b04603..c011491 100644 --- a/docs/developer-guide.txt +++ b/docs/developer-guide.txt @@ -66,7 +66,7 @@ and a reference to any issue tickets that the PR is intended to solve. All PRs with code changes should include tests. All changes should include a changelog entry. -``setuptools`` uses `towncrier `_ +``setuptools`` uses `towncrier `_ for changelog managment, so when making a PR, please add a news fragment in the ``changelog.d/`` folder. Changelog files are written in Restructured Text and should be a 1 or 2 sentence description of the substantive changes in the PR. @@ -89,31 +89,6 @@ code changes. See the following for an example news fragment: $ cat changelog.d/1288.change.rst Add support for maintainer in PKG-INFO ------------ -Source Code ------------ - -Grab the code at Github:: - - $ git clone https://github.com/pypa/setuptools - -If you want to contribute changes, we recommend you fork the repository on -Github, commit the changes to your repository, and then make a pull request -on Github. If you make some changes, don't forget to: - -- add a note in CHANGES.rst - -Please commit all changes in the 'master' branch against the latest available -commit or for bug-fixes, against an earlier commit or release in which the -bug occurred. - -If you find yourself working on more than one issue at a time, Setuptools -generally prefers Git-style branches, so use Mercurial bookmarks or Git -branches or multiple forks to maintain separate efforts. - -The Continuous Integration tests that validate every release are run -from this repository. - ------- Testing ------- diff --git a/docs/easy_install.txt b/docs/easy_install.txt index 5c99234..f426b6f 100644 --- a/docs/easy_install.txt +++ b/docs/easy_install.txt @@ -35,7 +35,7 @@ Please see the `setuptools PyPI page `_ for download links and basic installation instructions for each of the supported platforms. -You will need at least Python 3.3 or 2.7. An ``easy_install`` script will be +You will need at least Python 3.4 or 2.7. An ``easy_install`` script will be installed in the normal location for Python scripts on your platform. Note that the instructions on the setuptools PyPI page assume that you are diff --git a/docs/history.txt b/docs/history.txt index 8fd1dc6..385cfa7 100644 --- a/docs/history.txt +++ b/docs/history.txt @@ -40,7 +40,6 @@ Credits re-invigorated the community on the project, encouraged renewed innovation, and addressed many defects. -* Since the merge with Distribute, Jason R. Coombs is the - maintainer of setuptools. The project is maintained in coordination with - the Python Packaging Authority (PyPA) and the larger Python community. - +* Jason R. Coombs performed the merge with Distribute, maintaining the + project for several years in coordination with the Python Packaging + Authority (PyPA). diff --git a/docs/releases.txt b/docs/releases.txt index 234f69e..98ba39e 100644 --- a/docs/releases.txt +++ b/docs/releases.txt @@ -19,9 +19,13 @@ To update the changelog: ``git add`` for any modified files. 3. Run ``towncrier --version {new.version.number}`` to stage the changelog updates in git. +4. Verify that there are no remaining ``changelog.d/*.rst`` files. If a + file was named incorrectly, it may be ignored by towncrier. +5. Review the updated ``CHANGES.rst`` file. If any changes are needed, + make the edits and stage them via ``git add CHANGES.rst``. Once the changelog edits are staged and ready to commit, cut a release by -installing and running ``bump2version {part}`` where ``part`` +installing and running ``bump2version --allow-dirty {part}`` where ``part`` is major, minor, or patch based on the scope of the changes in the release. Then, push the commits to the master branch:: diff --git a/docs/roadmap.txt b/docs/roadmap.txt index 8f175b9..9bde493 100644 --- a/docs/roadmap.txt +++ b/docs/roadmap.txt @@ -2,5 +2,9 @@ Roadmap ======= -Setuptools is primarily in maintenance mode. The project attempts to address -user issues, concerns, and feature requests in a timely fashion. +Setuptools has the following large-scale goals on the roadmap: + +- Harmonize declarative config with pyproject.toml syntax. +- Deprecate and remove setup_requires and easy_install in + favor of PEP 518 build requirements and pip install. +- Adopt the Distutils package and stop monkeypatching stdlib. diff --git a/docs/setuptools.txt b/docs/setuptools.txt index f7b9351..c82dc51 100644 --- a/docs/setuptools.txt +++ b/docs/setuptools.txt @@ -970,35 +970,14 @@ a quick example of converting code that uses ``__file__`` to use Non-Package Data Files ---------------------- -The ``distutils`` normally install general "data files" to a platform-specific -location (e.g. ``/usr/share``). This feature intended to be used for things -like documentation, example configuration files, and the like. ``setuptools`` -does not install these data files in a separate location, however. They are -bundled inside the egg file or directory, alongside the Python modules and -packages. The data files can also be accessed using the :ref:`ResourceManager -API`, by specifying a ``Requirement`` instead of a package name:: - - from pkg_resources import Requirement, resource_filename - filename = resource_filename(Requirement.parse("MyProject"),"sample.conf") - -The above code will obtain the filename of the "sample.conf" file in the data -root of the "MyProject" distribution. - -Note, by the way, that this encapsulation of data files means that you can't -actually install data files to some arbitrary location on a user's machine; -this is a feature, not a bug. You can always include a script in your -distribution that extracts and copies your the documentation or data files to -a user-specified location, at their discretion. If you put related data files -in a single directory, you can use ``resource_filename()`` with the directory -name to get a filesystem directory that then can be copied with the ``shutil`` -module. (Even if your package is installed as a zipfile, calling -``resource_filename()`` on a directory will return an actual filesystem -directory, whose contents will be that entire subtree of your distribution.) - -(Of course, if you're writing a new package, you can just as easily place your -data files or directories inside one of your packages, rather than using the -distutils' approach. However, if you're updating an existing application, it -may be simpler not to change the way it currently specifies these data files.) +Historically, ``setuptools`` by way of ``easy_install`` would encapsulate data +files from the distribution into the egg (see `the old docs +`_). As eggs are deprecated and pip-based installs +fall back to the platform-specific location for installing data files, there is +no supported facility to reliably retrieve these resources. + +Instead, the PyPA recommends that any data files you wish to be accessible at +run time be included in the package. Automatic Resource Extraction diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 4e4409b..6701540 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -78,8 +78,11 @@ __import__('pkg_resources.extern.packaging.requirements') __import__('pkg_resources.extern.packaging.markers') -if (3, 0) < sys.version_info < (3, 3): - raise RuntimeError("Python 3.3 or later is required") +__metaclass__ = type + + +if (3, 0) < sys.version_info < (3, 4): + raise RuntimeError("Python 3.4 or later is required") if six.PY2: # Those builtin exceptions are only defined in Python 3 @@ -537,7 +540,7 @@ class IResourceProvider(IMetadataProvider): """List of resource names in the directory (like ``os.listdir()``)""" -class WorkingSet(object): +class WorkingSet: """A collection of active distributions on sys.path (or a similar list)""" def __init__(self, entries=None): @@ -944,7 +947,7 @@ class _ReqExtras(dict): return not req.marker or any(extra_evals) -class Environment(object): +class Environment: """Searchable snapshot of distributions on a search path""" def __init__( @@ -959,7 +962,7 @@ class Environment(object): `platform` is an optional string specifying the name of the platform that platform-specific distributions must be compatible with. If unspecified, it defaults to the current platform. `python` is an - optional string naming the desired version of Python (e.g. ``'3.3'``); + optional string naming the desired version of Python (e.g. ``'3.6'``); it defaults to the current version. You may explicitly set `platform` (and/or `python`) to ``None`` if you @@ -2279,7 +2282,7 @@ EGG_NAME = re.compile( ).match -class EntryPoint(object): +class EntryPoint: """Object representing an advertised importable object""" def __init__(self, name, module_name, attrs=(), extras=(), dist=None): @@ -2433,7 +2436,7 @@ def _version_from_file(lines): return safe_version(value.strip()) or None -class Distribution(object): +class Distribution: """Wrap an actual or potential sys.path entry w/metadata""" PKG_INFO = 'PKG-INFO' diff --git a/pkg_resources/extern/__init__.py b/pkg_resources/extern/__init__.py index b4156fe..c1eb9e9 100644 --- a/pkg_resources/extern/__init__.py +++ b/pkg_resources/extern/__init__.py @@ -48,7 +48,7 @@ class VendorImporter: # on later Python versions to cause relative imports # in the vendor package to resolve the same modules # as those going through this importer. - if sys.version_info > (3, 3): + if prefix and sys.version_info > (3, 3): del sys.modules[extant] return mod except ImportError: diff --git a/pkg_resources/py31compat.py b/pkg_resources/py31compat.py index 331a51b..fd4b6fd 100644 --- a/pkg_resources/py31compat.py +++ b/pkg_resources/py31compat.py @@ -15,8 +15,7 @@ def _makedirs_31(path, exist_ok=False): # and exists_ok considerations are disentangled. # See https://github.com/pypa/setuptools/pull/1083#issuecomment-315168663 needs_makedirs = ( - sys.version_info < (3, 2, 5) or - (3, 3) <= sys.version_info < (3, 3, 6) or + sys.version_info.major == 2 or (3, 4) <= sys.version_info < (3, 4, 1) ) makedirs = _makedirs_31 if needs_makedirs else os.makedirs diff --git a/pkg_resources/tests/test_pkg_resources.py b/pkg_resources/tests/test_pkg_resources.py index 7442b79..4e2cac9 100644 --- a/pkg_resources/tests/test_pkg_resources.py +++ b/pkg_resources/tests/test_pkg_resources.py @@ -13,15 +13,13 @@ import distutils.dist import distutils.command.install_egg_info from pkg_resources.extern.six.moves import map +from pkg_resources.extern.six import text_type, string_types import pytest import pkg_resources -try: - unicode -except NameError: - unicode = str +__metaclass__ = type def timestamp(dt): @@ -35,7 +33,7 @@ def timestamp(dt): return time.mktime(dt.timetuple()) -class EggRemover(unicode): +class EggRemover(text_type): def __call__(self): if self in sys.path: sys.path.remove(self) @@ -43,7 +41,7 @@ class EggRemover(unicode): os.remove(self) -class TestZipProvider(object): +class TestZipProvider: finalizers = [] ref_time = datetime.datetime(2013, 5, 12, 13, 25, 0) @@ -132,13 +130,13 @@ class TestZipProvider(object): manager.cleanup_resources() -class TestResourceManager(object): +class TestResourceManager: def test_get_cache_path(self): mgr = pkg_resources.ResourceManager() path = mgr.get_cache_path('foo') type_ = str(type(path)) message = "Unexpected type from get_cache_path: " + type_ - assert isinstance(path, (unicode, str)), message + assert isinstance(path, string_types), message class TestIndependence: @@ -163,7 +161,7 @@ class TestIndependence: subprocess.check_call(cmd) -class TestDeepVersionLookupDistutils(object): +class TestDeepVersionLookupDistutils: @pytest.fixture def env(self, tmpdir): """ diff --git a/pkg_resources/tests/test_resources.py b/pkg_resources/tests/test_resources.py index 04d02c1..171ba2f 100644 --- a/pkg_resources/tests/test_resources.py +++ b/pkg_resources/tests/test_resources.py @@ -668,7 +668,7 @@ class TestParsing: assert ( Requirement.parse("name==1.1;python_version=='2.7'") != - Requirement.parse("name==1.1;python_version=='3.3'") + Requirement.parse("name==1.1;python_version=='3.6'") ) assert ( Requirement.parse("name==1.0;python_version=='2.7'") @@ -676,9 +676,9 @@ class TestParsing: Requirement.parse("name==1.2;python_version=='2.7'") ) assert ( - Requirement.parse("name[foo]==1.0;python_version=='3.3'") + Requirement.parse("name[foo]==1.0;python_version=='3.6'") != - Requirement.parse("name[foo,bar]==1.0;python_version=='3.3'") + Requirement.parse("name[foo,bar]==1.0;python_version=='3.6'") ) def test_local_version(self): diff --git a/pkg_resources/tests/test_working_set.py b/pkg_resources/tests/test_working_set.py index 42ddcc8..b3ca4ea 100644 --- a/pkg_resources/tests/test_working_set.py +++ b/pkg_resources/tests/test_working_set.py @@ -9,6 +9,8 @@ import pkg_resources from .test_resources import Metadata +__metaclass__ = type + def strip_comments(s): return '\n'.join( @@ -37,7 +39,7 @@ def parse_distributions(s): requires=['foo>=3.0', 'baz; extra=="feature"'] ''' s = s.strip() - for spec in re.split('\n(?=[^\s])', s): + for spec in re.split(r'\n(?=[^\s])', s): if not spec: continue fields = spec.split('\n', 1) @@ -54,7 +56,7 @@ def parse_distributions(s): yield dist -class FakeInstaller(object): +class FakeInstaller: def __init__(self, installable_dists): self._installable_dists = installable_dists @@ -87,7 +89,7 @@ def parametrize_test_working_set_resolve(*test_list): ): idlist.append(id_) expected = strip_comments(expected.strip()) - if re.match('\w+$', expected): + if re.match(r'\w+$', expected): expected = getattr(pkg_resources, expected) assert issubclass(expected, Exception) else: diff --git a/pyproject.toml b/pyproject.toml index cffd0e9..07c23bb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,6 @@ +[build-system] +requires = ["wheel"] + [tool.towncrier] package = "setuptools" package_dir = "setuptools" diff --git a/pytest.ini b/pytest.ini index 16fdc5a..1c5b6b0 100755 --- a/pytest.ini +++ b/pytest.ini @@ -1,6 +1,7 @@ [pytest] -addopts=--doctest-modules --ignore release.py --ignore setuptools/lib2to3_ex.py --ignore tests/manual_test.py --ignore tests/test_pypi.py --ignore tests/shlib_test --doctest-glob=pkg_resources/api_tests.txt --ignore scripts/upload-old-releases-as-zip.py --ignore pavement.py --ignore setuptools/tests/mod_with_constant.py -rsxX +addopts=--doctest-modules --doctest-glob=pkg_resources/api_tests.txt -rsxX norecursedirs=dist build *.egg setuptools/extern pkg_resources/extern .* flake8-ignore = setuptools/site-patch.py F821 setuptools/py*compat.py F811 +doctest_optionflags=ELLIPSIS ALLOW_UNICODE diff --git a/setup.cfg b/setup.cfg index e23ee6f..2caeca9 100755 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 39.2.0 +current_version = 40.0.0 commit = True tag = True diff --git a/setup.py b/setup.py index b122df8..27a0e30 100755 --- a/setup.py +++ b/setup.py @@ -89,7 +89,7 @@ def pypi_link(pkg_filename): setup_params = dict( name="setuptools", - version="39.2.0", + version="40.0.0", description=( "Easily download, build, install, upgrade, and uninstall " "Python packages" @@ -161,7 +161,6 @@ setup_params = dict( Programming Language :: Python :: 2 Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 - Programming Language :: Python :: 3.3 Programming Language :: Python :: 3.4 Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 @@ -170,7 +169,7 @@ setup_params = dict( Topic :: System :: Systems Administration Topic :: Utilities """).strip().splitlines(), - python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*', + python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*', extras_require={ "ssl:sys_platform=='win32'": "wincertstore==0.2", "certs": "certifi==2016.9.26", diff --git a/setuptools/__init__.py b/setuptools/__init__.py index 7da47fb..ce55ec3 100644 --- a/setuptools/__init__.py +++ b/setuptools/__init__.py @@ -15,6 +15,8 @@ from setuptools.dist import Distribution, Feature from setuptools.depends import Require from . import monkey +__metaclass__ = type + __all__ = [ 'setup', 'Distribution', 'Feature', 'Command', 'Extension', 'Require', 'find_packages', @@ -31,7 +33,7 @@ run_2to3_on_doctests = True lib2to3_fixer_packages = ['lib2to3.fixes'] -class PackageFinder(object): +class PackageFinder: """ Generate a list of all Python packages found within a directory """ diff --git a/setuptools/command/bdist_egg.py b/setuptools/command/bdist_egg.py index 423b818..1453072 100644 --- a/setuptools/command/bdist_egg.py +++ b/setuptools/command/bdist_egg.py @@ -411,7 +411,7 @@ def scan_module(egg_dir, base, name, stubs): return True # Extension module pkg = base[len(egg_dir) + 1:].replace(os.sep, '.') module = pkg + (pkg and '.' or '') + os.path.splitext(name)[0] - if sys.version_info < (3, 3): + if sys.version_info.major == 2: skip = 8 # skip magic & date elif sys.version_info < (3, 7): skip = 12 # skip magic & date & file size diff --git a/setuptools/command/build_ext.py b/setuptools/command/build_ext.py index ea97b37..60a8a32 100644 --- a/setuptools/command/build_ext.py +++ b/setuptools/command/build_ext.py @@ -112,7 +112,7 @@ class build_ext(_build_ext): and get_abi3_suffix() ) if use_abi3: - so_ext = _get_config_var_837('EXT_SUFFIX') + so_ext = get_config_var('EXT_SUFFIX') filename = filename[:-len(so_ext)] filename = filename + get_abi3_suffix() if isinstance(ext, Library): @@ -319,13 +319,3 @@ else: self.create_static_lib( objects, basename, output_dir, debug, target_lang ) - - -def _get_config_var_837(name): - """ - In https://github.com/pypa/setuptools/pull/837, we discovered - Python 3.3.0 exposes the extension suffix under the name 'SO'. - """ - if sys.version_info < (3, 3, 1): - name = 'SO' - return get_config_var(name) diff --git a/setuptools/command/develop.py b/setuptools/command/develop.py index 959c932..fdc9fc4 100755 --- a/setuptools/command/develop.py +++ b/setuptools/command/develop.py @@ -12,6 +12,8 @@ from setuptools.command.easy_install import easy_install from setuptools import namespaces import setuptools +__metaclass__ = type + class develop(namespaces.DevelopInstaller, easy_install): """Set up package for development""" @@ -192,7 +194,7 @@ class develop(namespaces.DevelopInstaller, easy_install): return easy_install.install_wrapper_scripts(self, dist) -class VersionlessRequirement(object): +class VersionlessRequirement: """ Adapt a pkg_resources.Distribution to simply return the project name as the 'requirement' so that scripts will work across diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 85ee40f..05508ce 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -40,12 +40,13 @@ import subprocess import shlex import io +from sysconfig import get_config_vars, get_path + from setuptools.extern import six from setuptools.extern.six.moves import configparser, map from setuptools import Command from setuptools.sandbox import run_setup -from setuptools.py31compat import get_path, get_config_vars from setuptools.py27compat import rmtree_safe from setuptools.command import setopt from setuptools.archive_util import unpack_archive @@ -62,6 +63,8 @@ from pkg_resources import ( ) import pkg_resources.py31compat +__metaclass__ = type + # Turn on PEP440Warnings warnings.filterwarnings("default", category=pkg_resources.PEP440Warning) @@ -2049,7 +2052,7 @@ class WindowsCommandSpec(CommandSpec): split_args = dict(posix=False) -class ScriptWriter(object): +class ScriptWriter: """ Encapsulates behavior around writing entry point scripts for console and gui apps. diff --git a/setuptools/command/test.py b/setuptools/command/test.py index 51aee1f..dde0118 100644 --- a/setuptools/command/test.py +++ b/setuptools/command/test.py @@ -16,6 +16,8 @@ from pkg_resources import (resource_listdir, resource_exists, normalize_path, add_activation_listener, require, EntryPoint) from setuptools import Command +__metaclass__ = type + class ScanningLoader(TestLoader): @@ -58,7 +60,7 @@ class ScanningLoader(TestLoader): # adapted from jaraco.classes.properties:NonDataProperty -class NonDataProperty(object): +class NonDataProperty: def __init__(self, fget): self.fget = fget diff --git a/setuptools/config.py b/setuptools/config.py index d3f0b12..5f908cf 100644 --- a/setuptools/config.py +++ b/setuptools/config.py @@ -11,6 +11,9 @@ from setuptools.extern.packaging.version import LegacyVersion, parse from setuptools.extern.six import string_types +__metaclass__ = type + + def read_configuration( filepath, find_others=False, ignore_option_errors=False): """Read given configuration file and returns options from it as a dict. @@ -113,7 +116,7 @@ def parse_configuration( return meta, options -class ConfigHandler(object): +class ConfigHandler: """Handles metadata supplied in configuration files.""" section_prefix = None diff --git a/setuptools/extern/__init__.py b/setuptools/extern/__init__.py index da3d668..52785a0 100644 --- a/setuptools/extern/__init__.py +++ b/setuptools/extern/__init__.py @@ -48,7 +48,7 @@ class VendorImporter: # on later Python versions to cause relative imports # in the vendor package to resolve the same modules # as those going through this importer. - if sys.version_info > (3, 3): + if sys.version_info.major >= 3: del sys.modules[extant] return mod except ImportError: diff --git a/setuptools/monkey.py b/setuptools/monkey.py index 08ed50d..05a738b 100644 --- a/setuptools/monkey.py +++ b/setuptools/monkey.py @@ -75,8 +75,6 @@ def patch_all(): needs_warehouse = ( sys.version_info < (2, 7, 13) or - (3, 0) < sys.version_info < (3, 3, 7) - or (3, 4) < sys.version_info < (3, 4, 6) or (3, 5) < sys.version_info <= (3, 5, 3) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index b6407be..cda54b7 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -26,12 +26,13 @@ from setuptools.py27compat import get_all_headers from setuptools.py33compat import unescape from setuptools.wheel import Wheel +__metaclass__ = type + EGG_FRAGMENT = re.compile(r'^egg=([-A-Za-z0-9_.+!]+)$') -HREF = re.compile("""href\\s*=\\s*['"]?([^'"> ]+)""", re.I) -# this is here to fix emacs' cruddy broken syntax highlighting +HREF = re.compile(r"""href\s*=\s*['"]?([^'"> ]+)""", re.I) PYPI_MD5 = re.compile( - '([^<]+)\n\\s+\\(md5\\)' + r'([^<]+)\n\s+\(md5\)' ) URL_SCHEME = re.compile('([-+.a-z0-9]{2,}):', re.I).match EXTENSIONS = ".tar.gz .tar.bz2 .tar .zip .tgz".split() @@ -235,7 +236,7 @@ def find_external_links(url, page): yield urllib.parse.urljoin(url, htmldecode(match.group(1))) -class ContentChecker(object): +class ContentChecker: """ A null content checker that defines the interface for checking content """ @@ -933,12 +934,19 @@ entity_sub = re.compile(r'&(#(\d+|x[\da-fA-F]+)|[\w.:-]+);?').sub def decode_entity(match): - what = match.group(1) + what = match.group(0) return unescape(what) def htmldecode(text): - """Decode HTML entities in the given text.""" + """ + Decode HTML entities in the given text. + + >>> htmldecode( + ... 'https://../package_name-0.1.2.tar.gz' + ... '?tokena=A&tokenb=B">package_name-0.1.2.tar.gz') + 'https://../package_name-0.1.2.tar.gz?tokena=A&tokenb=B">package_name-0.1.2.tar.gz' + """ return entity_sub(decode_entity, text) @@ -980,7 +988,7 @@ def _encode_auth(auth): return encoded.replace('\n', '') -class Credential(object): +class Credential: """ A username/password pair. Use like a namedtuple. """ diff --git a/setuptools/pep425tags.py b/setuptools/pep425tags.py index 3bdd328..a86a0d1 100644 --- a/setuptools/pep425tags.py +++ b/setuptools/pep425tags.py @@ -97,8 +97,8 @@ def get_abi_tag(): lambda: sys.maxunicode == 0x10ffff, expected=4, warn=(impl == 'cp' and - sys.version_info < (3, 3))) \ - and sys.version_info < (3, 3): + sys.version_info.major == 2)) \ + and sys.version_info.major == 2: u = 'u' abi = '%s%s%s%s%s' % (impl, get_impl_ver(), d, m, u) elif soabi and soabi.startswith('cpython-'): diff --git a/setuptools/py31compat.py b/setuptools/py31compat.py index 4ea9532..1a0705e 100644 --- a/setuptools/py31compat.py +++ b/setuptools/py31compat.py @@ -1,15 +1,6 @@ -__all__ = ['get_config_vars', 'get_path'] +__all__ = [] -try: - # Python 2.7 or >=3.2 - from sysconfig import get_config_vars, get_path -except ImportError: - from distutils.sysconfig import get_config_vars, get_python_lib - - def get_path(name): - if name not in ('platlib', 'purelib'): - raise ValueError("Name must be purelib or platlib") - return get_python_lib(name == 'platlib') +__metaclass__ = type try: @@ -19,7 +10,7 @@ except ImportError: import shutil import tempfile - class TemporaryDirectory(object): + class TemporaryDirectory: """ Very simple temporary directory context manager. Will try to delete afterward, but will also ignore OS and similar diff --git a/setuptools/py33compat.py b/setuptools/py33compat.py index 2a73ebb..87cf539 100644 --- a/setuptools/py33compat.py +++ b/setuptools/py33compat.py @@ -10,11 +10,12 @@ except ImportError: from setuptools.extern import six from setuptools.extern.six.moves import html_parser +__metaclass__ = type OpArg = collections.namedtuple('OpArg', 'opcode arg') -class Bytecode_compat(object): +class Bytecode_compat: def __init__(self, code): self.code = code diff --git a/setuptools/script (dev).tmpl b/setuptools/script (dev).tmpl index d58b1bb..39a24b0 100644 --- a/setuptools/script (dev).tmpl +++ b/setuptools/script (dev).tmpl @@ -2,4 +2,5 @@ __requires__ = %(spec)r __import__('pkg_resources').require(%(spec)r) __file__ = %(dev_path)r -exec(compile(open(__file__).read(), __file__, 'exec')) +with open(__file__) as f: + exec(compile(f.read(), __file__, 'exec')) diff --git a/setuptools/site-patch.py b/setuptools/site-patch.py index 0d2d2ff..40b00de 100644 --- a/setuptools/site-patch.py +++ b/setuptools/site-patch.py @@ -23,7 +23,7 @@ def __boot(): break else: try: - import imp # Avoid import loop in Python >= 3.3 + import imp # Avoid import loop in Python 3 stream, path, descr = imp.find_module('site', [item]) except ImportError: continue diff --git a/setuptools/tests/test_build_meta.py b/setuptools/tests/test_build_meta.py index 659c1a6..b39b7b8 100644 --- a/setuptools/tests/test_build_meta.py +++ b/setuptools/tests/test_build_meta.py @@ -5,12 +5,14 @@ import pytest from .files import build_files from .textwrap import DALS +__metaclass__ = type + futures = pytest.importorskip('concurrent.futures') importlib = pytest.importorskip('importlib') -class BuildBackendBase(object): +class BuildBackendBase: def __init__(self, cwd=None, env={}, backend_name='setuptools.build_meta'): self.cwd = cwd self.env = env diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 57339c8..345d283 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -36,8 +36,10 @@ import pkg_resources from . import contexts from .textwrap import DALS +__metaclass__ = type -class FakeDist(object): + +class FakeDist: def get_entry_map(self, group): if group != 'console_scripts': return {} @@ -688,7 +690,7 @@ def create_setup_requires_package(path, distname='foobar', version='0.1', ) class TestScriptHeader: non_ascii_exe = '/Users/José/bin/python' - exe_with_spaces = r'C:\Program Files\Python33\python.exe' + exe_with_spaces = r'C:\Program Files\Python36\python.exe' def test_get_script_header(self): expected = '#!%s\n' % ei.nt_quote_arg(os.path.normpath(sys.executable)) diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index 8b3b90f..1a10026 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -16,12 +16,14 @@ from .files import build_files from .textwrap import DALS from . import contexts +__metaclass__ = type + class Environment(str): pass -class TestEggInfo(object): +class TestEggInfo: setup_script = DALS(""" from setuptools import setup @@ -181,7 +183,7 @@ class TestEggInfo(object): ) invalid_marker = "<=>++" - class RequiresTestHelper(object): + class RequiresTestHelper: @staticmethod def parametrize(*test_list, **format_dict): @@ -452,7 +454,7 @@ class TestEggInfo(object): def test_doesnt_provides_extra(self, tmpdir_cwd, env): self._setup_script_with_requires( - '''install_requires=["spam ; python_version<'3.3'"]''') + '''install_requires=["spam ; python_version<'3.6'"]''') environ = os.environ.copy().update( HOME=env.paths['home'], ) diff --git a/setuptools/tests/test_glibc.py b/setuptools/tests/test_glibc.py index 9cb9796..795fdc5 100644 --- a/setuptools/tests/test_glibc.py +++ b/setuptools/tests/test_glibc.py @@ -1,37 +1,52 @@ import warnings +import pytest + from setuptools.glibc import check_glibc_version +__metaclass__ = type + + +@pytest.fixture(params=[ + "2.20", + # used by "linaro glibc", see gh-3588 + "2.20-2014.11", + # weird possibilities that I just made up + "2.20+dev", + "2.20-custom", + "2.20.1", + ]) +def two_twenty(request): + return request.param + + +@pytest.fixture(params=["asdf", "", "foo.bar"]) +def bad_string(request): + return request.param -class TestGlibc(object): - def test_manylinux1_check_glibc_version(self): + +class TestGlibc: + def test_manylinux1_check_glibc_version(self, two_twenty): """ Test that the check_glibc_version function is robust against weird glibc version strings. """ - for two_twenty in ["2.20", - # used by "linaro glibc", see gh-3588 - "2.20-2014.11", - # weird possibilities that I just made up - "2.20+dev", - "2.20-custom", - "2.20.1", - ]: - assert check_glibc_version(two_twenty, 2, 15) - assert check_glibc_version(two_twenty, 2, 20) - assert not check_glibc_version(two_twenty, 2, 21) - assert not check_glibc_version(two_twenty, 3, 15) - assert not check_glibc_version(two_twenty, 1, 15) - - # For strings that we just can't parse at all, we should warn and - # return false - for bad_string in ["asdf", "", "foo.bar"]: - with warnings.catch_warnings(record=True) as ws: - warnings.filterwarnings("always") - assert not check_glibc_version(bad_string, 2, 5) - for w in ws: - if "Expected glibc version with" in str(w.message): - break - else: - # Didn't find the warning we were expecting - assert False + assert check_glibc_version(two_twenty, 2, 15) + assert check_glibc_version(two_twenty, 2, 20) + assert not check_glibc_version(two_twenty, 2, 21) + assert not check_glibc_version(two_twenty, 3, 15) + assert not check_glibc_version(two_twenty, 1, 15) + + def test_bad_versions(self, bad_string): + """ + For unparseable strings, warn and return False + """ + with warnings.catch_warnings(record=True) as ws: + warnings.filterwarnings("always") + assert not check_glibc_version(bad_string, 2, 5) + for w in ws: + if "Expected glibc version with" in str(w.message): + break + else: + # Didn't find the warning we were expecting + assert False diff --git a/setuptools/tests/test_install_scripts.py b/setuptools/tests/test_install_scripts.py index 7393241..727ad65 100644 --- a/setuptools/tests/test_install_scripts.py +++ b/setuptools/tests/test_install_scripts.py @@ -19,7 +19,7 @@ class TestInstallScripts: ) 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' + win32_exe = 'C:\\Dummy Test Path\\Program Files\\Python 3.6\\python.exe' def _run_install_scripts(self, install_dir, executable=None): dist = Distribution(self.settings) diff --git a/setuptools/tests/test_manifest.py b/setuptools/tests/test_manifest.py index 65eec7d..c9533dd 100644 --- a/setuptools/tests/test_manifest.py +++ b/setuptools/tests/test_manifest.py @@ -18,6 +18,8 @@ from setuptools.tests.textwrap import DALS import pytest +__metaclass__ = type + py3_only = pytest.mark.xfail(six.PY2, reason="Test runs on Python 3 only") @@ -157,7 +159,7 @@ def test_translated_pattern_mismatch(pattern_mismatch): assert not translate_pattern(pattern).match(target) -class TempDirTestCase(object): +class TempDirTestCase: def setup_method(self, method): self.temp_dir = tempfile.mkdtemp() self.old_cwd = os.getcwd() diff --git a/setuptools/tests/test_pep425tags.py b/setuptools/tests/test_pep425tags.py index 0f60e0e..658784a 100644 --- a/setuptools/tests/test_pep425tags.py +++ b/setuptools/tests/test_pep425tags.py @@ -4,8 +4,10 @@ from mock import patch from setuptools import pep425tags +__metaclass__ = type -class TestPEP425Tags(object): + +class TestPEP425Tags: def mock_get_config_var(self, **kwd): """ @@ -104,7 +106,7 @@ class TestPEP425Tags(object): self.abi_tag_unicode('dm', {'Py_DEBUG': True, 'WITH_PYMALLOC': True}) -class TestManylinux1Tags(object): +class TestManylinux1Tags: @patch('setuptools.pep425tags.get_platform', lambda: 'linux_x86_64') @patch('setuptools.glibc.have_compatible_glibc', diff --git a/setuptools/tests/test_wheel.py b/setuptools/tests/test_wheel.py index cf65086..6db5fa1 100644 --- a/setuptools/tests/test_wheel.py +++ b/setuptools/tests/test_wheel.py @@ -24,6 +24,8 @@ from .contexts import tempdir from .files import build_files from .textwrap import DALS +__metaclass__ = type + WHEEL_INFO_TESTS = ( ('invalid.whl', ValueError), @@ -148,7 +150,7 @@ def _check_wheel_install(filename, install_dir, install_tree_includes, assert requires_txt == dist.get_metadata('requires.txt').lstrip() -class Record(object): +class Record: def __init__(self, id, **kwargs): self._id = id diff --git a/setuptools/wheel.py b/setuptools/wheel.py index 4a33b20..95a794a 100644 --- a/setuptools/wheel.py +++ b/setuptools/wheel.py @@ -1,4 +1,4 @@ -'''Wheels support.''' +"""Wheels support.""" from distutils.util import get_platform import email @@ -16,11 +16,14 @@ from setuptools import pep425tags from setuptools.command.egg_info import write_requirements +__metaclass__ = type + + WHEEL_NAME = re.compile( r"""^(?P.+?)-(?P\d.*?) ((-(?P\d.*?))?-(?P.+?)-(?P.+?)-(?P.+?) )\.whl$""", -re.VERBOSE).match + re.VERBOSE).match NAMESPACE_PACKAGE_INIT = '''\ try: @@ -52,7 +55,7 @@ def unpack(src_dir, dst_dir): os.rmdir(dirpath) -class Wheel(object): +class Wheel: def __init__(self, filename): match = WHEEL_NAME(os.path.basename(filename)) @@ -64,9 +67,11 @@ class Wheel(object): def tags(self): '''List tags (py_version, abi, platform) supported by this wheel.''' - return itertools.product(self.py_version.split('.'), - self.abi.split('.'), - self.platform.split('.')) + return itertools.product( + self.py_version.split('.'), + self.abi.split('.'), + self.platform.split('.'), + ) def is_compatible(self): '''Is the wheel is compatible with the current platform?''' @@ -92,84 +97,114 @@ class Wheel(object): def install_as_egg(self, destination_eggdir): '''Install wheel as an egg directory.''' with zipfile.ZipFile(self.filename) as zf: - dist_basename = '%s-%s' % (self.project_name, self.version) - dist_info = self.get_dist_info(zf) - dist_data = '%s.data' % dist_basename - def get_metadata(name): - with zf.open(posixpath.join(dist_info, name)) as fp: - value = fp.read().decode('utf-8') if PY3 else fp.read() - return email.parser.Parser().parsestr(value) - wheel_metadata = get_metadata('WHEEL') - dist_metadata = get_metadata('METADATA') - # Check wheel format version is supported. - wheel_version = parse_version(wheel_metadata.get('Wheel-Version')) - if not parse_version('1.0') <= wheel_version < parse_version('2.0dev0'): - raise ValueError('unsupported wheel format version: %s' % wheel_version) - # Extract to target directory. - os.mkdir(destination_eggdir) - zf.extractall(destination_eggdir) - # Convert metadata. - dist_info = os.path.join(destination_eggdir, dist_info) - dist = Distribution.from_location( - destination_eggdir, dist_info, - metadata=PathMetadata(destination_eggdir, dist_info) + self._install_as_egg(destination_eggdir, zf) + + def _install_as_egg(self, destination_eggdir, zf): + dist_basename = '%s-%s' % (self.project_name, self.version) + dist_info = self.get_dist_info(zf) + dist_data = '%s.data' % dist_basename + egg_info = os.path.join(destination_eggdir, 'EGG-INFO') + + self._convert_metadata(zf, destination_eggdir, dist_info, egg_info) + self._move_data_entries(destination_eggdir, dist_data) + self._fix_namespace_packages(egg_info, destination_eggdir) + + @staticmethod + def _convert_metadata(zf, destination_eggdir, dist_info, egg_info): + def get_metadata(name): + with zf.open(posixpath.join(dist_info, name)) as fp: + value = fp.read().decode('utf-8') if PY3 else fp.read() + return email.parser.Parser().parsestr(value) + + wheel_metadata = get_metadata('WHEEL') + # Check wheel format version is supported. + wheel_version = parse_version(wheel_metadata.get('Wheel-Version')) + wheel_v1 = ( + parse_version('1.0') <= wheel_version < parse_version('2.0dev0') + ) + if not wheel_v1: + raise ValueError( + 'unsupported wheel format version: %s' % wheel_version) + # Extract to target directory. + os.mkdir(destination_eggdir) + zf.extractall(destination_eggdir) + # Convert metadata. + dist_info = os.path.join(destination_eggdir, dist_info) + dist = Distribution.from_location( + destination_eggdir, dist_info, + metadata=PathMetadata(destination_eggdir, dist_info), + ) + + # Note: Evaluate and strip markers now, + # as it's difficult to convert back from the syntax: + # foobar; "linux" in sys_platform and extra == 'test' + def raw_req(req): + req.marker = None + return str(req) + install_requires = list(sorted(map(raw_req, dist.requires()))) + extras_require = { + extra: sorted( + req + for req in map(raw_req, dist.requires((extra,))) + if req not in install_requires ) - # Note: we need to evaluate and strip markers now, - # as we can't easily convert back from the syntax: - # foobar; "linux" in sys_platform and extra == 'test' - def raw_req(req): - req.marker = None - return str(req) - install_requires = list(sorted(map(raw_req, dist.requires()))) - extras_require = { - extra: list(sorted( - req - for req in map(raw_req, dist.requires((extra,))) - if req not in install_requires - )) - for extra in dist.extras - } - egg_info = os.path.join(destination_eggdir, 'EGG-INFO') - os.rename(dist_info, egg_info) - os.rename(os.path.join(egg_info, 'METADATA'), - os.path.join(egg_info, 'PKG-INFO')) - setup_dist = SetuptoolsDistribution(attrs=dict( + for extra in dist.extras + } + os.rename(dist_info, egg_info) + os.rename( + os.path.join(egg_info, 'METADATA'), + os.path.join(egg_info, 'PKG-INFO'), + ) + setup_dist = SetuptoolsDistribution( + attrs=dict( install_requires=install_requires, extras_require=extras_require, - )) - write_requirements(setup_dist.get_command_obj('egg_info'), - None, os.path.join(egg_info, 'requires.txt')) - # Move data entries to their correct location. - dist_data = os.path.join(destination_eggdir, dist_data) - dist_data_scripts = os.path.join(dist_data, 'scripts') - if os.path.exists(dist_data_scripts): - egg_info_scripts = os.path.join(destination_eggdir, - 'EGG-INFO', 'scripts') - os.mkdir(egg_info_scripts) - for entry in os.listdir(dist_data_scripts): - # Remove bytecode, as it's not properly handled - # during easy_install scripts install phase. - if entry.endswith('.pyc'): - os.unlink(os.path.join(dist_data_scripts, entry)) - else: - os.rename(os.path.join(dist_data_scripts, entry), - os.path.join(egg_info_scripts, entry)) - os.rmdir(dist_data_scripts) - for subdir in filter(os.path.exists, ( - os.path.join(dist_data, d) - for d in ('data', 'headers', 'purelib', 'platlib') - )): - unpack(subdir, destination_eggdir) - if os.path.exists(dist_data): - os.rmdir(dist_data) - # Fix namespace packages. - namespace_packages = os.path.join(egg_info, 'namespace_packages.txt') - if os.path.exists(namespace_packages): - with open(namespace_packages) as fp: - namespace_packages = fp.read().split() - for mod in namespace_packages: - mod_dir = os.path.join(destination_eggdir, *mod.split('.')) - mod_init = os.path.join(mod_dir, '__init__.py') - if os.path.exists(mod_dir) and not os.path.exists(mod_init): - with open(mod_init, 'w') as fp: - fp.write(NAMESPACE_PACKAGE_INIT) + ), + ) + write_requirements( + setup_dist.get_command_obj('egg_info'), + None, + os.path.join(egg_info, 'requires.txt'), + ) + + @staticmethod + def _move_data_entries(destination_eggdir, dist_data): + """Move data entries to their correct location.""" + dist_data = os.path.join(destination_eggdir, dist_data) + dist_data_scripts = os.path.join(dist_data, 'scripts') + if os.path.exists(dist_data_scripts): + egg_info_scripts = os.path.join( + destination_eggdir, 'EGG-INFO', 'scripts') + os.mkdir(egg_info_scripts) + for entry in os.listdir(dist_data_scripts): + # Remove bytecode, as it's not properly handled + # during easy_install scripts install phase. + if entry.endswith('.pyc'): + os.unlink(os.path.join(dist_data_scripts, entry)) + else: + os.rename( + os.path.join(dist_data_scripts, entry), + os.path.join(egg_info_scripts, entry), + ) + os.rmdir(dist_data_scripts) + for subdir in filter(os.path.exists, ( + os.path.join(dist_data, d) + for d in ('data', 'headers', 'purelib', 'platlib') + )): + unpack(subdir, destination_eggdir) + if os.path.exists(dist_data): + os.rmdir(dist_data) + + @staticmethod + def _fix_namespace_packages(egg_info, destination_eggdir): + namespace_packages = os.path.join( + egg_info, 'namespace_packages.txt') + if os.path.exists(namespace_packages): + with open(namespace_packages) as fp: + namespace_packages = fp.read().split() + for mod in namespace_packages: + mod_dir = os.path.join(destination_eggdir, *mod.split('.')) + mod_init = os.path.join(mod_dir, '__init__.py') + if os.path.exists(mod_dir) and not os.path.exists(mod_init): + with open(mod_init, 'w') as fp: + fp.write(NAMESPACE_PACKAGE_INIT) diff --git a/tests/manual_test.py b/tests/manual_test.py index e5aaf17..52295f9 100644 --- a/tests/manual_test.py +++ b/tests/manual_test.py @@ -89,8 +89,10 @@ def test_full(): assert len(eggs) == 3 assert eggs[1].startswith('setuptools') del eggs[1] - assert eggs == ['extensions-0.3-py2.6.egg', - 'zc.recipe.egg-1.2.2-py2.6.egg'] + assert eggs == [ + 'extensions-0.3-py2.6.egg', + 'zc.recipe.egg-1.2.2-py2.6.egg', + ] if __name__ == '__main__': diff --git a/tests/requirements.txt b/tests/requirements.txt index aff32c1..b38fcbf 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,10 +1,10 @@ -importlib; python_version<"2.7" mock -pytest-flake8<=1.0.0; python_version>="3.3" and python_version<"3.5" -pytest-flake8; python_version>="2.7" and python_version!="3.3" and python_version!="3.4" +pytest-flake8; python_version!="3.4" +pytest-flake8<=1.0.0; python_version=="3.4" virtualenv>=13.0.0 pytest-virtualenv>=1.2.7 pytest>=3.0.2 wheel coverage>=4.5.1 pytest-cov>=2.5.1 +paver; python_version>="3.6" diff --git a/tests/test_pypi.py b/tests/test_pypi.py deleted file mode 100644 index b3425e5..0000000 --- a/tests/test_pypi.py +++ /dev/null @@ -1,82 +0,0 @@ -import os -import subprocess - -import virtualenv -from setuptools.extern.six.moves import http_client -from setuptools.extern.six.moves import xmlrpc_client - -TOP = 200 -PYPI_HOSTNAME = 'pypi.python.org' - - -def rpc_pypi(method, *args): - """Call an XML-RPC method on the Pypi server.""" - conn = http_client.HTTPSConnection(PYPI_HOSTNAME) - headers = {'Content-Type': 'text/xml'} - payload = xmlrpc_client.dumps(args, method) - - conn.request("POST", "/pypi", payload, headers) - response = conn.getresponse() - if response.status == 200: - result = xmlrpc_client.loads(response.read())[0][0] - return result - else: - raise RuntimeError("Unable to download the list of top " - "packages from Pypi.") - - -def get_top_packages(limit): - """Collect the name of the top packages on Pypi.""" - packages = rpc_pypi('top_packages') - return packages[:limit] - - -def _package_install(package_name, tmp_dir=None, local_setuptools=True): - """Try to install a package and return the exit status. - - This function creates a virtual environment, install setuptools using pip - and then install the required package. If local_setuptools is True, it - will install the local version of setuptools. - """ - package_dir = os.path.join(tmp_dir, "test_%s" % package_name) - if not local_setuptools: - package_dir = package_dir + "_baseline" - - virtualenv.create_environment(package_dir) - - pip_path = os.path.join(package_dir, "bin", "pip") - if local_setuptools: - subprocess.check_call([pip_path, "install", "."]) - returncode = subprocess.call([pip_path, "install", package_name]) - return returncode - - -def test_package_install(package_name, tmpdir): - """Test to verify the outcome of installing a package. - - This test compare that the return code when installing a package is the - same as with the current stable version of setuptools. - """ - new_exit_status = _package_install(package_name, tmp_dir=str(tmpdir)) - if new_exit_status: - print("Installation failed, testing against stable setuptools", - package_name) - old_exit_status = _package_install(package_name, tmp_dir=str(tmpdir), - local_setuptools=False) - assert new_exit_status == old_exit_status - - -def pytest_generate_tests(metafunc): - """Generator function for test_package_install. - - This function will generate calls to test_package_install. If a package - list has been specified on the command line, it will be used. Otherwise, - Pypi will be queried to get the current list of top packages. - """ - if "package_name" in metafunc.fixturenames: - if not metafunc.config.option.package_name: - packages = get_top_packages(TOP) - packages = [name for name, downloads in packages] - else: - packages = metafunc.config.option.package_name - metafunc.parametrize("package_name", packages) diff --git a/tox.ini b/tox.ini index a16e89f..1a36965 100644 --- a/tox.ini +++ b/tox.ini @@ -2,7 +2,7 @@ # # To run Tox against all supported Python interpreters, you can set: # -# export TOXENV='py27,py3{3,4,5,6},pypy,pypy3' +# export TOXENV='py27,py3{4,5,6},pypy,pypy3' [tox] envlist=python -- 2.34.1