summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefano Rivera <stefano@rivera.za.net>2021-03-02 11:46:31 -0800
committerStefano Rivera <stefano@rivera.za.net>2021-03-02 12:19:10 -0800
commit8f2e3d69782192920882bafc76c927a3887ee5b7 (patch)
treee791888c2cc757b11b4cc4a8abfa0cd62d4e5e12
parente7d6e54dff0ef93197624c51cbde264dc390c511 (diff)
downloadpip-8f2e3d69782192920882bafc76c927a3887ee5b7.tar.gz
Parse pkg_resources Dist versions with packaging.version
Due to a mix of bundled and unbundled dependencies, pkg_resources Version class may not be the same as packaging's Version class. See: https://github.com/pypa/setuptools/issues/2052
-rw-r--r--news/9e768673-6079-491e-bbe0-d1593952f1c7.trivial.rst0
-rw-r--r--src/pip/_internal/metadata/pkg_resources.py6
-rw-r--r--src/pip/_internal/resolution/resolvelib/candidates.py11
-rw-r--r--src/pip/_internal/resolution/resolvelib/resolver.py3
4 files changed, 15 insertions, 5 deletions
diff --git a/news/9e768673-6079-491e-bbe0-d1593952f1c7.trivial.rst b/news/9e768673-6079-491e-bbe0-d1593952f1c7.trivial.rst
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/news/9e768673-6079-491e-bbe0-d1593952f1c7.trivial.rst
diff --git a/src/pip/_internal/metadata/pkg_resources.py b/src/pip/_internal/metadata/pkg_resources.py
index 5cd9eaee6..0196ff347 100644
--- a/src/pip/_internal/metadata/pkg_resources.py
+++ b/src/pip/_internal/metadata/pkg_resources.py
@@ -4,6 +4,7 @@ from typing import Iterator, List, Optional
from pip._vendor import pkg_resources
from pip._vendor.packaging.utils import canonicalize_name
from pip._vendor.packaging.version import _BaseVersion
+from pip._vendor.packaging.version import parse as parse_version
from pip._internal.utils import misc # TODO: Move definition here.
from pip._internal.utils.packaging import get_installer
@@ -16,6 +17,7 @@ class Distribution(BaseDistribution):
def __init__(self, dist):
# type: (pkg_resources.Distribution) -> None
self._dist = dist
+ self._version = None
@classmethod
def from_wheel(cls, path, name):
@@ -45,7 +47,9 @@ class Distribution(BaseDistribution):
@property
def version(self):
# type: () -> _BaseVersion
- return self._dist.parsed_version
+ if self._version is None:
+ self._version = parse_version(self._dist.version)
+ return self._version
@property
def installer(self):
diff --git a/src/pip/_internal/resolution/resolvelib/candidates.py b/src/pip/_internal/resolution/resolvelib/candidates.py
index 035e118d0..5638eb0c1 100644
--- a/src/pip/_internal/resolution/resolvelib/candidates.py
+++ b/src/pip/_internal/resolution/resolvelib/candidates.py
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING, Any, FrozenSet, Iterable, Optional, Tuple, Uni
from pip._vendor.packaging.specifiers import InvalidSpecifier, SpecifierSet
from pip._vendor.packaging.utils import canonicalize_name
from pip._vendor.packaging.version import Version, _BaseVersion
+from pip._vendor.packaging.version import parse as parse_version
from pip._vendor.pkg_resources import Distribution
from pip._internal.exceptions import HashError, MetadataInconsistent
@@ -180,7 +181,7 @@ class _InstallRequirementBackedCandidate(Candidate):
def version(self):
# type: () -> _BaseVersion
if self._version is None:
- self._version = self.dist.parsed_version
+ self._version = parse_version(self.dist.version)
return self._version
def format_for_error(self):
@@ -206,7 +207,8 @@ class _InstallRequirementBackedCandidate(Candidate):
self._name,
dist.project_name,
)
- if self._version is not None and self._version != dist.parsed_version:
+ parsed_version = parse_version(dist.version)
+ if self._version is not None and self._version != parsed_version:
raise MetadataInconsistent(
self._ireq,
"version",
@@ -345,6 +347,7 @@ class AlreadyInstalledCandidate(Candidate):
self.dist = dist
self._ireq = make_install_req_from_dist(dist, template)
self._factory = factory
+ self._version = None
# This is just logging some messages, so we can do it eagerly.
# The returned dist would be exactly the same as self.dist because we
@@ -387,7 +390,9 @@ class AlreadyInstalledCandidate(Candidate):
@property
def version(self):
# type: () -> _BaseVersion
- return self.dist.parsed_version
+ if self._version is None:
+ self._version = parse_version(self.dist.version)
+ return self._version
@property
def is_editable(self):
diff --git a/src/pip/_internal/resolution/resolvelib/resolver.py b/src/pip/_internal/resolution/resolvelib/resolver.py
index eba441091..7826cfc0f 100644
--- a/src/pip/_internal/resolution/resolvelib/resolver.py
+++ b/src/pip/_internal/resolution/resolvelib/resolver.py
@@ -4,6 +4,7 @@ import os
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple
from pip._vendor.packaging.utils import canonicalize_name
+from pip._vendor.packaging.version import parse as parse_version
from pip._vendor.resolvelib import ResolutionImpossible
from pip._vendor.resolvelib import Resolver as RLResolver
from pip._vendor.resolvelib.resolvers import Result
@@ -139,7 +140,7 @@ class Resolver(BaseResolver):
elif self.factory.force_reinstall:
# The --force-reinstall flag is set -- reinstall.
ireq.should_reinstall = True
- elif installed_dist.parsed_version != candidate.version:
+ elif parse_version(installed_dist.version) != candidate.version:
# The installation is different in version -- reinstall.
ireq.should_reinstall = True
elif candidate.is_editable or dist_is_editable(installed_dist):