From db23abf7ef8422013c2a5151f39bae0238a61804 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 20 Dec 2020 23:34:22 -0500 Subject: Remove use of packaging.version.LegacyVersion. Fixes #2497. --- pkg_resources/__init__.py | 71 ++--------------------------------------------- 1 file changed, 2 insertions(+), 69 deletions(-) diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index 737f4d5f..afe6078c 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -34,7 +34,6 @@ import email.parser import errno import tempfile import textwrap -import itertools import inspect import ntpath import posixpath @@ -108,11 +107,7 @@ class PEP440Warning(RuntimeWarning): """ -def parse_version(v): - try: - return packaging.version.Version(v) - except packaging.version.InvalidVersion: - return packaging.version.LegacyVersion(v) +parse_version = packaging.version.Version _state_vars = {} @@ -2000,32 +1995,6 @@ def find_nothing(importer, path_item, only=False): register_finder(object, find_nothing) -def _by_version_descending(names): - """ - Given a list of filenames, return them in descending order - by version number. - - >>> names = 'bar', 'foo', 'Python-2.7.10.egg', 'Python-2.7.2.egg' - >>> _by_version_descending(names) - ['Python-2.7.10.egg', 'Python-2.7.2.egg', 'foo', 'bar'] - >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.egg' - >>> _by_version_descending(names) - ['Setuptools-1.2.3.egg', 'Setuptools-1.2.3b1.egg'] - >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.post1.egg' - >>> _by_version_descending(names) - ['Setuptools-1.2.3.post1.egg', 'Setuptools-1.2.3b1.egg'] - """ - def _by_version(name): - """ - Parse each component of the filename - """ - name, ext = os.path.splitext(name) - parts = itertools.chain(name.split('-'), [ext]) - return [packaging.version.parse(part) for part in parts] - - return sorted(names, key=_by_version, reverse=True) - - def find_on_path(importer, path_item, only=False): """Yield distributions accessible on a sys.path directory""" path_item = _normalize_cached(path_item) @@ -2043,18 +2012,8 @@ def find_on_path(importer, path_item, only=False): for child in safe_listdir(path_item) ) - # for performance, before sorting by version, - # screen entries for only those that will yield - # distributions - filtered = ( - entry - for entry in entries - if dist_factory(path_item, entry, only) - ) - # scan for .egg and .egg-info in directory - path_item_entries = _by_version_descending(filtered) - for entry in path_item_entries: + for entry in sorted(entries): fullpath = os.path.join(path_item, entry) factory = dist_factory(path_item, entry, only) for dist in factory(fullpath): @@ -2644,32 +2603,6 @@ class Distribution: return self._parsed_version - def _warn_legacy_version(self): - LV = packaging.version.LegacyVersion - is_legacy = isinstance(self._parsed_version, LV) - if not is_legacy: - return - - # While an empty version is technically a legacy version and - # is not a valid PEP 440 version, it's also unlikely to - # actually come from someone and instead it is more likely that - # it comes from setuptools attempting to parse a filename and - # including it in the list. So for that we'll gate this warning - # on if the version is anything at all or not. - if not self.version: - return - - tmpl = textwrap.dedent(""" - '{project_name} ({version})' is being parsed as a legacy, - non PEP 440, - version. You may find odd behavior and sort order. - In particular it will be sorted as less than 0.0. It - is recommended to migrate to PEP 440 compatible - versions. - """).strip().replace('\n', ' ') - - warnings.warn(tmpl.format(**vars(self)), PEP440Warning) - @property def version(self): try: -- cgit v1.2.1 From adf71a781816d61db524441fcce2c097106a73b5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 20 Dec 2020 23:36:23 -0500 Subject: Add changelog. Ref #2497. --- changelog.d/2497.breaking.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/2497.breaking.rst diff --git a/changelog.d/2497.breaking.rst b/changelog.d/2497.breaking.rst new file mode 100644 index 00000000..eef6a5ac --- /dev/null +++ b/changelog.d/2497.breaking.rst @@ -0,0 +1 @@ +Support for PEP 440 non-conforming versions has been removed. Environments containing packages with non-conforming versions may fail or the packages may not be recognized. -- cgit v1.2.1 From 731e1e6c5c7bc73519922847d116ed9ed6833f3b Mon Sep 17 00:00:00 2001 From: Chih-Hsuan Yen Date: Fri, 25 Dec 2020 14:42:42 +0800 Subject: egg_info: avoid non-PEP440 versions from tag_date --- setuptools/command/egg_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py index 0b7ad677..97e10d99 100644 --- a/setuptools/command/egg_info.py +++ b/setuptools/command/egg_info.py @@ -140,7 +140,7 @@ class InfoCommon: if self.tag_build: version += self.tag_build if self.tag_date: - version += time.strftime("-%Y%m%d") + version += time.strftime("%Y%m%d") return version vtags = property(tags) -- cgit v1.2.1 From f7e70d0fbf7488198026631b435b3e7faaf3dab2 Mon Sep 17 00:00:00 2001 From: Chih-Hsuan Yen Date: Fri, 25 Dec 2020 14:45:43 +0800 Subject: package_index: don't create dists with non-PEP440 versions --- setuptools/package_index.py | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index 3979b131..bc0ba7a6 100644 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -152,35 +152,24 @@ def interpret_distro_name( location, basename, metadata, py_version=None, precedence=SOURCE_DIST, platform=None ): - """Generate alternative interpretations of a source distro name + """Generate the interpretation of a source distro name Note: if `location` is a filesystem filename, you should call ``pkg_resources.normalize_path()`` on it before passing it to this routine! """ - # Generate alternative interpretations of a source distro name - # Because some packages are ambiguous as to name/versions split - # e.g. "adns-python-1.1.0", "egenix-mx-commercial", etc. - # So, we generate each possible interepretation (e.g. "adns, python-1.1.0" - # "adns-python, 1.1.0", and "adns-python-1.1.0, no version"). In practice, - # the spurious interpretations should be ignored, because in the event - # there's also an "adns" package, the spurious "python-1.1.0" version will - # compare lower than any numeric version number, and is therefore unlikely - # to match a request for it. It's still a potential problem, though, and - # in the long run PyPI and the distutils should go for "safe" names and - # versions in distribution archive names (sdist and bdist). parts = basename.split('-') if not py_version and any(re.match(r'py\d\.\d$', p) for p in parts[2:]): # it is a bdist_dumb, not an sdist -- bail out return - for p in range(1, len(parts) + 1): - yield Distribution( - location, metadata, '-'.join(parts[:p]), '-'.join(parts[p:]), - py_version=py_version, precedence=precedence, - platform=platform - ) + p = len(parts) - 1 + yield Distribution( + location, metadata, '-'.join(parts[:p]), '-'.join(parts[p:]), + py_version=py_version, precedence=precedence, + platform=platform + ) # From Python 2.7 docs -- cgit v1.2.1 From a9d3576584cd9a91734dae6473ab6c3253f09f64 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 22 Oct 2021 12:12:04 -0400 Subject: Suppress the now invalid pbr version. --- setuptools/package_index.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index c9254289..1300b406 100644 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -283,6 +283,12 @@ class PackageIndex(Environment): self.to_scan = [] self.opener = urllib.request.urlopen + def add(self, dist): + # ignore invalid pbr version + if dist.version == '0.5.2.5.g5b3e942': + return + return super().add(dist) + # FIXME: 'PackageIndex.process_url' is too complex (14) def process_url(self, url, retrieve=False): # noqa: C901 """Evaluate a URL as a possible download, and maybe retrieve it""" -- cgit v1.2.1 From 6fc5d3099898fc3d06bcf72f1f6607d02124d60f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 22 Oct 2021 12:44:53 -0400 Subject: Update test_egg_fragment to include a name with a dash in it. Expand on interpret_distro_name to be a tiny bit smarter about inferring the pivot separating name and version. --- setuptools/package_index.py | 9 ++++++++- setuptools/tests/test_packageindex.py | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index 1300b406..bef2ef81 100644 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -165,7 +165,14 @@ def interpret_distro_name( # it is a bdist_dumb, not an sdist -- bail out return - p = len(parts) - 1 + # find the pivot (p) that splits the name from the version. + # infer the version as the first item that has a digit. + for p in range(len(parts)): + if parts[p][:1].isdigit(): + break + else: + p = len(parts) + yield Distribution( location, metadata, '-'.join(parts[:p]), '-'.join(parts[p:]), py_version=py_version, precedence=precedence, diff --git a/setuptools/tests/test_packageindex.py b/setuptools/tests/test_packageindex.py index 8e9435ef..5f09e1bd 100644 --- a/setuptools/tests/test_packageindex.py +++ b/setuptools/tests/test_packageindex.py @@ -189,7 +189,7 @@ class TestPackageIndex: for locs in local] for v, vc in versions: dists = list(setuptools.package_index.distros_for_url( - 'http://example.com/example.zip#egg=example-' + v)) + 'http://example.com/example-foo.zip#egg=example-foo-' + v)) assert dists[0].version == '' assert dists[1].version == vc -- cgit v1.2.1 From 310a41c78bc80da05dbc37cf452a86f48ca55427 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 14 Jan 2023 11:57:18 -0500 Subject: =?UTF-8?q?=E2=9A=AB=20Fade=20to=20black.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setuptools/tests/test_dist_info.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/setuptools/tests/test_dist_info.py b/setuptools/tests/test_dist_info.py index 350e6429..b83b8021 100644 --- a/setuptools/tests/test_dist_info.py +++ b/setuptools/tests/test_dist_info.py @@ -19,19 +19,18 @@ read = partial(pathlib.Path.read_text, encoding="utf-8") class TestDistInfo: - metadata_base = DALS(""" + metadata_base = DALS( + """ Metadata-Version: 1.2 Requires-Dist: splort (==4) Provides-Extra: baz Requires-Dist: quux (>=1.1); extra == 'baz' - """) + """ + ) @classmethod def build_metadata(cls, **kwargs): - lines = ( - '{key}: {value}\n'.format(**locals()) - for key, value in kwargs.items() - ) + lines = ('{key}: {value}\n'.format(**locals()) for key, value in kwargs.items()) return cls.metadata_base + ''.join(lines) @pytest.fixture @@ -59,8 +58,7 @@ class TestDistInfo: def test_distinfo(self, metadata): dists = dict( - (d.project_name, d) - for d in pkg_resources.find_distributions(metadata) + (d.project_name, d) for d in pkg_resources.find_distributions(metadata) ) assert len(dists) == 2, dists @@ -116,7 +114,7 @@ class TestDistInfo: def test_output_dir(self, tmp_path, keep_egg_info): config = "[metadata]\nname=proj\nversion=42\n" (tmp_path / "setup.cfg").write_text(config, encoding="utf-8") - out = (tmp_path / "__out") + out = tmp_path / "__out" out.mkdir() opts = ["--keep-egg-info"] if keep_egg_info else [] run_command("dist_info", "--output-dir", out, *opts, cwd=tmp_path) @@ -133,7 +131,9 @@ class TestWheelCompatibility: """Make sure the .dist-info directory produced with the ``dist_info`` command is the same as the one produced by ``bdist_wheel``. """ - SETUPCFG = DALS(""" + + SETUPCFG = DALS( + """ [metadata] name = {name} version = {version} @@ -149,7 +149,8 @@ class TestWheelCompatibility: executable-name = my_package.module:function discover = myproj = my_package.other_module:function - """) + """ + ) EGG_INFO_OPTS = [ # Related: #3088 #2872 -- cgit v1.2.1 From 0a6cd4fc60a5ac61ab8f57a52d171ef4d2837067 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 14 Jan 2023 12:41:47 -0500 Subject: Update test_invalid_version to expect failure. --- setuptools/tests/test_dist_info.py | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/setuptools/tests/test_dist_info.py b/setuptools/tests/test_dist_info.py index b83b8021..45b0d7fb 100644 --- a/setuptools/tests/test_dist_info.py +++ b/setuptools/tests/test_dist_info.py @@ -82,13 +82,16 @@ class TestDistInfo: assert d.extras == ['baz'] def test_invalid_version(self, tmp_path): + """ + Supplying an invalid version crashes dist_info. + """ config = "[metadata]\nname=proj\nversion=42\n[egg_info]\ntag_build=invalid!!!\n" (tmp_path / "setup.cfg").write_text(config, encoding="utf-8") msg = re.compile("invalid version", re.M | re.I) - output = run_command("dist_info", cwd=tmp_path) - assert msg.search(output) - dist_info = next(tmp_path.glob("*.dist-info")) - assert dist_info.name.startswith("proj-42") + proc = run_command_inner("dist_info", cwd=tmp_path, check=False) + assert proc.returncode + assert msg.search(proc.stdout) + assert not list(tmp_path.glob("*.dist-info")) def test_tag_arguments(self, tmp_path): config = """ @@ -190,7 +193,17 @@ class TestWheelCompatibility: assert read(dist_info / file) == read(wheel_dist_info / file) -def run_command(*cmd, **kwargs): - opts = {"stderr": subprocess.STDOUT, "text": True, **kwargs} +def run_command_inner(*cmd, **kwargs): + opts = { + "stderr": subprocess.STDOUT, + "stdout": subprocess.PIPE, + "text": True, + 'check': True, + **kwargs, + } cmd = [sys.executable, "-c", "__import__('setuptools').setup()", *map(str, cmd)] - return subprocess.check_output(cmd, **opts) + return subprocess.run(cmd, **opts) + + +def run_command(*args, **kwargs): + return run_command_inner(*args, **kwargs).stdout -- cgit v1.2.1