From: Stefano Rivera <stefanor@debian.org>
Date: Mon, 1 Mar 2021 10:57:10 -0800
Subject: Re-parse pkg_resources Versions from str

When debundling pkg_resources and packaging use different Version
classes, causing trouble.

Based on: https://github.com/pypa/pip/pull/9467

Bug-Upstream: https://github.com/pypa/pip/issues/9348
---
 src/pip/_internal/req/req_install.py                  | 12 ++++++++++--
 src/pip/_internal/resolution/resolvelib/candidates.py |  8 ++++----
 src/pip/_internal/resolution/resolvelib/resolver.py   |  3 ++-
 src/pip/_internal/wheel_builder.py                    |  3 ++-
 4 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/src/pip/_internal/req/req_install.py b/src/pip/_internal/req/req_install.py
index 866d18f..548c00d 100644
--- a/src/pip/_internal/req/req_install.py
+++ b/src/pip/_internal/req/req_install.py
@@ -434,8 +434,16 @@ class InstallRequirement(object):
         if not existing_dist:
             return
 
-        existing_version = existing_dist.parsed_version
-        if not self.req.specifier.contains(existing_version, prereleases=True):
+        # pkg_resouces may contain a different copy of packaging.version from
+        # pip in if the downstream distributor does a poor job debundling pip.
+        # We avoid existing_dist.parsed_version and let SpecifierSet.contains
+        # parses the version instead.
+        existing_version = existing_dist.version
+        version_compatible = (
+            existing_version is not None and
+            self.req.specifier.contains(existing_version, prereleases=True)
+        )
+        if not version_compatible:
             self.satisfied_by = None
             if use_user_site:
                 if dist_in_usersite(existing_dist):
diff --git a/src/pip/_internal/resolution/resolvelib/candidates.py b/src/pip/_internal/resolution/resolvelib/candidates.py
index 83b6c98..5211a17 100644
--- a/src/pip/_internal/resolution/resolvelib/candidates.py
+++ b/src/pip/_internal/resolution/resolvelib/candidates.py
@@ -3,7 +3,7 @@ import sys
 
 from pip._vendor.packaging.specifiers import InvalidSpecifier, SpecifierSet
 from pip._vendor.packaging.utils import canonicalize_name
-from pip._vendor.packaging.version import Version
+from pip._vendor.packaging.version import Version, parse as parse_version
 
 from pip._internal.exceptions import HashError, MetadataInconsistent
 from pip._internal.models.wheel import Wheel
@@ -191,7 +191,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):
@@ -212,7 +212,7 @@ class _InstallRequirementBackedCandidate(Candidate):
         name = canonicalize_name(dist.project_name)
         if self._name is not None and self._name != name:
             raise MetadataInconsistent(self._ireq, "name", dist.project_name)
-        version = dist.parsed_version
+        version = parse_version(dist.version)
         if self._version is not None and self._version != version:
             raise MetadataInconsistent(self._ireq, "version", dist.version)
 
@@ -396,7 +396,7 @@ class AlreadyInstalledCandidate(Candidate):
     @property
     def version(self):
         # type: () -> _BaseVersion
-        return self.dist.parsed_version
+        return parse_version(self.dist.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 30b860f..84421d4 100644
--- a/src/pip/_internal/resolution/resolvelib/resolver.py
+++ b/src/pip/_internal/resolution/resolvelib/resolver.py
@@ -4,6 +4,7 @@ import os
 
 from pip._vendor import six
 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
 
@@ -141,7 +142,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):
diff --git a/src/pip/_internal/wheel_builder.py b/src/pip/_internal/wheel_builder.py
index dbc34d0..f7e15af 100644
--- a/src/pip/_internal/wheel_builder.py
+++ b/src/pip/_internal/wheel_builder.py
@@ -9,6 +9,7 @@ import zipfile
 
 from pip._vendor.packaging.utils import canonicalize_name, canonicalize_version
 from pip._vendor.packaging.version import InvalidVersion, Version
+from pip._vendor.packaging.version import parse as parse_version
 from pip._vendor.pkg_resources import Distribution
 
 from pip._internal.exceptions import InvalidWheelFilename, UnsupportedWheel
@@ -200,7 +201,7 @@ def _verify_one(req, wheel_path):
             "got {!r}".format(dist.version, w.version),
         )
     if (_get_metadata_version(dist) >= Version("1.2")
-            and not isinstance(dist.parsed_version, Version)):
+            and not isinstance(parse_version(dist.version), Version)):
         raise UnsupportedWheel(
             "Metadata 1.2 mandates PEP 440 version, "
             "but {!r} is not".format(dist.version)
