summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changelog.d/2497.breaking.rst1
-rw-r--r--pkg_resources/__init__.py88
-rw-r--r--setuptools/command/egg_info.py2
-rw-r--r--setuptools/package_index.py40
-rw-r--r--setuptools/tests/test_dist_info.py50
-rw-r--r--setuptools/tests/test_packageindex.py2
6 files changed, 55 insertions, 128 deletions
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.
diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py
index 394fbf91..bba775b9 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
@@ -120,16 +119,7 @@ class PEP440Warning(RuntimeWarning):
"""
-def parse_version(v):
- try:
- return packaging.version.Version(v)
- except packaging.version.InvalidVersion:
- warnings.warn(
- f"{v} is an invalid version and will not be supported in "
- "a future release",
- PkgResourcesDeprecationWarning,
- )
- return packaging.version.LegacyVersion(v)
+parse_version = packaging.version.Version
_state_vars = {}
@@ -2083,42 +2073,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', 'bar', 'foo']
- >>> 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 try_parse(name):
- """
- Attempt to parse as a version or return a null version.
- """
- try:
- return packaging.version.Version(name)
- except Exception:
- return packaging.version.Version('0')
-
- def _by_version(name):
- """
- Parse each component of the filename
- """
- name, ext = os.path.splitext(name)
- parts = itertools.chain(name.split('-'), [ext])
- return [try_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)
@@ -2132,14 +2086,8 @@ def find_on_path(importer, path_item, only=False):
entries = (os.path.join(path_item, child) 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):
@@ -2731,38 +2679,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:
diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py
index 95c81845..1885efb0 100644
--- a/setuptools/command/egg_info.py
+++ b/setuptools/command/egg_info.py
@@ -155,7 +155,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)
diff --git a/setuptools/package_index.py b/setuptools/package_index.py
index 362e26f3..bec41835 100644
--- a/setuptools/package_index.py
+++ b/setuptools/package_index.py
@@ -169,39 +169,35 @@ def distros_for_filename(filename, metadata=None):
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 interpretation (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,
- )
+ # 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,
+ platform=platform
+ )
def unique_values(func):
diff --git a/setuptools/tests/test_dist_info.py b/setuptools/tests/test_dist_info.py
index 350e6429..45b0d7fb 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
@@ -84,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 = """
@@ -116,7 +117,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 +134,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 +152,8 @@ class TestWheelCompatibility:
executable-name = my_package.module:function
discover =
myproj = my_package.other_module:function
- """)
+ """
+ )
EGG_INFO_OPTS = [
# Related: #3088 #2872
@@ -189,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
diff --git a/setuptools/tests/test_packageindex.py b/setuptools/tests/test_packageindex.py
index 7b0bf112..8b5356dc 100644
--- a/setuptools/tests/test_packageindex.py
+++ b/setuptools/tests/test_packageindex.py
@@ -180,7 +180,7 @@ class TestPackageIndex:
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 == ''