From 4a6b8ba7ced6bb841000a59bdef7f9879fb6578d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 17 Feb 2019 15:42:23 -0500 Subject: Add test capturing expectation that provides_extras are ordered. --- setuptools/tests/test_dist.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/setuptools/tests/test_dist.py b/setuptools/tests/test_dist.py index 390c3dfc..e349d068 100644 --- a/setuptools/tests/test_dist.py +++ b/setuptools/tests/test_dist.py @@ -263,3 +263,16 @@ def test_maintainer_author(name, attrs, tmpdir): else: line = '%s: %s' % (fkey, val) assert line in pkg_lines_set + + +def test_provides_extras_deterministic_order(): + attrs = dict(extras_require=dict( + a=['foo'], + b=['bar'], + )) + dist = Distribution(attrs) + assert dist.metadata.provides_extras == ['a', 'b'] + attrs['extras_require'] = dict( + reversed(list(attrs['extras_require'].items()))) + dist = Distribution(attrs) + assert dist.metadata.provides_extras == ['b', 'a'] -- cgit v1.2.3 From 3d289a7015b9ba4f8dd29594309e472fd880841e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 17 Feb 2019 17:01:57 -0500 Subject: Add 'ordered_set' as a vendored package --- setuptools/_vendor/ordered_set.py | 488 ++++++++++++++++++++++++++++++++++++++ setuptools/_vendor/vendored.txt | 1 + setuptools/extern/__init__.py | 2 +- 3 files changed, 490 insertions(+), 1 deletion(-) create mode 100644 setuptools/_vendor/ordered_set.py diff --git a/setuptools/_vendor/ordered_set.py b/setuptools/_vendor/ordered_set.py new file mode 100644 index 00000000..d257470b --- /dev/null +++ b/setuptools/_vendor/ordered_set.py @@ -0,0 +1,488 @@ +""" +An OrderedSet is a custom MutableSet that remembers its order, so that every +entry has an index that can be looked up. + +Based on a recipe originally posted to ActiveState Recipes by Raymond Hettiger, +and released under the MIT license. +""" +import itertools as it +from collections import deque + +try: + # Python 3 + from collections.abc import MutableSet, Sequence +except ImportError: + # Python 2.7 + from collections import MutableSet, Sequence + +SLICE_ALL = slice(None) +__version__ = "3.1" + + +def is_iterable(obj): + """ + Are we being asked to look up a list of things, instead of a single thing? + We check for the `__iter__` attribute so that this can cover types that + don't have to be known by this module, such as NumPy arrays. + + Strings, however, should be considered as atomic values to look up, not + iterables. The same goes for tuples, since they are immutable and therefore + valid entries. + + We don't need to check for the Python 2 `unicode` type, because it doesn't + have an `__iter__` attribute anyway. + """ + return ( + hasattr(obj, "__iter__") + and not isinstance(obj, str) + and not isinstance(obj, tuple) + ) + + +class OrderedSet(MutableSet, Sequence): + """ + An OrderedSet is a custom MutableSet that remembers its order, so that + every entry has an index that can be looked up. + + Example: + >>> OrderedSet([1, 1, 2, 3, 2]) + OrderedSet([1, 2, 3]) + """ + + def __init__(self, iterable=None): + self.items = [] + self.map = {} + if iterable is not None: + self |= iterable + + def __len__(self): + """ + Returns the number of unique elements in the ordered set + + Example: + >>> len(OrderedSet([])) + 0 + >>> len(OrderedSet([1, 2])) + 2 + """ + return len(self.items) + + def __getitem__(self, index): + """ + Get the item at a given index. + + If `index` is a slice, you will get back that slice of items, as a + new OrderedSet. + + If `index` is a list or a similar iterable, you'll get a list of + items corresponding to those indices. This is similar to NumPy's + "fancy indexing". The result is not an OrderedSet because you may ask + for duplicate indices, and the number of elements returned should be + the number of elements asked for. + + Example: + >>> oset = OrderedSet([1, 2, 3]) + >>> oset[1] + 2 + """ + if isinstance(index, slice) and index == SLICE_ALL: + return self.copy() + elif hasattr(index, "__index__") or isinstance(index, slice): + result = self.items[index] + if isinstance(result, list): + return self.__class__(result) + else: + return result + elif is_iterable(index): + return [self.items[i] for i in index] + else: + raise TypeError("Don't know how to index an OrderedSet by %r" % index) + + def copy(self): + """ + Return a shallow copy of this object. + + Example: + >>> this = OrderedSet([1, 2, 3]) + >>> other = this.copy() + >>> this == other + True + >>> this is other + False + """ + return self.__class__(self) + + def __getstate__(self): + if len(self) == 0: + # The state can't be an empty list. + # We need to return a truthy value, or else __setstate__ won't be run. + # + # This could have been done more gracefully by always putting the state + # in a tuple, but this way is backwards- and forwards- compatible with + # previous versions of OrderedSet. + return (None,) + else: + return list(self) + + def __setstate__(self, state): + if state == (None,): + self.__init__([]) + else: + self.__init__(state) + + def __contains__(self, key): + """ + Test if the item is in this ordered set + + Example: + >>> 1 in OrderedSet([1, 3, 2]) + True + >>> 5 in OrderedSet([1, 3, 2]) + False + """ + return key in self.map + + def add(self, key): + """ + Add `key` as an item to this OrderedSet, then return its index. + + If `key` is already in the OrderedSet, return the index it already + had. + + Example: + >>> oset = OrderedSet() + >>> oset.append(3) + 0 + >>> print(oset) + OrderedSet([3]) + """ + if key not in self.map: + self.map[key] = len(self.items) + self.items.append(key) + return self.map[key] + + append = add + + def update(self, sequence): + """ + Update the set with the given iterable sequence, then return the index + of the last element inserted. + + Example: + >>> oset = OrderedSet([1, 2, 3]) + >>> oset.update([3, 1, 5, 1, 4]) + 4 + >>> print(oset) + OrderedSet([1, 2, 3, 5, 4]) + """ + item_index = None + try: + for item in sequence: + item_index = self.add(item) + except TypeError: + raise ValueError( + "Argument needs to be an iterable, got %s" % type(sequence) + ) + return item_index + + def index(self, key): + """ + Get the index of a given entry, raising an IndexError if it's not + present. + + `key` can be an iterable of entries that is not a string, in which case + this returns a list of indices. + + Example: + >>> oset = OrderedSet([1, 2, 3]) + >>> oset.index(2) + 1 + """ + if is_iterable(key): + return [self.index(subkey) for subkey in key] + return self.map[key] + + # Provide some compatibility with pd.Index + get_loc = index + get_indexer = index + + def pop(self): + """ + Remove and return the last element from the set. + + Raises KeyError if the set is empty. + + Example: + >>> oset = OrderedSet([1, 2, 3]) + >>> oset.pop() + 3 + """ + if not self.items: + raise KeyError("Set is empty") + + elem = self.items[-1] + del self.items[-1] + del self.map[elem] + return elem + + def discard(self, key): + """ + Remove an element. Do not raise an exception if absent. + + The MutableSet mixin uses this to implement the .remove() method, which + *does* raise an error when asked to remove a non-existent item. + + Example: + >>> oset = OrderedSet([1, 2, 3]) + >>> oset.discard(2) + >>> print(oset) + OrderedSet([1, 3]) + >>> oset.discard(2) + >>> print(oset) + OrderedSet([1, 3]) + """ + if key in self: + i = self.map[key] + del self.items[i] + del self.map[key] + for k, v in self.map.items(): + if v >= i: + self.map[k] = v - 1 + + def clear(self): + """ + Remove all items from this OrderedSet. + """ + del self.items[:] + self.map.clear() + + def __iter__(self): + """ + Example: + >>> list(iter(OrderedSet([1, 2, 3]))) + [1, 2, 3] + """ + return iter(self.items) + + def __reversed__(self): + """ + Example: + >>> list(reversed(OrderedSet([1, 2, 3]))) + [3, 2, 1] + """ + return reversed(self.items) + + def __repr__(self): + if not self: + return "%s()" % (self.__class__.__name__,) + return "%s(%r)" % (self.__class__.__name__, list(self)) + + def __eq__(self, other): + """ + Returns true if the containers have the same items. If `other` is a + Sequence, then order is checked, otherwise it is ignored. + + Example: + >>> oset = OrderedSet([1, 3, 2]) + >>> oset == [1, 3, 2] + True + >>> oset == [1, 2, 3] + False + >>> oset == [2, 3] + False + >>> oset == OrderedSet([3, 2, 1]) + False + """ + # In Python 2 deque is not a Sequence, so treat it as one for + # consistent behavior with Python 3. + if isinstance(other, (Sequence, deque)): + # Check that this OrderedSet contains the same elements, in the + # same order, as the other object. + return list(self) == list(other) + try: + other_as_set = set(other) + except TypeError: + # If `other` can't be converted into a set, it's not equal. + return False + else: + return set(self) == other_as_set + + def union(self, *sets): + """ + Combines all unique items. + Each items order is defined by its first appearance. + + Example: + >>> oset = OrderedSet.union(OrderedSet([3, 1, 4, 1, 5]), [1, 3], [2, 0]) + >>> print(oset) + OrderedSet([3, 1, 4, 5, 2, 0]) + >>> oset.union([8, 9]) + OrderedSet([3, 1, 4, 5, 2, 0, 8, 9]) + >>> oset | {10} + OrderedSet([3, 1, 4, 5, 2, 0, 10]) + """ + cls = self.__class__ if isinstance(self, OrderedSet) else OrderedSet + containers = map(list, it.chain([self], sets)) + items = it.chain.from_iterable(containers) + return cls(items) + + def __and__(self, other): + # the parent implementation of this is backwards + return self.intersection(other) + + def intersection(self, *sets): + """ + Returns elements in common between all sets. Order is defined only + by the first set. + + Example: + >>> oset = OrderedSet.intersection(OrderedSet([0, 1, 2, 3]), [1, 2, 3]) + >>> print(oset) + OrderedSet([1, 2, 3]) + >>> oset.intersection([2, 4, 5], [1, 2, 3, 4]) + OrderedSet([2]) + >>> oset.intersection() + OrderedSet([1, 2, 3]) + """ + cls = self.__class__ if isinstance(self, OrderedSet) else OrderedSet + if sets: + common = set.intersection(*map(set, sets)) + items = (item for item in self if item in common) + else: + items = self + return cls(items) + + def difference(self, *sets): + """ + Returns all elements that are in this set but not the others. + + Example: + >>> OrderedSet([1, 2, 3]).difference(OrderedSet([2])) + OrderedSet([1, 3]) + >>> OrderedSet([1, 2, 3]).difference(OrderedSet([2]), OrderedSet([3])) + OrderedSet([1]) + >>> OrderedSet([1, 2, 3]) - OrderedSet([2]) + OrderedSet([1, 3]) + >>> OrderedSet([1, 2, 3]).difference() + OrderedSet([1, 2, 3]) + """ + cls = self.__class__ + if sets: + other = set.union(*map(set, sets)) + items = (item for item in self if item not in other) + else: + items = self + return cls(items) + + def issubset(self, other): + """ + Report whether another set contains this set. + + Example: + >>> OrderedSet([1, 2, 3]).issubset({1, 2}) + False + >>> OrderedSet([1, 2, 3]).issubset({1, 2, 3, 4}) + True + >>> OrderedSet([1, 2, 3]).issubset({1, 4, 3, 5}) + False + """ + if len(self) > len(other): # Fast check for obvious cases + return False + return all(item in other for item in self) + + def issuperset(self, other): + """ + Report whether this set contains another set. + + Example: + >>> OrderedSet([1, 2]).issuperset([1, 2, 3]) + False + >>> OrderedSet([1, 2, 3, 4]).issuperset({1, 2, 3}) + True + >>> OrderedSet([1, 4, 3, 5]).issuperset({1, 2, 3}) + False + """ + if len(self) < len(other): # Fast check for obvious cases + return False + return all(item in self for item in other) + + def symmetric_difference(self, other): + """ + Return the symmetric difference of two OrderedSets as a new set. + That is, the new set will contain all elements that are in exactly + one of the sets. + + Their order will be preserved, with elements from `self` preceding + elements from `other`. + + Example: + >>> this = OrderedSet([1, 4, 3, 5, 7]) + >>> other = OrderedSet([9, 7, 1, 3, 2]) + >>> this.symmetric_difference(other) + OrderedSet([4, 5, 9, 2]) + """ + cls = self.__class__ if isinstance(self, OrderedSet) else OrderedSet + diff1 = cls(self).difference(other) + diff2 = cls(other).difference(self) + return diff1.union(diff2) + + def _update_items(self, items): + """ + Replace the 'items' list of this OrderedSet with a new one, updating + self.map accordingly. + """ + self.items = items + self.map = {item: idx for (idx, item) in enumerate(items)} + + def difference_update(self, *sets): + """ + Update this OrderedSet to remove items from one or more other sets. + + Example: + >>> this = OrderedSet([1, 2, 3]) + >>> this.difference_update(OrderedSet([2, 4])) + >>> print(this) + OrderedSet([1, 3]) + + >>> this = OrderedSet([1, 2, 3, 4, 5]) + >>> this.difference_update(OrderedSet([2, 4]), OrderedSet([1, 4, 6])) + >>> print(this) + OrderedSet([3, 5]) + """ + items_to_remove = set() + for other in sets: + items_to_remove |= set(other) + self._update_items([item for item in self.items if item not in items_to_remove]) + + def intersection_update(self, other): + """ + Update this OrderedSet to keep only items in another set, preserving + their order in this set. + + Example: + >>> this = OrderedSet([1, 4, 3, 5, 7]) + >>> other = OrderedSet([9, 7, 1, 3, 2]) + >>> this.intersection_update(other) + >>> print(this) + OrderedSet([1, 3, 7]) + """ + other = set(other) + self._update_items([item for item in self.items if item in other]) + + def symmetric_difference_update(self, other): + """ + Update this OrderedSet to remove items from another set, then + add items from the other set that were not present in this set. + + Example: + >>> this = OrderedSet([1, 4, 3, 5, 7]) + >>> other = OrderedSet([9, 7, 1, 3, 2]) + >>> this.symmetric_difference_update(other) + >>> print(this) + OrderedSet([4, 5, 9, 2]) + """ + items_to_add = [item for item in other if item not in self] + items_to_remove = set(other) + self._update_items( + [item for item in self.items if item not in items_to_remove] + items_to_add + ) diff --git a/setuptools/_vendor/vendored.txt b/setuptools/_vendor/vendored.txt index 7d77863d..379aae56 100644 --- a/setuptools/_vendor/vendored.txt +++ b/setuptools/_vendor/vendored.txt @@ -1,3 +1,4 @@ packaging==16.8 pyparsing==2.2.1 six==1.10.0 +ordered-set diff --git a/setuptools/extern/__init__.py b/setuptools/extern/__init__.py index cb2fa329..e8c616f9 100644 --- a/setuptools/extern/__init__.py +++ b/setuptools/extern/__init__.py @@ -69,5 +69,5 @@ class VendorImporter: sys.meta_path.append(self) -names = 'six', 'packaging', 'pyparsing', +names = 'six', 'packaging', 'pyparsing', 'ordered_set', VendorImporter(__name__, names, 'setuptools._vendor').install() -- cgit v1.2.3 From 636070d9922f1443ae98b0fdd45b6c74c3c9af11 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 17 Feb 2019 17:09:26 -0500 Subject: Use an ordered set when constructing 'extras provided'. Ref #1305. --- setuptools/dist.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setuptools/dist.py b/setuptools/dist.py index ddb1787a..ce37761e 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -28,6 +28,7 @@ from distutils.version import StrictVersion from setuptools.extern import six from setuptools.extern import packaging +from setuptools.extern import ordered_set from setuptools.extern.six.moves import map, filter, filterfalse from . import SetuptoolsDeprecationWarning @@ -408,7 +409,7 @@ class Distribution(_Distribution): _DISTUTILS_UNSUPPORTED_METADATA = { 'long_description_content_type': None, 'project_urls': dict, - 'provides_extras': set, + 'provides_extras': ordered_set.OrderedSet, } _patched_dist = None -- cgit v1.2.3 From 7f7780e5b572d6fcacd63bf99389dd9f48c5345c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 17 Feb 2019 17:37:01 -0500 Subject: In tests, force deterministic ordering on extras_require so tests pass. --- setuptools/tests/test_dist.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/setuptools/tests/test_dist.py b/setuptools/tests/test_dist.py index e349d068..0c0b9d66 100644 --- a/setuptools/tests/test_dist.py +++ b/setuptools/tests/test_dist.py @@ -3,6 +3,8 @@ from __future__ import unicode_literals import io +import collections + from setuptools.dist import DistDeprecationWarning, _get_unpatched from setuptools import Distribution from setuptools.extern.six.moves.urllib.request import pathname2url @@ -266,13 +268,13 @@ def test_maintainer_author(name, attrs, tmpdir): def test_provides_extras_deterministic_order(): - attrs = dict(extras_require=dict( - a=['foo'], - b=['bar'], - )) + extras = collections.OrderedDict() + extras['a'] = ['foo'] + extras['b'] = ['bar'] + attrs = dict(extras_require=extras) dist = Distribution(attrs) assert dist.metadata.provides_extras == ['a', 'b'] - attrs['extras_require'] = dict( + attrs['extras_require'] = collections.OrderedDict( reversed(list(attrs['extras_require'].items()))) dist = Distribution(attrs) assert dist.metadata.provides_extras == ['b', 'a'] -- cgit v1.2.3 From 880ff4a3579bac7839f8f038085381ae14155f31 Mon Sep 17 00:00:00 2001 From: Bastian Venthur Date: Thu, 16 May 2019 12:46:50 +0200 Subject: Force metadata-version = 1.2 when project urls are present. Closes: #1756 --- setuptools/dist.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setuptools/dist.py b/setuptools/dist.py index 9a165de0..ea6411b1 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -54,7 +54,8 @@ def get_metadata_version(self): mv = StrictVersion('2.1') elif (self.maintainer is not None or self.maintainer_email is not None or - getattr(self, 'python_requires', None) is not None): + getattr(self, 'python_requires', None) is not None or + self.project_urls): mv = StrictVersion('1.2') elif (self.provides or self.requires or self.obsoletes or self.classifiers or self.download_url): -- cgit v1.2.3 From a64ddf0d2f2bcd6e9843fb55c94fba922f315722 Mon Sep 17 00:00:00 2001 From: Bastian Venthur Date: Thu, 16 May 2019 13:48:15 +0200 Subject: Added test for metadata-version 1.2 --- setuptools/tests/test_egg_info.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index db9c3873..316eb2ed 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -622,6 +622,7 @@ class TestEggInfo: assert expected_line in pkg_info_lines expected_line = 'Project-URL: Link Two, https://example.com/two/' assert expected_line in pkg_info_lines + assert 'Metadata-Version: 1.2' in pkg_info_lines def test_python_requires_egg_info(self, tmpdir_cwd, env): self._setup_script_with_requires( -- cgit v1.2.3 From 5e8927a17f4e1a5b7e97cbe42639dbcba21acb69 Mon Sep 17 00:00:00 2001 From: Bastian Venthur Date: Fri, 17 May 2019 08:22:55 +0200 Subject: Added changelog entry. --- changelog.d/1756.change.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/1756.change.rst diff --git a/changelog.d/1756.change.rst b/changelog.d/1756.change.rst new file mode 100644 index 00000000..5c908d35 --- /dev/null +++ b/changelog.d/1756.change.rst @@ -0,0 +1 @@ +Forse metadata-version >= 1.2. when project urls are present. -- cgit v1.2.3 From ca1f766ee16c3a504082a95f2afd5a58fcae7d47 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Tue, 28 May 2019 21:38:56 +0200 Subject: tests: unpin pytest The new releases for pytest-fixture-config and pytest-shutil are compatible with pytest>=4.0. --- tests/requirements.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/requirements.txt b/tests/requirements.txt index f944df27..cb3e6726 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -3,8 +3,7 @@ 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 pinned to <4 due to #1638 -pytest>=3.7,<4 +pytest>=3.7 wheel coverage>=4.5.1 pytest-cov>=2.5.1 -- cgit v1.2.3 From 59dd72d9df7a88d692637a8c488aa884c182e557 Mon Sep 17 00:00:00 2001 From: Cyril Roelandt Date: Sat, 1 Jun 2019 20:33:32 +0200 Subject: Use license classifiers rather than the license field. The license field has a 'free' format, while the classifiers are unique identifiers, similar to SPDX identifiers. In the documentation, we should therefore showcase the use of classifiers. --- changelog.d/1776.doc.rst | 1 + docs/setuptools.txt | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 changelog.d/1776.doc.rst diff --git a/changelog.d/1776.doc.rst b/changelog.d/1776.doc.rst new file mode 100644 index 00000000..d4f1dbca --- /dev/null +++ b/changelog.d/1776.doc.rst @@ -0,0 +1 @@ +Use license classifiers rather than the license field. diff --git a/docs/setuptools.txt b/docs/setuptools.txt index 64b385cb..2e7fe3bd 100644 --- a/docs/setuptools.txt +++ b/docs/setuptools.txt @@ -136,16 +136,18 @@ dependencies, and perhaps some data files and scripts:: author="Me", author_email="me@example.com", description="This is an Example Package", - license="PSF", keywords="hello world example examples", url="http://example.com/HelloWorld/", # project home page, if any project_urls={ "Bug Tracker": "https://bugs.example.com/HelloWorld/", "Documentation": "https://docs.example.com/HelloWorld/", "Source Code": "https://code.example.com/HelloWorld/", - } + }, + classifiers=[ + 'License :: OSI Approved :: Python Software Foundation License' + ] - # could also include long_description, download_url, classifiers, etc. + # could also include long_description, download_url, etc. ) In the sections that follow, we'll explain what most of these ``setup()`` @@ -2234,6 +2236,7 @@ boilerplate code in some cases. license = BSD 3-Clause License classifiers = Framework :: Django + License :: OSI Approved :: BSD License Programming Language :: Python :: 3 Programming Language :: Python :: 3.5 -- cgit v1.2.3 From 8aeff6b2c9a64e47ad2a22533d7e65c08cd4103f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 10 Jun 2019 13:03:33 -0400 Subject: Update developer docs to describe motivation behind vendored dependencies. Ref #1781. --- docs/developer-guide.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/developer-guide.txt b/docs/developer-guide.txt index a5942c8b..d145fba1 100644 --- a/docs/developer-guide.txt +++ b/docs/developer-guide.txt @@ -137,3 +137,17 @@ To build the docs locally, use tox:: .. _Sphinx: http://www.sphinx-doc.org/en/master/ .. _published documentation: https://setuptools.readthedocs.io/en/latest/ + +--------------------- +Vendored Dependencies +--------------------- + +Setuptools has some dependencies, but due to `bootstrapping issues +`, those dependencies +cannot be declared as they won't be resolved soon enough to build +setuptools from source. Eventually, this limitation may be lifted as +PEP 517/518 reach ubiquitous adoption, but for now, Setuptools +cannot declare dependencies other than through +``setuptools/_vendor/vendored.txt`` and +``pkg_reosurces/_vendor/vendored.txt`` and refreshed by way of +``paver update_vendored`` (pavement.py). -- cgit v1.2.3 From fa22b42d9f2f8a15568dd3a3d290e33c9be86796 Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Thu, 13 Jun 2019 18:31:57 +0200 Subject: launcher: Fix build with mingw-w64 execv() requires process.h to be included according to the MSVC documentation but for some reason it also works without it. mingw-w64 on the other hand fails to build the launcher if the include isn't there, so add it. --- launcher.c | 1 + 1 file changed, 1 insertion(+) diff --git a/launcher.c b/launcher.c index be69f0c6..23ef3ac2 100644 --- a/launcher.c +++ b/launcher.c @@ -37,6 +37,7 @@ #include #include #include +#include int child_pid=0; -- cgit v1.2.3 From 53b8db359378f436bfd88f90a90aaf01b650d3a6 Mon Sep 17 00:00:00 2001 From: Inada Naoki Date: Tue, 18 Jun 2019 16:15:25 +0900 Subject: Stop using deprecated HTMLParser.unescape HTMLParser.unescape is accessed even when unused - this will cause an exception when `HTMLParser.unescape` is removed in Python 3.9. --- changelog.d/1788.change.rst | 1 + setuptools/py33compat.py | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 changelog.d/1788.change.rst diff --git a/changelog.d/1788.change.rst b/changelog.d/1788.change.rst new file mode 100644 index 00000000..d8a49fd4 --- /dev/null +++ b/changelog.d/1788.change.rst @@ -0,0 +1 @@ +Changed compatibility fallback logic for ``html.unescape`` to avoid accessing ``HTMLParser.unescape`` when not necessary. ``HTMLParser.unescape`` is deprecated and will be removed in Python 3.9. diff --git a/setuptools/py33compat.py b/setuptools/py33compat.py index 87cf5398..cb694436 100644 --- a/setuptools/py33compat.py +++ b/setuptools/py33compat.py @@ -52,4 +52,8 @@ class Bytecode_compat: Bytecode = getattr(dis, 'Bytecode', Bytecode_compat) -unescape = getattr(html, 'unescape', html_parser.HTMLParser().unescape) +unescape = getattr(html, 'unescape', None) +if unescape is None: + # HTMLParser.unescape is deprecated since Python 3.4, and will be removed + # from 3.9. + unescape = html_parser.HTMLParser().unescape -- cgit v1.2.3 From 10fe6be3d61414bd6cd9ed723e961d7ea8f5fd61 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Sun, 30 Jun 2019 14:24:41 +0200 Subject: tests: fix `test_distribution_version_missing` to work with pytest>=5.0 --- pkg_resources/tests/test_pkg_resources.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg_resources/tests/test_pkg_resources.py b/pkg_resources/tests/test_pkg_resources.py index fb77c685..a0f2c452 100644 --- a/pkg_resources/tests/test_pkg_resources.py +++ b/pkg_resources/tests/test_pkg_resources.py @@ -242,7 +242,7 @@ def test_distribution_version_missing(tmpdir, suffix, expected_filename, with pytest.raises(ValueError) as excinfo: dist.version - err = str(excinfo) + err = str(excinfo.value) # Include a string expression after the assert so the full strings # will be visible for inspection on failure. assert expected_text in err, str((expected_text, err)) -- cgit v1.2.3 From 4598c1a2a918f2f74e7242df775308841e477038 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Sun, 30 Jun 2019 14:25:12 +0200 Subject: tests: tweak default pytest arguments to fix Python 3.8 support --- pytest.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytest.ini b/pytest.ini index 1c5b6b09..612fb91f 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,5 +1,5 @@ [pytest] -addopts=--doctest-modules --doctest-glob=pkg_resources/api_tests.txt -rsxX +addopts=--doctest-modules --doctest-glob=pkg_resources/api_tests.txt -r sxX norecursedirs=dist build *.egg setuptools/extern pkg_resources/extern .* flake8-ignore = setuptools/site-patch.py F821 -- cgit v1.2.3 From 67344c95b9402b4720d3c9e61d01096a6453efa6 Mon Sep 17 00:00:00 2001 From: Chris Jerdonek Date: Sat, 13 Jul 2019 03:19:50 -0700 Subject: Fix #1790 : Include the file path in get_metadata() UnicodeDecodeErrors (#1791) Include the file path in get_metadata() UnicodeDecodeErrors. --- changelog.d/1790.change.rst | 2 ++ pkg_resources/__init__.py | 13 ++++++-- pkg_resources/tests/test_pkg_resources.py | 54 +++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 changelog.d/1790.change.rst diff --git a/changelog.d/1790.change.rst b/changelog.d/1790.change.rst new file mode 100644 index 00000000..e4a7998d --- /dev/null +++ b/changelog.d/1790.change.rst @@ -0,0 +1,2 @@ +Added the file path to the error message when a ``UnicodeDecodeError`` occurs +while reading a metadata file. diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 97e08d68..1f170cfd 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -1416,8 +1416,17 @@ class NullProvider: def get_metadata(self, name): if not self.egg_info: return "" - value = self._get(self._fn(self.egg_info, name)) - return value.decode('utf-8') if six.PY3 else value + path = self._get_metadata_path(name) + value = self._get(path) + if six.PY2: + return value + try: + return value.decode('utf-8') + except UnicodeDecodeError as exc: + # Include the path in the error message to simplify + # troubleshooting, and without changing the exception type. + exc.reason += ' in {} file at path: {}'.format(name, path) + raise def get_metadata_lines(self, name): return yield_lines(self.get_metadata(name)) diff --git a/pkg_resources/tests/test_pkg_resources.py b/pkg_resources/tests/test_pkg_resources.py index a0f2c452..5960868a 100644 --- a/pkg_resources/tests/test_pkg_resources.py +++ b/pkg_resources/tests/test_pkg_resources.py @@ -18,6 +18,7 @@ except ImportError: import mock from pkg_resources import DistInfoDistribution, Distribution, EggInfoDistribution +from setuptools.extern import six from pkg_resources.extern.six.moves import map from pkg_resources.extern.six import text_type, string_types @@ -191,6 +192,59 @@ class TestResourceManager: subprocess.check_call(cmd) +def make_test_distribution(metadata_path, metadata): + """ + Make a test Distribution object, and return it. + + :param metadata_path: the path to the metadata file that should be + created. This should be inside a distribution directory that should + also be created. For example, an argument value might end with + ".dist-info/METADATA". + :param metadata: the desired contents of the metadata file, as bytes. + """ + dist_dir = os.path.dirname(metadata_path) + os.mkdir(dist_dir) + with open(metadata_path, 'wb') as f: + f.write(metadata) + dists = list(pkg_resources.distributions_from_metadata(dist_dir)) + dist, = dists + + return dist + + +def test_get_metadata__bad_utf8(tmpdir): + """ + Test a metadata file with bytes that can't be decoded as utf-8. + """ + filename = 'METADATA' + # Convert the tmpdir LocalPath object to a string before joining. + metadata_path = os.path.join(str(tmpdir), 'foo.dist-info', filename) + # Encode a non-ascii string with the wrong encoding (not utf-8). + metadata = 'née'.encode('iso-8859-1') + dist = make_test_distribution(metadata_path, metadata=metadata) + + if six.PY2: + # In Python 2, get_metadata() doesn't do any decoding. + actual = dist.get_metadata(filename) + assert actual == metadata + return + + # Otherwise, we are in the Python 3 case. + with pytest.raises(UnicodeDecodeError) as excinfo: + dist.get_metadata(filename) + + exc = excinfo.value + actual = str(exc) + expected = ( + # The error message starts with "'utf-8' codec ..." However, the + # spelling of "utf-8" can vary (e.g. "utf8") so we don't include it + "codec can't decode byte 0xe9 in position 1: " + 'invalid continuation byte in METADATA file at path: ' + ) + assert expected in actual, 'actual: {}'.format(actual) + assert actual.endswith(metadata_path), 'actual: {}'.format(actual) + + # TODO: remove this in favor of Path.touch() when Python 2 is dropped. def touch_file(path): """ -- cgit v1.2.3 From 305bb1cefc3251c67b55149139a768ddf474f7b6 Mon Sep 17 00:00:00 2001 From: Daniel Himmelstein Date: Thu, 23 May 2019 14:15:19 -0400 Subject: fix assert_string_list docstring value=None raises TypeError DistutilsSetupError: 2 must be a list of strings (got None) --- setuptools/dist.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/dist.py b/setuptools/dist.py index ea6411b1..1e1b83be 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -213,7 +213,7 @@ def check_importable(dist, attr, value): def assert_string_list(dist, attr, value): - """Verify that value is a string list or None""" + """Verify that value is a string list""" try: assert ''.join(value) != value except (TypeError, ValueError, AttributeError, AssertionError): -- cgit v1.2.3 From 8f848bd777278fc8dcb42dc45751cd8b95ec2a02 Mon Sep 17 00:00:00 2001 From: Daniel Himmelstein Date: Wed, 22 May 2019 17:45:44 -0400 Subject: improve `package_data` check Ensure the dictionary values are lists/tuples of strings. Fix #1459. --- changelog.d/1769.change.rst | 1 + setuptools/dist.py | 29 +++++++++++------------ setuptools/tests/test_dist.py | 53 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 68 insertions(+), 15 deletions(-) create mode 100644 changelog.d/1769.change.rst diff --git a/changelog.d/1769.change.rst b/changelog.d/1769.change.rst new file mode 100644 index 00000000..d48a23b6 --- /dev/null +++ b/changelog.d/1769.change.rst @@ -0,0 +1 @@ +Improve ``package_data`` check: ensure the dictionary values are lists/tuples of strings. diff --git a/setuptools/dist.py b/setuptools/dist.py index 1e1b83be..f0f030b5 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -215,6 +215,10 @@ def check_importable(dist, attr, value): def assert_string_list(dist, attr, value): """Verify that value is a string list""" try: + # verify that value is a list or tuple to exclude unordered + # or single-use iterables + assert isinstance(value, (list, tuple)) + # verify that elements of value are strings assert ''.join(value) != value except (TypeError, ValueError, AttributeError, AssertionError): raise DistutilsSetupError( @@ -307,20 +311,17 @@ def check_test_suite(dist, attr, value): def check_package_data(dist, attr, value): """Verify that value is a dictionary of package names to glob lists""" - if isinstance(value, dict): - for k, v in value.items(): - if not isinstance(k, str): - break - try: - iter(v) - except TypeError: - break - else: - return - raise DistutilsSetupError( - attr + " must be a dictionary mapping package names to lists of " - "wildcard patterns" - ) + if not isinstance(value, dict): + raise DistutilsSetupError( + "{!r} must be a dictionary mapping package names to lists of " + "string wildcard patterns".format(attr)) + for k, v in value.items(): + if not isinstance(k, six.string_types): + raise DistutilsSetupError( + "keys of {!r} dict must be strings (got {!r})" + .format(attr, k) + ) + assert_string_list(dist, 'values of {!r} dict'.format(attr), v) def check_packages(dist, attr, value): diff --git a/setuptools/tests/test_dist.py b/setuptools/tests/test_dist.py index 390c3dfc..c771a19a 100644 --- a/setuptools/tests/test_dist.py +++ b/setuptools/tests/test_dist.py @@ -3,7 +3,13 @@ from __future__ import unicode_literals import io -from setuptools.dist import DistDeprecationWarning, _get_unpatched +import re +from distutils.errors import DistutilsSetupError +from setuptools.dist import ( + _get_unpatched, + check_package_data, + DistDeprecationWarning, +) from setuptools import Distribution from setuptools.extern.six.moves.urllib.request import pathname2url from setuptools.extern.six.moves.urllib_parse import urljoin @@ -263,3 +269,48 @@ def test_maintainer_author(name, attrs, tmpdir): else: line = '%s: %s' % (fkey, val) assert line in pkg_lines_set + + +CHECK_PACKAGE_DATA_TESTS = ( + # Valid. + ({ + '': ['*.txt', '*.rst'], + 'hello': ['*.msg'], + }, None), + # Not a dictionary. + (( + ('', ['*.txt', '*.rst']), + ('hello', ['*.msg']), + ), ( + "'package_data' must be a dictionary mapping package" + " names to lists of string wildcard patterns" + )), + # Invalid key type. + ({ + 400: ['*.txt', '*.rst'], + }, ( + "keys of 'package_data' dict must be strings (got 400)" + )), + # Invalid value type. + ({ + 'hello': str('*.msg'), + }, ( + "\"values of 'package_data' dict\" must be a list of strings (got '*.msg')" + )), + # Invalid value type (generators are single use) + ({ + 'hello': (x for x in "generator"), + }, ( + "\"values of 'package_data' dict\" must be a list of strings " + "(got Date: Tue, 23 Jul 2019 11:29:21 +0200 Subject: tests: fix `test_pip_upgrade_from_source` on Python 3.4 Do not test pip's master on 3.4, as support for it has been dropped. --- setuptools/tests/test_virtualenv.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/setuptools/tests/test_virtualenv.py b/setuptools/tests/test_virtualenv.py index d7b98c77..74a1284c 100644 --- a/setuptools/tests/test_virtualenv.py +++ b/setuptools/tests/test_virtualenv.py @@ -8,6 +8,8 @@ from pytest_fixture_config import yield_requires_config import pytest_virtualenv +from setuptools.extern import six + from .textwrap import DALS from .test_easy_install import make_nspkg_sdist @@ -75,9 +77,12 @@ def _get_pip_versions(): 'pip==10.0.1', 'pip==18.1', 'pip==19.0.1', - 'https://github.com/pypa/pip/archive/master.zip', ] + # Pip's master dropped support for 3.4. + if not six.PY34: + network_versions.append('https://github.com/pypa/pip/archive/master.zip') + versions = [None] + [ pytest.param(v, **({} if network else {'marks': pytest.mark.skip})) for v in network_versions -- cgit v1.2.3 From 5405d1e2770e798ed755e8cc821f6b95cb480d52 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Mon, 12 Aug 2019 06:18:19 +0200 Subject: travis: update PyPy jobs to use more recent versions --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ffcad998..64d0544c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,9 +8,9 @@ jobs: python: 2.7 - <<: *latest_py2 env: LANG=C - - python: pypy2.7-6.0.0 + - python: pypy env: DISABLE_COVERAGE=1 # Don't run coverage on pypy (too slow). - - python: pypy3.5-6.0.0 + - python: pypy3 env: DISABLE_COVERAGE=1 - python: 3.4 - python: 3.5 -- cgit v1.2.3 From 95d72cc558c7dddef164eb09a880b95e2f484bee Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 13 Aug 2019 09:42:47 -0400 Subject: =?UTF-8?q?Bump=20version:=2041.0.1=20=E2=86=92=2041.1.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- CHANGES.rst | 13 +++++++++++++ changelog.d/1697.change.rst | 1 - changelog.d/1749.change.rst | 1 - changelog.d/1750.change.rst | 1 - changelog.d/1756.change.rst | 1 - changelog.d/1769.change.rst | 1 - changelog.d/1776.doc.rst | 1 - changelog.d/1788.change.rst | 1 - changelog.d/1790.change.rst | 2 -- setup.cfg | 2 +- 11 files changed, 15 insertions(+), 11 deletions(-) delete mode 100644 changelog.d/1697.change.rst delete mode 100644 changelog.d/1749.change.rst delete mode 100644 changelog.d/1750.change.rst delete mode 100644 changelog.d/1756.change.rst delete mode 100644 changelog.d/1769.change.rst delete mode 100644 changelog.d/1776.doc.rst delete mode 100644 changelog.d/1788.change.rst delete mode 100644 changelog.d/1790.change.rst diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 87acb5ef..5a453660 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 41.0.1 +current_version = 41.1.0 commit = True tag = True diff --git a/CHANGES.rst b/CHANGES.rst index 9da22537..9f9603c0 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,16 @@ +v41.1.0 +------- + +* #1697: Moved most of the constants from setup.py to setup.cfg +* #1749: Fixed issue with the PEP 517 backend where building a source distribution would fail if any tarball existed in the destination directory. +* #1750: Fixed an issue with PEP 517 backend where wheel builds would fail if the destination directory did not already exist. +* #1756: Forse metadata-version >= 1.2. when project urls are present. +* #1769: Improve ``package_data`` check: ensure the dictionary values are lists/tuples of strings. +* #1788: Changed compatibility fallback logic for ``html.unescape`` to avoid accessing ``HTMLParser.unescape`` when not necessary. ``HTMLParser.unescape`` is deprecated and will be removed in Python 3.9. +* #1790: Added the file path to the error message when a ``UnicodeDecodeError`` occurs while reading a metadata file. +* #1776: Use license classifiers rather than the license field. + + v41.0.1 ------- diff --git a/changelog.d/1697.change.rst b/changelog.d/1697.change.rst deleted file mode 100644 index 44818b3c..00000000 --- a/changelog.d/1697.change.rst +++ /dev/null @@ -1 +0,0 @@ -Moved most of the constants from setup.py to setup.cfg diff --git a/changelog.d/1749.change.rst b/changelog.d/1749.change.rst deleted file mode 100644 index de678072..00000000 --- a/changelog.d/1749.change.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed issue with the PEP 517 backend where building a source distribution would fail if any tarball existed in the destination directory. diff --git a/changelog.d/1750.change.rst b/changelog.d/1750.change.rst deleted file mode 100644 index 7a22229e..00000000 --- a/changelog.d/1750.change.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed an issue with PEP 517 backend where wheel builds would fail if the destination directory did not already exist. diff --git a/changelog.d/1756.change.rst b/changelog.d/1756.change.rst deleted file mode 100644 index 5c908d35..00000000 --- a/changelog.d/1756.change.rst +++ /dev/null @@ -1 +0,0 @@ -Forse metadata-version >= 1.2. when project urls are present. diff --git a/changelog.d/1769.change.rst b/changelog.d/1769.change.rst deleted file mode 100644 index d48a23b6..00000000 --- a/changelog.d/1769.change.rst +++ /dev/null @@ -1 +0,0 @@ -Improve ``package_data`` check: ensure the dictionary values are lists/tuples of strings. diff --git a/changelog.d/1776.doc.rst b/changelog.d/1776.doc.rst deleted file mode 100644 index d4f1dbca..00000000 --- a/changelog.d/1776.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Use license classifiers rather than the license field. diff --git a/changelog.d/1788.change.rst b/changelog.d/1788.change.rst deleted file mode 100644 index d8a49fd4..00000000 --- a/changelog.d/1788.change.rst +++ /dev/null @@ -1 +0,0 @@ -Changed compatibility fallback logic for ``html.unescape`` to avoid accessing ``HTMLParser.unescape`` when not necessary. ``HTMLParser.unescape`` is deprecated and will be removed in Python 3.9. diff --git a/changelog.d/1790.change.rst b/changelog.d/1790.change.rst deleted file mode 100644 index e4a7998d..00000000 --- a/changelog.d/1790.change.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added the file path to the error message when a ``UnicodeDecodeError`` occurs -while reading a metadata file. diff --git a/setup.cfg b/setup.cfg index ff87464b..3bcf4429 100644 --- a/setup.cfg +++ b/setup.cfg @@ -19,7 +19,7 @@ universal = 1 [metadata] name = setuptools -version = 41.0.1 +version = 41.1.0 description = Easily download, build, install, upgrade, and uninstall Python packages author = Python Packaging Authority author_email = distutils-sig@python.org -- cgit v1.2.3 From 42bd00ada0e0f47c2446d6d1b750eb97eba45640 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 13 Aug 2019 09:47:19 -0400 Subject: Prefer token for automated releases --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 64d0544c..13815fd4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,9 +35,9 @@ jobs: on: tags: true all_branches: true - user: jaraco + user: __token__ password: - secure: tfWrsQMH2bHrWjqnP+08IX1WlkbW94Q30f4d7lCyhWS1FIf/jBDx4jrEILNfMxQ1NCwuBRje5sihj1Ow0BFf0vVrkaeff2IdvnNDEGFduMejaEQJL3s3QrLfpiAvUbtqwyWaHfAdGfk48PovDKTx0ZTvXZKYGXZhxGCYSlG2CE6Y6RDvnEl6Tk8e+LqUohkcSOwxrRwUoyxSnUaavdGohXxDT8MJlfWOXgr2u+KsRrriZqp3l6Fdsnk4IGvy6pXpy42L1HYQyyVu9XyJilR2JTbC6eCp5f8p26093m1Qas49+t6vYb0VLqQe12dO+Jm3v4uztSS5pPQzS7PFyjEYd2Rdb6ijsdbsy1074S4q7G9Sz+T3RsPUwYEJ07lzez8cxP64dtj5j94RL8m35A1Fb1OE8hHN+4c1yLG1gudfXbem+fUhi2eqhJrzQo5vsvDv1xS5x5GIS5ZHgKHCsWcW1Tv+dsFkrhaup3uU6VkOuc9UN+7VPsGEY7NvquGpTm8O1CnGJRzuJg6nbYRGj8ORwDpI0KmrExx6akV92P72fMC/I5TCgbSQSZn370H3Jj40gz1SM30WAli9M+wFHFd4ddMVY65yxj0NLmrP+m1tvnWdKtNh/RHuoW92d9/UFtiA5IhMf1/3djfsjBq6S9NT1uaLkVkTttqrPYJ7hOql8+g= + secure: lBgpqft5tKMPRGefCPScPLWNKKGPF89kYrGt3RogqZrb9xB9+52bNrHgt0M5H2EQIRW9IC7/RFRXpT/dF4N8CT1hsljSVQxTQxiGazEYPSdEfOJ2CJxqs0smiL5Ck1T8EQeiuqRSM+/RFEDNaTjp+fe4HhSoPhea6TojAXRSzKdmcDLCwSJOujDccz0yMOagibnqfhO6ZsIv1LUUHWBeeUVrmx+3lz6uAqmNIOQ6hn6YTP4HLoEXTN+IIeQGIzXEZwY2Z/OXakiugxeNZOgRlkikT32KXyZ01hOhOdPOWrtv+q9tAAdqUeQmtdfFb3zy2vBr6bJkvplI5Obh/qHTphWA3iOTOoCICFYPhXY/npztwwqG7jFBRsZbWo1zuP92zUji6OoxK0ezkqEQcIhu+qsUERmsuowriNyFJZK8zVRdGc7JGaZvYe1h9k4l44J+VEIXUurKWji8BpL7dxq/ZPZRf2r5P2JqhU1VkGXrNgfze/N7U1Z1oUkHo1g/5InOl8nDN4Ul0oRXm9tezk5vYO/RMs9hphTdzda4iETikVjnXyHScSLWwI0UqF5MQdKBYsOCJM9deirWG2gXXspkW4HPkYUUe1pTCkaqoQ9+fWHcKTeDVT/52iuCsaSOJccOItyQqH/4nS3i3LaEf11DPMKKL58pbkoMD56p9iSrCCs= distributions: release skip_cleanup: true skip_upload_docs: true -- cgit v1.2.3 From e40a6035d9e688d5a34077132b49c48dc74932f4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 13 Aug 2019 13:39:28 -0400 Subject: Revert "Prefer token for automated releases" This reverts commit 42bd00ada0e0f47c2446d6d1b750eb97eba45640. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 13815fd4..64d0544c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,9 +35,9 @@ jobs: on: tags: true all_branches: true - user: __token__ + user: jaraco password: - secure: lBgpqft5tKMPRGefCPScPLWNKKGPF89kYrGt3RogqZrb9xB9+52bNrHgt0M5H2EQIRW9IC7/RFRXpT/dF4N8CT1hsljSVQxTQxiGazEYPSdEfOJ2CJxqs0smiL5Ck1T8EQeiuqRSM+/RFEDNaTjp+fe4HhSoPhea6TojAXRSzKdmcDLCwSJOujDccz0yMOagibnqfhO6ZsIv1LUUHWBeeUVrmx+3lz6uAqmNIOQ6hn6YTP4HLoEXTN+IIeQGIzXEZwY2Z/OXakiugxeNZOgRlkikT32KXyZ01hOhOdPOWrtv+q9tAAdqUeQmtdfFb3zy2vBr6bJkvplI5Obh/qHTphWA3iOTOoCICFYPhXY/npztwwqG7jFBRsZbWo1zuP92zUji6OoxK0ezkqEQcIhu+qsUERmsuowriNyFJZK8zVRdGc7JGaZvYe1h9k4l44J+VEIXUurKWji8BpL7dxq/ZPZRf2r5P2JqhU1VkGXrNgfze/N7U1Z1oUkHo1g/5InOl8nDN4Ul0oRXm9tezk5vYO/RMs9hphTdzda4iETikVjnXyHScSLWwI0UqF5MQdKBYsOCJM9deirWG2gXXspkW4HPkYUUe1pTCkaqoQ9+fWHcKTeDVT/52iuCsaSOJccOItyQqH/4nS3i3LaEf11DPMKKL58pbkoMD56p9iSrCCs= + secure: tfWrsQMH2bHrWjqnP+08IX1WlkbW94Q30f4d7lCyhWS1FIf/jBDx4jrEILNfMxQ1NCwuBRje5sihj1Ow0BFf0vVrkaeff2IdvnNDEGFduMejaEQJL3s3QrLfpiAvUbtqwyWaHfAdGfk48PovDKTx0ZTvXZKYGXZhxGCYSlG2CE6Y6RDvnEl6Tk8e+LqUohkcSOwxrRwUoyxSnUaavdGohXxDT8MJlfWOXgr2u+KsRrriZqp3l6Fdsnk4IGvy6pXpy42L1HYQyyVu9XyJilR2JTbC6eCp5f8p26093m1Qas49+t6vYb0VLqQe12dO+Jm3v4uztSS5pPQzS7PFyjEYd2Rdb6ijsdbsy1074S4q7G9Sz+T3RsPUwYEJ07lzez8cxP64dtj5j94RL8m35A1Fb1OE8hHN+4c1yLG1gudfXbem+fUhi2eqhJrzQo5vsvDv1xS5x5GIS5ZHgKHCsWcW1Tv+dsFkrhaup3uU6VkOuc9UN+7VPsGEY7NvquGpTm8O1CnGJRzuJg6nbYRGj8ORwDpI0KmrExx6akV92P72fMC/I5TCgbSQSZn370H3Jj40gz1SM30WAli9M+wFHFd4ddMVY65yxj0NLmrP+m1tvnWdKtNh/RHuoW92d9/UFtiA5IhMf1/3djfsjBq6S9NT1uaLkVkTttqrPYJ7hOql8+g= distributions: release skip_cleanup: true skip_upload_docs: true -- cgit v1.2.3 From 05f42a2c14275937250c99478c94b20171d14aeb Mon Sep 17 00:00:00 2001 From: A_Rog Date: Wed, 14 Aug 2019 00:40:12 +0100 Subject: Fixed html sidebars to supported version in Sphinx (#1804) --- .travis.yml | 2 ++ changelog.d/1565.misc.rst | 2 ++ docs/conf.py | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 changelog.d/1565.misc.rst diff --git a/.travis.yml b/.travis.yml index 64d0544c..8441261d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,8 @@ jobs: - <<: *latest_py3 env: LANG=C - python: 3.8-dev + - <<: *latest_py3 + env: TOXENV=docs DISABLE_COVERAGE=1 - <<: *default_py stage: deploy (to PyPI for tagged commits) if: tag IS present diff --git a/changelog.d/1565.misc.rst b/changelog.d/1565.misc.rst new file mode 100644 index 00000000..ca15573a --- /dev/null +++ b/changelog.d/1565.misc.rst @@ -0,0 +1,2 @@ +Changed html_sidebars from string to list of string as per +https://www.sphinx-doc.org/en/master/changes.html#id58 diff --git a/docs/conf.py b/docs/conf.py index c7eb6d3f..cbd19fb4 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -69,7 +69,7 @@ html_theme_path = ['_theme'] html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -html_sidebars = {'index': 'indexsidebar.html'} +html_sidebars = {'index': ['relations.html', 'sourcelink.html', 'indexsidebar.html', 'searchbox.html']} # If false, no module index is generated. html_use_modindex = False -- cgit v1.2.3 From eb7436b36f9967d1becd2b822da548bd59b35d05 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Mon, 8 Jul 2019 09:32:21 -0700 Subject: Fix some usage of deprecated `imp` module --- changelog.d/479.change.rst | 1 + setuptools/command/build_ext.py | 10 ++++++++-- setuptools/command/install_lib.py | 6 +++--- 3 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 changelog.d/479.change.rst diff --git a/changelog.d/479.change.rst b/changelog.d/479.change.rst new file mode 100644 index 00000000..d494c0fc --- /dev/null +++ b/changelog.d/479.change.rst @@ -0,0 +1 @@ +Remove some usage of the deprecated ``imp`` module. diff --git a/setuptools/command/build_ext.py b/setuptools/command/build_ext.py index 60a8a32f..daa8e4fe 100644 --- a/setuptools/command/build_ext.py +++ b/setuptools/command/build_ext.py @@ -1,7 +1,6 @@ import os import sys import itertools -import imp from distutils.command.build_ext import build_ext as _du_build_ext from distutils.file_util import copy_file from distutils.ccompiler import new_compiler @@ -12,6 +11,13 @@ from distutils import log from setuptools.extension import Library from setuptools.extern import six +if six.PY2: + import imp + + EXTENSION_SUFFIXES = [s for s, _, tp in imp.get_suffixes() if tp == imp.C_EXTENSION] +else: + from importlib.machinery import EXTENSION_SUFFIXES + try: # Attempt to use Cython for building extensions, if available from Cython.Distutils.build_ext import build_ext as _build_ext @@ -64,7 +70,7 @@ if_dl = lambda s: s if have_rtld else '' def get_abi3_suffix(): """Return the file extension for an abi3-compliant Extension()""" - for suffix, _, _ in (s for s in imp.get_suffixes() if s[2] == imp.C_EXTENSION): + for suffix in EXTENSION_SUFFIXES: if '.abi3' in suffix: # Unix return suffix elif suffix == '.pyd': # Windows diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index 2b31c3e3..07d65933 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -1,5 +1,5 @@ import os -import imp +import sys from itertools import product, starmap import distutils.command.install_lib as orig @@ -74,10 +74,10 @@ class install_lib(orig.install_lib): yield '__init__.pyc' yield '__init__.pyo' - if not hasattr(imp, 'get_tag'): + if not hasattr(sys, 'implementation'): return - base = os.path.join('__pycache__', '__init__.' + imp.get_tag()) + base = os.path.join('__pycache__', '__init__.' + sys.implementation.cache_tag) yield base + '.pyc' yield base + '.pyo' yield base + '.opt-1.pyc' -- cgit v1.2.3 From 35233197be40eafa1e81d71aedeb82af1a761f54 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 21 Aug 2019 04:49:30 -0400 Subject: Once again, use token for cutting releases. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8441261d..8b7cece8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,9 +37,9 @@ jobs: on: tags: true all_branches: true - user: jaraco + user: __token__ password: - secure: tfWrsQMH2bHrWjqnP+08IX1WlkbW94Q30f4d7lCyhWS1FIf/jBDx4jrEILNfMxQ1NCwuBRje5sihj1Ow0BFf0vVrkaeff2IdvnNDEGFduMejaEQJL3s3QrLfpiAvUbtqwyWaHfAdGfk48PovDKTx0ZTvXZKYGXZhxGCYSlG2CE6Y6RDvnEl6Tk8e+LqUohkcSOwxrRwUoyxSnUaavdGohXxDT8MJlfWOXgr2u+KsRrriZqp3l6Fdsnk4IGvy6pXpy42L1HYQyyVu9XyJilR2JTbC6eCp5f8p26093m1Qas49+t6vYb0VLqQe12dO+Jm3v4uztSS5pPQzS7PFyjEYd2Rdb6ijsdbsy1074S4q7G9Sz+T3RsPUwYEJ07lzez8cxP64dtj5j94RL8m35A1Fb1OE8hHN+4c1yLG1gudfXbem+fUhi2eqhJrzQo5vsvDv1xS5x5GIS5ZHgKHCsWcW1Tv+dsFkrhaup3uU6VkOuc9UN+7VPsGEY7NvquGpTm8O1CnGJRzuJg6nbYRGj8ORwDpI0KmrExx6akV92P72fMC/I5TCgbSQSZn370H3Jj40gz1SM30WAli9M+wFHFd4ddMVY65yxj0NLmrP+m1tvnWdKtNh/RHuoW92d9/UFtiA5IhMf1/3djfsjBq6S9NT1uaLkVkTttqrPYJ7hOql8+g= + secure: FSp9KU+pdvWPxBOaxe6BNmcJ9y8259G3/NdTJ00r0qx/xMLpSneGjpuLqoD6BL2JoM6gRwurwakWoH/9Ah+Di7afETjMnL6WJKtDZ+Uu3YLx3ss7/FlhVz6zmVTaDJUzuo9dGr//qLBQTIxVjGYfQelRJyfMAXtrYWdeT/4489E45lMw+86Z/vnSBOxs4lWekeQW5Gem0cDViWu67RRiGkAEvrYVwuImMr2Dyhpv+l/mQGQIS/ezXuAEFToE6+q8VUVe/aK498Qovdc+O4M7OYk1JouFpffZ3tVZ6iWHQFcR11480UdI6VCIcFpPvGC/J8MWUWLjq7YOm0X9jPXgdYMUQLAP4clFgUr2qNoRSKWfuQlNdVVuS2htYcjJ3eEl90FhcIZKp+WVMrypRPOQJ8CBielZEs0dhytRrZSaJC1BNq25O/BPzws8dL8hYtoXsM6I3Zv5cZgdyqyq/eOEMCX7Cetv6do0U41VGEV5UohvyyuwH5l9GCuPREpY3sXayPg8fw7XcPjvvzSVyjcUT/ePW8sfnAyWZnngjweAn6dK8IFGPuSPQdlos78uxeUOvCVUW0xv/0m4lX73yoHdVVdLbu1MJTyibFGec86Bew9JqIcDlhHaIJ9ihZ9Z9tOtvp1cuNyKYE4kvmOtumDDicEw4DseYn2z5sZDTYTBsKY= distributions: release skip_cleanup: true skip_upload_docs: true -- cgit v1.2.3 From a3e6e68365079642d8949b26ecb810751cc15ef1 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 21 Aug 2019 04:50:43 -0400 Subject: =?UTF-8?q?Bump=20version:=2041.1.0=20=E2=86=92=2041.2.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- CHANGES.rst | 8 ++++++++ changelog.d/1565.misc.rst | 2 -- changelog.d/479.change.rst | 1 - setup.cfg | 2 +- 5 files changed, 10 insertions(+), 5 deletions(-) delete mode 100644 changelog.d/1565.misc.rst delete mode 100644 changelog.d/479.change.rst diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 5a453660..5e7e8ee4 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 41.1.0 +current_version = 41.2.0 commit = True tag = True diff --git a/CHANGES.rst b/CHANGES.rst index 9f9603c0..84007b31 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,11 @@ +v41.2.0 +------- + +* #479: Remove some usage of the deprecated ``imp`` module. +* #1565: Changed html_sidebars from string to list of string as per + https://www.sphinx-doc.org/en/master/changes.html#id58 + + v41.1.0 ------- diff --git a/changelog.d/1565.misc.rst b/changelog.d/1565.misc.rst deleted file mode 100644 index ca15573a..00000000 --- a/changelog.d/1565.misc.rst +++ /dev/null @@ -1,2 +0,0 @@ -Changed html_sidebars from string to list of string as per -https://www.sphinx-doc.org/en/master/changes.html#id58 diff --git a/changelog.d/479.change.rst b/changelog.d/479.change.rst deleted file mode 100644 index d494c0fc..00000000 --- a/changelog.d/479.change.rst +++ /dev/null @@ -1 +0,0 @@ -Remove some usage of the deprecated ``imp`` module. diff --git a/setup.cfg b/setup.cfg index 3bcf4429..96792dd3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -19,7 +19,7 @@ universal = 1 [metadata] name = setuptools -version = 41.1.0 +version = 41.2.0 description = Easily download, build, install, upgrade, and uninstall Python packages author = Python Packaging Authority author_email = distutils-sig@python.org -- cgit v1.2.3 From 04940b6e09bb5054666442196383c2fe9e5a09a2 Mon Sep 17 00:00:00 2001 From: anatoly techtonik Date: Tue, 3 Sep 2019 21:36:49 +0300 Subject: Fix typo in CHANGES.rst --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 84007b31..dd47cb43 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -12,7 +12,7 @@ v41.1.0 * #1697: Moved most of the constants from setup.py to setup.cfg * #1749: Fixed issue with the PEP 517 backend where building a source distribution would fail if any tarball existed in the destination directory. * #1750: Fixed an issue with PEP 517 backend where wheel builds would fail if the destination directory did not already exist. -* #1756: Forse metadata-version >= 1.2. when project urls are present. +* #1756: Force metadata-version >= 1.2. when project urls are present. * #1769: Improve ``package_data`` check: ensure the dictionary values are lists/tuples of strings. * #1788: Changed compatibility fallback logic for ``html.unescape`` to avoid accessing ``HTMLParser.unescape`` when not necessary. ``HTMLParser.unescape`` is deprecated and will be removed in Python 3.9. * #1790: Added the file path to the error message when a ``UnicodeDecodeError`` occurs while reading a metadata file. -- cgit v1.2.3 From ca0ee009f81a460b483c7e451e58dfdcd7787045 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 11 Sep 2019 16:39:57 +0100 Subject: Add test capturing failure. Ref #1787. --- setuptools/tests/test_config.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/setuptools/tests/test_config.py b/setuptools/tests/test_config.py index bc97664d..42187138 100644 --- a/setuptools/tests/test_config.py +++ b/setuptools/tests/test_config.py @@ -819,6 +819,18 @@ class TestOptions: ] assert sorted(dist.data_files) == sorted(expected) + def test_python_requires_invalid(self, tmpdir): + fake_env( + tmpdir, + DALS(""" + [options] + python_requires=invalid + """), + ) + with pytest.raises(DistutilsOptionError): + with get_dist(tmpdir) as dist: + dist.parse_config_files() + saved_dist_init = _Distribution.__init__ -- cgit v1.2.3 From b31777cd50c7cb59b4ef6c22bd014f0229ef32fa Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 11 Sep 2019 16:52:58 +0100 Subject: Add more tests for valid behavior. Expand exception, any should do. --- setuptools/tests/test_config.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/setuptools/tests/test_config.py b/setuptools/tests/test_config.py index 42187138..1b94a586 100644 --- a/setuptools/tests/test_config.py +++ b/setuptools/tests/test_config.py @@ -819,6 +819,28 @@ class TestOptions: ] assert sorted(dist.data_files) == sorted(expected) + def test_python_requires_simple(self, tmpdir): + fake_env( + tmpdir, + DALS(""" + [options] + python_requires=>=2.7 + """), + ) + with get_dist(tmpdir) as dist: + dist.parse_config_files() + + def test_python_requires_compound(self, tmpdir): + fake_env( + tmpdir, + DALS(""" + [options] + python_requires=>=2.7,!=3.0.* + """), + ) + with get_dist(tmpdir) as dist: + dist.parse_config_files() + def test_python_requires_invalid(self, tmpdir): fake_env( tmpdir, @@ -827,7 +849,7 @@ class TestOptions: python_requires=invalid """), ) - with pytest.raises(DistutilsOptionError): + with pytest.raises(Exception): with get_dist(tmpdir) as dist: dist.parse_config_files() -- cgit v1.2.3 From c3df086ed3570e7065e6935a52d95c8cdef2b071 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 11 Sep 2019 16:54:07 +0100 Subject: Ensure that python_requires is checked during option processing. Fixes #1787. --- setuptools/config.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setuptools/config.py b/setuptools/config.py index b6626043..2d50e25e 100644 --- a/setuptools/config.py +++ b/setuptools/config.py @@ -12,6 +12,7 @@ from importlib import import_module from distutils.errors import DistutilsOptionError, DistutilsFileError from setuptools.extern.packaging.version import LegacyVersion, parse +from setuptools.extern.packaging.specifiers import SpecifierSet from setuptools.extern.six import string_types, PY3 @@ -554,6 +555,7 @@ class ConfigOptionsHandler(ConfigHandler): 'packages': self._parse_packages, 'entry_points': self._parse_file, 'py_modules': parse_list, + 'python_requires': SpecifierSet, } def _parse_packages(self, value): -- cgit v1.2.3 From 895d18c17d15f443c6d8953a176aa6c4df354c7d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 11 Sep 2019 16:55:09 +0100 Subject: Update changelog. Ref #1787. --- changelog.d/1847.change.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/1847.change.rst diff --git a/changelog.d/1847.change.rst b/changelog.d/1847.change.rst new file mode 100644 index 00000000..2a6b9c77 --- /dev/null +++ b/changelog.d/1847.change.rst @@ -0,0 +1 @@ +Now traps errors when invalid ``python_requires`` values are supplied. -- cgit v1.2.3 From 45b83cd189db31a0315a4297053feab77d8618b4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 11 Sep 2019 18:14:53 +0100 Subject: Update changelog. Ref #1690. --- changelog.d/1690.change.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/1690.change.rst diff --git a/changelog.d/1690.change.rst b/changelog.d/1690.change.rst new file mode 100644 index 00000000..ecc51c55 --- /dev/null +++ b/changelog.d/1690.change.rst @@ -0,0 +1 @@ +When storing extras, rely on OrderedSet to retain order of extras as indicated by the packager, which will also be deterministic on Python 2.7 (with PYTHONHASHSEED unset) and Python 3.6+. -- cgit v1.2.3 From 6f962a07f586162d05e087a90ea8f44461772070 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 6 Oct 2019 20:42:14 -0400 Subject: Refresh vendored packages (ordereddict 3.1.1) --- setuptools/_vendor/ordered_set.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/_vendor/ordered_set.py b/setuptools/_vendor/ordered_set.py index d257470b..14876000 100644 --- a/setuptools/_vendor/ordered_set.py +++ b/setuptools/_vendor/ordered_set.py @@ -87,14 +87,14 @@ class OrderedSet(MutableSet, Sequence): """ if isinstance(index, slice) and index == SLICE_ALL: return self.copy() + elif is_iterable(index): + return [self.items[i] for i in index] elif hasattr(index, "__index__") or isinstance(index, slice): result = self.items[index] if isinstance(result, list): return self.__class__(result) else: return result - elif is_iterable(index): - return [self.items[i] for i in index] else: raise TypeError("Don't know how to index an OrderedSet by %r" % index) -- cgit v1.2.3 From 53d662a9de0b8d449d167bf1c5cf291a2fecb094 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 6 Oct 2019 21:17:53 -0400 Subject: Allow 'long_description_content_type' warnings for new versions of packaging. Fixes #1858. --- changelog.d/1858.misc.rst | 1 + setuptools/tests/test_integration.py | 1 + 2 files changed, 2 insertions(+) create mode 100644 changelog.d/1858.misc.rst diff --git a/changelog.d/1858.misc.rst b/changelog.d/1858.misc.rst new file mode 100644 index 00000000..b16ac1dd --- /dev/null +++ b/changelog.d/1858.misc.rst @@ -0,0 +1 @@ +Fixed failing integration test triggered by 'long_description_content_type' in packaging. diff --git a/setuptools/tests/test_integration.py b/setuptools/tests/test_integration.py index 1e132188..1c0b2b18 100644 --- a/setuptools/tests/test_integration.py +++ b/setuptools/tests/test_integration.py @@ -143,6 +143,7 @@ def test_build_deps_on_distutils(request, tmpdir_factory, build_dep): 'tests_require', 'python_requires', 'install_requires', + 'long_description_content_type', ] assert not match or match.group(1).strip('"\'') in allowed_unknowns -- cgit v1.2.3 From da3ccf5f648a5836ce5e9b0747a263860ae1dfaa Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 6 Oct 2019 21:22:05 -0400 Subject: =?UTF-8?q?Bump=20version:=2041.2.0=20=E2=86=92=2041.3.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- CHANGES.rst | 7 +++++++ changelog.d/1690.change.rst | 1 - changelog.d/1858.misc.rst | 1 - setup.cfg | 2 +- 5 files changed, 9 insertions(+), 4 deletions(-) delete mode 100644 changelog.d/1690.change.rst delete mode 100644 changelog.d/1858.misc.rst diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 5e7e8ee4..37b22446 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 41.2.0 +current_version = 41.3.0 commit = True tag = True diff --git a/CHANGES.rst b/CHANGES.rst index dd47cb43..883f4f2b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,10 @@ +v41.3.0 +------- + +* #1690: When storing extras, rely on OrderedSet to retain order of extras as indicated by the packager, which will also be deterministic on Python 2.7 (with PYTHONHASHSEED unset) and Python 3.6+. +* #1858: Fixed failing integration test triggered by 'long_description_content_type' in packaging. + + v41.2.0 ------- diff --git a/changelog.d/1690.change.rst b/changelog.d/1690.change.rst deleted file mode 100644 index ecc51c55..00000000 --- a/changelog.d/1690.change.rst +++ /dev/null @@ -1 +0,0 @@ -When storing extras, rely on OrderedSet to retain order of extras as indicated by the packager, which will also be deterministic on Python 2.7 (with PYTHONHASHSEED unset) and Python 3.6+. diff --git a/changelog.d/1858.misc.rst b/changelog.d/1858.misc.rst deleted file mode 100644 index b16ac1dd..00000000 --- a/changelog.d/1858.misc.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed failing integration test triggered by 'long_description_content_type' in packaging. diff --git a/setup.cfg b/setup.cfg index 96792dd3..77a35de0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -19,7 +19,7 @@ universal = 1 [metadata] name = setuptools -version = 41.2.0 +version = 41.3.0 description = Easily download, build, install, upgrade, and uninstall Python packages author = Python Packaging Authority author_email = distutils-sig@python.org -- cgit v1.2.3 From 2e3c34f669c5272d036ef7edc58871c96663d587 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 6 Oct 2019 21:29:32 -0400 Subject: Clarify the scope of the change. --- changelog.d/1847.change.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/1847.change.rst b/changelog.d/1847.change.rst index 2a6b9c77..d3f7724e 100644 --- a/changelog.d/1847.change.rst +++ b/changelog.d/1847.change.rst @@ -1 +1 @@ -Now traps errors when invalid ``python_requires`` values are supplied. +In declarative config, now traps errors when invalid ``python_requires`` values are supplied. -- cgit v1.2.3 From 5eee6b4b523a6d2ae16ef913c01302f951b4f614 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 6 Oct 2019 21:30:46 -0400 Subject: =?UTF-8?q?Bump=20version:=2041.3.0=20=E2=86=92=2041.4.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- CHANGES.rst | 6 ++++++ changelog.d/1847.change.rst | 1 - setup.cfg | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) delete mode 100644 changelog.d/1847.change.rst diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 37b22446..d6768cb8 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 41.3.0 +current_version = 41.4.0 commit = True tag = True diff --git a/CHANGES.rst b/CHANGES.rst index 883f4f2b..ecde25a5 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,9 @@ +v41.4.0 +------- + +* #1847: In declarative config, now traps errors when invalid ``python_requires`` values are supplied. + + v41.3.0 ------- diff --git a/changelog.d/1847.change.rst b/changelog.d/1847.change.rst deleted file mode 100644 index d3f7724e..00000000 --- a/changelog.d/1847.change.rst +++ /dev/null @@ -1 +0,0 @@ -In declarative config, now traps errors when invalid ``python_requires`` values are supplied. diff --git a/setup.cfg b/setup.cfg index 77a35de0..a55106a5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -19,7 +19,7 @@ universal = 1 [metadata] name = setuptools -version = 41.3.0 +version = 41.4.0 description = Easily download, build, install, upgrade, and uninstall Python packages author = Python Packaging Authority author_email = distutils-sig@python.org -- cgit v1.2.3 From 026f9b75544c53636fd692af386730553740a511 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Wed, 14 Aug 2019 02:43:53 +0200 Subject: docs: mention dependency links support was dropped in pip 19.0 --- docs/setuptools.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/setuptools.txt b/docs/setuptools.txt index 2e7fe3bd..8cfb5f13 100644 --- a/docs/setuptools.txt +++ b/docs/setuptools.txt @@ -675,6 +675,10 @@ using ``setup.py develop``.) Dependencies that aren't in PyPI -------------------------------- +.. warning:: + Dependency links support has been dropped by pip starting with version + 19.0 (released 2019-01-22). + If your project depends on packages that don't exist on PyPI, you may still be able to depend on them, as long as they are available for download as: -- cgit v1.2.3 From d2db805b008346ba9aa34d8fb36faf2d019eed64 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Wed, 14 Aug 2019 02:44:20 +0200 Subject: docs: mention eggs are deprecated and not supported by pip --- docs/setuptools.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/setuptools.txt b/docs/setuptools.txt index 8cfb5f13..26a3044e 100644 --- a/docs/setuptools.txt +++ b/docs/setuptools.txt @@ -1693,6 +1693,9 @@ file locations. ``bdist_egg`` - Create a Python Egg for the project =================================================== +.. warning:: + **eggs** are deprecated in favor of wheels, and not supported by pip. + This command generates a Python Egg (``.egg`` file) for the project. Python Eggs are the preferred binary distribution format for EasyInstall, because they are cross-platform (for "pure" packages), directly importable, and contain -- cgit v1.2.3 From 8b3a8d08da9780d16dce7d62433f35dbb4cc55ad Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Mon, 7 Oct 2019 18:58:40 +0200 Subject: add news entry --- changelog.d/1860.doc.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/1860.doc.rst diff --git a/changelog.d/1860.doc.rst b/changelog.d/1860.doc.rst new file mode 100644 index 00000000..f3554643 --- /dev/null +++ b/changelog.d/1860.doc.rst @@ -0,0 +1 @@ +Update documentation to mention the egg format is not supported by pip and dependency links support was dropped starting with pip 19.0. -- cgit v1.2.3 From 734d09c5a3f48338b6a3d7687c5f9d0ed02ab479 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 7 Oct 2019 16:36:54 -0400 Subject: Pin ordered-set to current version for consistency. --- setuptools/_vendor/vendored.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/_vendor/vendored.txt b/setuptools/_vendor/vendored.txt index 379aae56..5731b424 100644 --- a/setuptools/_vendor/vendored.txt +++ b/setuptools/_vendor/vendored.txt @@ -1,4 +1,4 @@ packaging==16.8 pyparsing==2.2.1 six==1.10.0 -ordered-set +ordered-set==3.1.1 -- cgit v1.2.3 From cb8769d7d1a694d37194c44b98c543b2d5d38fc5 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Wed, 26 Jun 2019 22:25:03 +0200 Subject: minor cleanup --- setuptools/command/easy_install.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 06c98271..d7b7566c 100644 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -1180,8 +1180,7 @@ class easy_install(Command): # to the setup.cfg file. ei_opts = self.distribution.get_option_dict('easy_install').copy() fetch_directives = ( - 'find_links', 'site_dirs', 'index_url', 'optimize', - 'site_dirs', 'allow_hosts', + 'find_links', 'site_dirs', 'index_url', 'optimize', 'allow_hosts', ) fetch_options = {} for key, val in ei_opts.items(): -- cgit v1.2.3 From 6a73945462a7e73168be53e377e4110a5dc89fb9 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Wed, 14 Aug 2019 00:49:50 +0200 Subject: tests: drop (easy_install based) manual tests --- tests/manual_test.py | 100 --------------------------------------------------- 1 file changed, 100 deletions(-) delete mode 100644 tests/manual_test.py diff --git a/tests/manual_test.py b/tests/manual_test.py deleted file mode 100644 index 99db4b01..00000000 --- a/tests/manual_test.py +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env python - -import sys -import os -import shutil -import tempfile -import subprocess -from distutils.command.install import INSTALL_SCHEMES -from string import Template - -from setuptools.extern.six.moves import urllib - - -def _system_call(*args): - assert subprocess.call(args) == 0 - - -def tempdir(func): - def _tempdir(*args, **kwargs): - test_dir = tempfile.mkdtemp() - old_dir = os.getcwd() - os.chdir(test_dir) - try: - return func(*args, **kwargs) - finally: - os.chdir(old_dir) - shutil.rmtree(test_dir) - - return _tempdir - - -SIMPLE_BUILDOUT = """\ -[buildout] - -parts = eggs - -[eggs] -recipe = zc.recipe.egg - -eggs = - extensions -""" - -BOOTSTRAP = 'http://downloads.buildout.org/1/bootstrap.py' -PYVER = sys.version.split()[0][:3] - -_VARS = {'base': '.', - 'py_version_short': PYVER} - -scheme = 'nt' if sys.platform == 'win32' else 'unix_prefix' -PURELIB = INSTALL_SCHEMES[scheme]['purelib'] - - -@tempdir -def test_virtualenv(): - """virtualenv with setuptools""" - purelib = os.path.abspath(Template(PURELIB).substitute(**_VARS)) - _system_call('virtualenv', '--no-site-packages', '.') - _system_call('bin/easy_install', 'setuptools==dev') - # linux specific - site_pkg = os.listdir(purelib) - site_pkg.sort() - assert 'setuptools' in site_pkg[0] - easy_install = os.path.join(purelib, 'easy-install.pth') - with open(easy_install) as f: - res = f.read() - assert 'setuptools' in res - - -@tempdir -def test_full(): - """virtualenv + pip + buildout""" - _system_call('virtualenv', '--no-site-packages', '.') - _system_call('bin/easy_install', '-q', 'setuptools==dev') - _system_call('bin/easy_install', '-qU', 'setuptools==dev') - _system_call('bin/easy_install', '-q', 'pip') - _system_call('bin/pip', 'install', '-q', 'zc.buildout') - - with open('buildout.cfg', 'w') as f: - f.write(SIMPLE_BUILDOUT) - - with open('bootstrap.py', 'w') as f: - f.write(urllib.request.urlopen(BOOTSTRAP).read()) - - _system_call('bin/python', 'bootstrap.py') - _system_call('bin/buildout', '-q') - eggs = os.listdir('eggs') - eggs.sort() - 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', - ] - - -if __name__ == '__main__': - test_virtualenv() - test_full() -- cgit v1.2.3 From d89682fcba90595d5d6aaf071d6efcc815bceba8 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Mon, 21 Oct 2019 16:49:13 -0700 Subject: Change coding cookie to use utf-8 (lowercase) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While perfectly valid, the encoding 'UTF-8' (uppercase) is not recognized by the Emacs MULE system. As such, it displays the following warning when opening a file with it used as an encoding cookie: Warning (mule): Invalid coding system ‘UTF-8’ is specified for the current buffer/file by the :coding tag. It is highly recommended to fix it before writing to a file. Some discussion of this can be found at: https://stackoverflow.com/questions/14031724/how-to-make-emacs-accept-utf-8-uppercase-encoding While the post does offer a workaround for Emacs users, rather than ask all to implement it, use the more typical utf-8 (lowercase). --- setuptools/tests/test_config.py | 2 +- setuptools/tests/test_test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/setuptools/tests/test_config.py b/setuptools/tests/test_config.py index 1b94a586..69d8d00d 100644 --- a/setuptools/tests/test_config.py +++ b/setuptools/tests/test_config.py @@ -1,4 +1,4 @@ -# -*- coding: UTF-8 -*- +# -*- coding: utf-8 -*- from __future__ import unicode_literals import contextlib diff --git a/setuptools/tests/test_test.py b/setuptools/tests/test_test.py index faaa6ba9..3415913b 100644 --- a/setuptools/tests/test_test.py +++ b/setuptools/tests/test_test.py @@ -1,4 +1,4 @@ -# -*- coding: UTF-8 -*- +# -*- coding: utf-8 -*- from __future__ import unicode_literals -- cgit v1.2.3 From cd84510713ada48bf33d4efa749c2952e3fc1a49 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sat, 19 Oct 2019 08:39:30 -0700 Subject: Deprecate the test command Provide a warning to users. Suggest using tox as an alternative generic entry point. Refs #1684 --- changelog.d/1878.change.rst | 1 + docs/setuptools.txt | 13 +++++++++++ setuptools/command/test.py | 10 ++++++++- setuptools/tests/test_test.py | 50 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 changelog.d/1878.change.rst diff --git a/changelog.d/1878.change.rst b/changelog.d/1878.change.rst new file mode 100644 index 00000000..0774b5d3 --- /dev/null +++ b/changelog.d/1878.change.rst @@ -0,0 +1 @@ +Formally deprecated the ``test`` command, with the recommendation that users migrate to ``tox``. diff --git a/docs/setuptools.txt b/docs/setuptools.txt index 26a3044e..f69b75c2 100644 --- a/docs/setuptools.txt +++ b/docs/setuptools.txt @@ -346,6 +346,8 @@ unless you need the associated ``setuptools`` feature. specified test suite, e.g. via ``setup.py test``. See the section on the `test`_ command below for more details. + New in 41.5.0: Deprecated the test command. + ``tests_require`` If your project's tests need one or more additional packages besides those needed to install it, you can use this option to specify them. It should @@ -357,6 +359,8 @@ unless you need the associated ``setuptools`` feature. are run, but only downloaded to the project's setup directory if they're not already installed locally. + New in 41.5.0: Deprecated the test command. + .. _test_loader: ``test_loader`` @@ -380,6 +384,8 @@ unless you need the associated ``setuptools`` feature. as long as you use the ``tests_require`` option to ensure that the package containing the loader class is available when the ``test`` command is run. + New in 41.5.0: Deprecated the test command. + ``eager_resources`` A list of strings naming resources that should be extracted together, if any of them is needed, or if any C extensions included in the project are @@ -2142,6 +2148,11 @@ distutils configuration file the option will be added to (or removed from). ``test`` - Build package and run a unittest suite ================================================= +.. warning:: + ``test`` is deprecated and will be removed in a future version. Users + looking for a generic test entry point independent of test runner are + encouraged to use `tox `_. + When doing test-driven development, or running automated builds that need testing before they are deployed for downloading or use, it's often useful to be able to run a project's unit tests without actually deploying the project @@ -2187,6 +2198,8 @@ available: If you did not set a ``test_suite`` in your ``setup()`` call, and do not provide a ``--test-suite`` option, an error will occur. +New in 41.5.0: Deprecated the test command. + .. _upload: diff --git a/setuptools/command/test.py b/setuptools/command/test.py index 973e4eb2..c148b38d 100644 --- a/setuptools/command/test.py +++ b/setuptools/command/test.py @@ -74,7 +74,7 @@ class NonDataProperty: class test(Command): """Command to run unit tests after in-place build""" - description = "run unit tests after in-place build" + description = "run unit tests after in-place build (deprecated)" user_options = [ ('test-module=', 'm', "Run 'test_suite' in specified module"), @@ -214,6 +214,14 @@ class test(Command): return itertools.chain(ir_d, tr_d, er_d) def run(self): + self.announce( + "WARNING: Testing via this command is deprecated and will be " + "removed in a future version. Users looking for a generic test " + "entry point independent of test runner are encouraged to use " + "tox.", + log.WARN, + ) + installed_dists = self.install_dists(self.distribution) cmd = ' '.join(self._argv) diff --git a/setuptools/tests/test_test.py b/setuptools/tests/test_test.py index faaa6ba9..382bd640 100644 --- a/setuptools/tests/test_test.py +++ b/setuptools/tests/test_test.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals +import mock from distutils import log import os @@ -124,3 +125,52 @@ def test_tests_are_run_once(capfd): cmd.run() out, err = capfd.readouterr() assert out == 'Foo\n' + + +@pytest.mark.usefixtures('sample_test') +def test_warns_deprecation(capfd): + params = dict( + name='foo', + packages=['name', 'name.space', 'name.space.tests'], + namespace_packages=['name'], + test_suite='name.space.tests.test_suite', + use_2to3=True + ) + dist = Distribution(params) + dist.script_name = 'setup.py' + cmd = test(dist) + cmd.ensure_finalized() + cmd.announce = mock.Mock() + cmd.run() + capfd.readouterr() + msg = ( + "WARNING: Testing via this command is deprecated and will be " + "removed in a future version. Users looking for a generic test " + "entry point independent of test runner are encouraged to use " + "tox." + ) + cmd.announce.assert_any_call(msg, log.WARN) + + +@pytest.mark.usefixtures('sample_test') +def test_deprecation_stderr(capfd): + params = dict( + name='foo', + packages=['name', 'name.space', 'name.space.tests'], + namespace_packages=['name'], + test_suite='name.space.tests.test_suite', + use_2to3=True + ) + dist = Distribution(params) + dist.script_name = 'setup.py' + cmd = test(dist) + cmd.ensure_finalized() + cmd.run() + out, err = capfd.readouterr() + msg = ( + "WARNING: Testing via this command is deprecated and will be " + "removed in a future version. Users looking for a generic test " + "entry point independent of test runner are encouraged to use " + "tox.\n" + ) + assert msg in err -- cgit v1.2.3 From 4069e0b536802a47c8c15ce839fd98a5f4c84620 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Mon, 21 Oct 2019 17:01:18 -0700 Subject: Remove outdated comment and suppressed exception from test_test.py The test command has not called sys.exit since commit 2c4fd43277fc477d85b50e15c37b176136676270. --- setuptools/tests/test_test.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/setuptools/tests/test_test.py b/setuptools/tests/test_test.py index 280c837b..6242a018 100644 --- a/setuptools/tests/test_test.py +++ b/setuptools/tests/test_test.py @@ -86,9 +86,7 @@ def test_test(capfd): dist.script_name = 'setup.py' cmd = test(dist) cmd.ensure_finalized() - # The test runner calls sys.exit - with contexts.suppress_exceptions(SystemExit): - cmd.run() + cmd.run() out, err = capfd.readouterr() assert out == 'Foo\n' @@ -120,9 +118,7 @@ def test_tests_are_run_once(capfd): dist.script_name = 'setup.py' cmd = test(dist) cmd.ensure_finalized() - # The test runner calls sys.exit - with contexts.suppress_exceptions(SystemExit): - cmd.run() + cmd.run() out, err = capfd.readouterr() assert out == 'Foo\n' -- cgit v1.2.3 From e4ef537525c2b1d120497379da9484c33ea3d773 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Mon, 21 Oct 2019 17:51:26 -0700 Subject: Add a trove classifier to document support for Python 3.8 --- changelog.d/1884.doc.rst | 1 + setup.cfg | 1 + 2 files changed, 2 insertions(+) create mode 100644 changelog.d/1884.doc.rst diff --git a/changelog.d/1884.doc.rst b/changelog.d/1884.doc.rst new file mode 100644 index 00000000..45615d5d --- /dev/null +++ b/changelog.d/1884.doc.rst @@ -0,0 +1 @@ +Added a trove classifier to document support for Python 3.8. diff --git a/setup.cfg b/setup.cfg index a55106a5..373ae8b5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -42,6 +42,7 @@ classifiers = Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 Topic :: Software Development :: Libraries :: Python Modules Topic :: System :: Archiving :: Packaging Topic :: System :: Systems Administration -- cgit v1.2.3