From 2063cffefaa644e5948f50eddd524a0df23c8eb0 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 19 Feb 2019 17:52:15 -0500 Subject: Store 'provides_extras' as an ordered list to retain order. --- setuptools/dist.py | 19 ++++++++++--------- setuptools/itertools_recipes.py | 19 +++++++++++++++++++ setuptools/tests/test_dist.py | 2 +- 3 files changed, 30 insertions(+), 10 deletions(-) create mode 100644 setuptools/itertools_recipes.py diff --git a/setuptools/dist.py b/setuptools/dist.py index ddb1787a..f03f3862 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -31,6 +31,7 @@ from setuptools.extern import packaging from setuptools.extern.six.moves import map, filter, filterfalse from . import SetuptoolsDeprecationWarning +from .itertools_recipes import unique_everseen from setuptools.depends import Require from setuptools import windows_support @@ -408,7 +409,7 @@ class Distribution(_Distribution): _DISTUTILS_UNSUPPORTED_METADATA = { 'long_description_content_type': None, 'project_urls': dict, - 'provides_extras': set, + 'provides_extras': list, } _patched_dist = None @@ -493,14 +494,14 @@ class Distribution(_Distribution): if getattr(self, 'python_requires', None): self.metadata.python_requires = self.python_requires - if getattr(self, 'extras_require', None): - for extra in self.extras_require.keys(): - # Since this gets called multiple times at points where the - # keys have become 'converted' extras, ensure that we are only - # truly adding extras we haven't seen before here. - extra = extra.split(':')[0] - if extra: - self.metadata.provides_extras.add(extra) + # Since this gets called multiple times at points where the + # keys have become 'converted' extras, ensure that we are only + # truly adding extras we haven't seen before here. + raw_extra_names = filter(None, unique_everseen( + extra.split(':')[0] + for extra in getattr(self, 'extras_require', None) or {} + )) + self.metadata.provides_extras.extend(raw_extra_names) self._convert_extras_requirements() self._move_install_requirements_markers() diff --git a/setuptools/itertools_recipes.py b/setuptools/itertools_recipes.py new file mode 100644 index 00000000..6b611f64 --- /dev/null +++ b/setuptools/itertools_recipes.py @@ -0,0 +1,19 @@ +from setuptools.extern.six.moves import filterfalse + + +def unique_everseen(iterable, key=None): + "List unique elements, preserving order. Remember all elements ever seen." + # unique_everseen('AAAABBBCCDAABBB') --> A B C D + # unique_everseen('ABBCcAD', str.lower) --> A B C D + seen = set() + seen_add = seen.add + if key is None: + for element in filterfalse(seen.__contains__, iterable): + seen_add(element) + yield element + else: + for element in iterable: + k = key(element) + if k not in seen: + seen_add(k) + yield element diff --git a/setuptools/tests/test_dist.py b/setuptools/tests/test_dist.py index 7409400f..f73eeaea 100644 --- a/setuptools/tests/test_dist.py +++ b/setuptools/tests/test_dist.py @@ -169,7 +169,7 @@ def test_read_metadata(name, attrs): ('requires', dist_class.get_requires), ('classifiers', dist_class.get_classifiers), ('project_urls', lambda s: getattr(s, 'project_urls', {})), - ('provides_extras', lambda s: getattr(s, 'provides_extras', set())), + ('provides_extras', lambda s: getattr(s, 'provides_extras', [])), ] for attr, getter in tested_attrs: -- cgit v1.2.3