diff --git a/news/5082.feature b/news/5082.feature
deleted file mode 100644
index 17c678764..000000000
--- a/news/5082.feature
+++ /dev/null
@@ -1,2 +0,0 @@
-Improve the error message when ``METADATA`` or ``PKG-INFO`` is None when
-accessing metadata.
diff --git a/news/6121.feature b/news/6121.feature
deleted file mode 100644
index afe1f3857..000000000
--- a/news/6121.feature
+++ /dev/null
@@ -1,2 +0,0 @@
-Include the wheel's tags in the log message explanation when a candidate
-wheel link is found incompatible.
diff --git a/news/6386.bugfix b/news/6386.bugfix
deleted file mode 100644
index 366ec2862..000000000
--- a/news/6386.bugfix
+++ /dev/null
@@ -1,2 +0,0 @@
-Extend to Subversion 1.8+ the behavior of calling Subversion in
-interactive mode when pip is run interactively.
diff --git a/news/6513.bugfix b/news/6513.bugfix
deleted file mode 100644
index 0e1757ae7..000000000
--- a/news/6513.bugfix
+++ /dev/null
@@ -1,2 +0,0 @@
-Include more details in the log message if ``pip freeze`` can't generate a
-requirement string for a particular distribution.
diff --git a/news/6549.feature b/news/6549.feature
new file mode 100644
index 000000000..d4970e39a
--- /dev/null
+++ b/news/6549.feature
@@ -0,0 +1,1 @@
+Improve deprecation messages to include the version in which the functionality will be removed.
diff --git a/src/pip/_internal/exceptions.py b/src/pip/_internal/exceptions.py
index 096adcd6c..7b291a1e4 100644
--- a/src/pip/_internal/exceptions.py
+++ b/src/pip/_internal/exceptions.py
@@ -9,7 +9,6 @@ from pip._internal.utils.typing import MYPY_CHECK_RUNNING
 
 if MYPY_CHECK_RUNNING:
     from typing import Optional
-    from pip._vendor.pkg_resources import Distribution
     from pip._internal.req.req_install import InstallRequirement
 
 
@@ -29,36 +28,6 @@ class UninstallationError(PipError):
     """General exception during uninstallation"""
 
 
-class NoneMetadataError(PipError):
-    """
-    Raised when accessing "METADATA" or "PKG-INFO" metadata for a
-    pip._vendor.pkg_resources.Distribution object and
-    `dist.has_metadata('METADATA')` returns True but
-    `dist.get_metadata('METADATA')` returns None (and similarly for
-    "PKG-INFO").
-    """
-
-    def __init__(self, dist, metadata_name):
-        # type: (Distribution, str) -> None
-        """
-        :param dist: A Distribution object.
-        :param metadata_name: The name of the metadata being accessed
-            (can be "METADATA" or "PKG-INFO").
-        """
-        self.dist = dist
-        self.metadata_name = metadata_name
-
-    def __str__(self):
-        # type: () -> str
-        # Use `dist` in the error message because its stringification
-        # includes more information, like the version and location.
-        return (
-            'None {} metadata found for distribution: {}'.format(
-                self.metadata_name, self.dist,
-            )
-        )
-
-
 class DistributionNotFound(InstallationError):
     """Raised when a distribution cannot be found to satisfy a requirement"""
 
diff --git a/src/pip/_internal/index.py b/src/pip/_internal/index.py
index 5b42a7c72..62845b657 100644
--- a/src/pip/_internal/index.py
+++ b/src/pip/_internal/index.py
@@ -384,15 +384,7 @@ class CandidateEvaluator(object):
                     return (False, reason)
 
                 if not self._is_wheel_supported(wheel):
-                    # Include the wheel's tags in the reason string to
-                    # simplify troubleshooting compatibility issues.
-                    file_tags = wheel.get_formatted_file_tags()
-                    reason = (
-                        "none of the wheel's tags match: {}".format(
-                            ', '.join(file_tags)
-                        )
-                    )
-                    return (False, reason)
+                    return (False, 'it is not compatible with this Python')
 
                 version = wheel.version
 
@@ -1074,9 +1066,7 @@ class PackageFinder(object):
     def _log_skipped_link(self, link, reason):
         # type: (Link, str) -> None
         if link not in self._logged_links:
-            # Put the link at the end so the reason is more visible and
-            # because the link string is usually very long.
-            logger.debug('Skipping link: %s: %s', reason, link)
+            logger.debug('Skipping link %s; %s', link, reason)
             self._logged_links.add(link)
 
     def get_install_candidate(self, link, search):
diff --git a/src/pip/_internal/operations/freeze.py b/src/pip/_internal/operations/freeze.py
index 03e8696bb..c79a785c5 100644
--- a/src/pip/_internal/operations/freeze.py
+++ b/src/pip/_internal/operations/freeze.py
@@ -60,14 +60,10 @@ def freeze(
                                             user_only=user_only):
         try:
             req = FrozenRequirement.from_dist(dist)
-        except RequirementParseError as exc:
-            # We include dist rather than dist.project_name because the
-            # dist string includes more information, like the version and
-            # location. We also include the exception message to aid
-            # troubleshooting.
+        except RequirementParseError:
             logger.warning(
-                'Could not generate requirement for distribution %r: %s',
-                dist, exc
+                "Could not parse requirement: %s",
+                dist.project_name
             )
             continue
         if exclude_editable and req.editable:
diff --git a/src/pip/_internal/utils/deprecation.py b/src/pip/_internal/utils/deprecation.py
index 8c896f8ce..b9359bddc 100644
--- a/src/pip/_internal/utils/deprecation.py
+++ b/src/pip/_internal/utils/deprecation.py
@@ -78,16 +78,23 @@ def deprecated(reason, replacement, gone_in, issue=None):
     """
 
     # Construct a nice message.
-    # This is purposely eagerly formatted as we want it to appear as if someone
-    # typed this entire message out.
-    message = DEPRECATION_MSG_PREFIX + reason
-    if replacement is not None:
-        message += " A possible replacement is {}.".format(replacement)
-    if issue is not None:
-        url = "https://github.com/pypa/pip/issues/" + str(issue)
-        message += " You can find discussion regarding this at {}.".format(url)
+    #   This is eagerly formatted as we want it to get logged as if someone
+    #   typed this entire message out.
+    sentences = [
+        (reason, DEPRECATION_MSG_PREFIX + "{}"),
+        (gone_in, "pip {} will remove support for this functionality."),
+        (replacement, "A possible replacement is {}."),
+        (issue, (
+            "You can find discussion regarding this at "
+            "https://github.com/pypa/pip/issues/{}."
+        )),
+    ]
+    message = " ".join(
+        template.format(val) for val, template in sentences if val is not None
+    )
 
     # Raise as an error if it has to be removed.
     if gone_in is not None and parse(current_version) >= parse(gone_in):
         raise PipDeprecationWarning(message)
+
     warnings.warn(message, category=PipDeprecationWarning, stacklevel=2)
diff --git a/src/pip/_internal/utils/packaging.py b/src/pip/_internal/utils/packaging.py
index 2d80920df..ac27e5600 100644
--- a/src/pip/_internal/utils/packaging.py
+++ b/src/pip/_internal/utils/packaging.py
@@ -6,7 +6,6 @@ from email.parser import FeedParser
 from pip._vendor import pkg_resources
 from pip._vendor.packaging import specifiers, version
 
-from pip._internal.exceptions import NoneMetadataError
 from pip._internal.utils.misc import display_path
 from pip._internal.utils.typing import MYPY_CHECK_RUNNING
 
@@ -44,27 +43,16 @@ def check_requires_python(requires_python, version_info):
 
 def get_metadata(dist):
     # type: (Distribution) -> Message
-    """
-    :raises NoneMetadataError: if the distribution reports `has_metadata()`
-        True but `get_metadata()` returns None.
-    """
-    metadata_name = 'METADATA'
     if (isinstance(dist, pkg_resources.DistInfoDistribution) and
-            dist.has_metadata(metadata_name)):
-        metadata = dist.get_metadata(metadata_name)
+            dist.has_metadata('METADATA')):
+        metadata = dist.get_metadata('METADATA')
     elif dist.has_metadata('PKG-INFO'):
-        metadata_name = 'PKG-INFO'
-        metadata = dist.get_metadata(metadata_name)
+        metadata = dist.get_metadata('PKG-INFO')
     else:
         logger.warning("No metadata found in %s", display_path(dist.location))
         metadata = ''
 
-    if metadata is None:
-        raise NoneMetadataError(dist, metadata_name)
-
     feed_parser = FeedParser()
-    # The following line errors out if with a "NoneType" TypeError if
-    # passed metadata=None.
     feed_parser.feed(metadata)
     return feed_parser.close()
 
diff --git a/src/pip/_internal/vcs/subversion.py b/src/pip/_internal/vcs/subversion.py
index 0d787009f..7ab03a277 100644
--- a/src/pip/_internal/vcs/subversion.py
+++ b/src/pip/_internal/vcs/subversion.py
@@ -20,7 +20,6 @@ _svn_info_xml_url_re = re.compile(r'<url>(.*)</url>')
 
 if MYPY_CHECK_RUNNING:
     from typing import List, Optional, Tuple
-    from pip._internal.vcs import RevOptions
 
 logger = logging.getLogger(__name__)
 
@@ -49,12 +48,10 @@ class Subversion(VersionControl):
                 # Subversion doesn't like to check out over an existing
                 # directory --force fixes this, but was only added in svn 1.5
                 rmtree(location)
-            cmd_args = (['export'] + self.get_remote_call_options() +
-                        rev_options.to_args() + [url, location])
+            cmd_args = ['export'] + rev_options.to_args() + [url, location]
             self.run_command(cmd_args, show_stdout=False)
 
     def fetch_new(self, dest, url, rev_options):
-        # type: (str, str, RevOptions) -> None
         rev_display = rev_options.to_display()
         logger.info(
             'Checking out %s%s to %s',
@@ -62,21 +59,15 @@ class Subversion(VersionControl):
             rev_display,
             display_path(dest),
         )
-        cmd_args = (['checkout', '-q'] +
-                    self.get_remote_call_options() +
-                    rev_options.to_args() + [url, dest])
+        cmd_args = ['checkout', '-q'] + rev_options.to_args() + [url, dest]
         self.run_command(cmd_args)
 
     def switch(self, dest, url, rev_options):
-        # type: (str, str, RevOptions) -> None
-        cmd_args = (['switch'] + self.get_remote_call_options() +
-                    rev_options.to_args() + [url, dest])
+        cmd_args = ['switch'] + rev_options.to_args() + [url, dest]
         self.run_command(cmd_args)
 
     def update(self, dest, url, rev_options):
-        # type: (str, str, RevOptions) -> None
-        cmd_args = (['update'] + self.get_remote_call_options() +
-                    rev_options.to_args() + [dest])
+        cmd_args = ['update'] + rev_options.to_args() + [dest]
         self.run_command(cmd_args)
 
     @classmethod
@@ -186,11 +177,6 @@ class Subversion(VersionControl):
         else:
             try:
                 # subversion >= 1.7
-                # Note that using get_remote_call_options is not necessary here
-                # because `svn info` is being run against a local directory.
-                # We don't need to worry about making sure interactive mode
-                # is being used to prompt for passwords, because passwords
-                # are only potentially needed for remote server requests.
                 xml = cls.run_command(
                     ['info', '--xml', location],
                     show_stdout=False,
diff --git a/src/pip/_internal/wheel.py b/src/pip/_internal/wheel.py
index 970dadf8f..18f25df4a 100644
--- a/src/pip/_internal/wheel.py
+++ b/src/pip/_internal/wheel.py
@@ -663,16 +663,6 @@ def check_compatibility(version, name):
         )
 
 
-def format_tag(file_tag):
-    # type: (Tuple[str, ...]) -> str
-    """
-    Format three tags in the form "<python_tag>-<abi_tag>-<platform_tag>".
-
-    :param file_tag: A 3-tuple of tags (python_tag, abi_tag, platform_tag).
-    """
-    return '-'.join(file_tag)
-
-
 class Wheel(object):
     """A wheel file"""
 
@@ -712,13 +702,6 @@ class Wheel(object):
             for y in self.abis for z in self.plats
         }
 
-    def get_formatted_file_tags(self):
-        # type: () -> List[str]
-        """
-        Return the wheel's tags as a sorted list of strings.
-        """
-        return sorted(format_tag(tag) for tag in self.file_tags)
-
     def support_index_min(self, tags=None):
         # type: (Optional[List[Pep425Tag]]) -> Optional[int]
         """

Update pip's deprecation helpers to mention version
> The deprecation messages should've mentioned the release in which the functionality will be removed.

I have a PR in the works; I'll post it soon.

_Originally posted by @pradyunsg in https://github.com/pypa/pip/issues/6162#issuecomment-456662154_
diff --git a/tests/functional/test_freeze.py b/tests/functional/test_freeze.py
index 68625ff43..4016b5c86 100644
--- a/tests/functional/test_freeze.py
+++ b/tests/functional/test_freeze.py
@@ -108,19 +108,12 @@ def test_freeze_with_invalid_names(script):
             '...{}==1.0...'.format(pkgname.replace('_', '-'))
         )
     for pkgname in invalid_pkgnames:
-        # Check that the full distribution repr is present.
-        dist_repr = '{} 1.0 ('.format(pkgname.replace('_', '-'))
-        expected = (
-            '...Could not generate requirement for '
-            'distribution {}...'.format(dist_repr)
+        _check_output(
+            result.stderr,
+            '...Could not parse requirement: {}\n...'.format(
+                pkgname.replace('_', '-')
+            )
         )
-        _check_output(result.stderr, expected)
-
-    # Also check that the parse error details occur at least once.
-    # We only need to find one occurrence to know that exception details
-    # are logged.
-    expected = '...site-packages): Parse error at "...'
-    _check_output(result.stderr, expected)
 
 
 @pytest.mark.git
diff --git a/tests/functional/test_install_config.py b/tests/functional/test_install_config.py
index a5d842c1e..cf405ca3f 100644
--- a/tests/functional/test_install_config.py
+++ b/tests/functional/test_install_config.py
@@ -105,10 +105,7 @@ def test_command_line_append_flags(script, virtualenv, data):
         "Analyzing links from page https://test.pypi.org"
         in result.stdout
     )
-    assert (
-        'Skipping link: not a file: {}'.format(data.find_links) in
-        result.stdout
-    ), 'stdout: {}'.format(result.stdout)
+    assert "Skipping link %s" % data.find_links in result.stdout
 
 
 @pytest.mark.network
@@ -130,10 +127,7 @@ def test_command_line_appends_correctly(script, data):
         "Analyzing links from page https://test.pypi.org"
         in result.stdout
     ), result.stdout
-    assert (
-        'Skipping link: not a file: {}'.format(data.find_links) in
-        result.stdout
-    ), 'stdout: {}'.format(result.stdout)
+    assert "Skipping link %s" % data.find_links in result.stdout
 
 
 def test_config_file_override_stack(script, virtualenv):
diff --git a/tests/functional/test_install_vcs_svn.py b/tests/functional/test_install_vcs_svn.py
index 8db3e8f50..6aea2737d 100644
--- a/tests/functional/test_install_vcs_svn.py
+++ b/tests/functional/test_install_vcs_svn.py
@@ -1,66 +1,30 @@
-from unittest import TestCase
-
+import pytest
 from mock import patch
 
-from pip._internal.vcs import RevOptions
 from pip._internal.vcs.subversion import Subversion
 
 
-class TestSubversionArgs(TestCase):
-    def setUp(self):
-        patcher = patch('pip._internal.vcs.call_subprocess')
-        self.addCleanup(patcher.stop)
-        self.call_subprocess_mock = patcher.start()
-
-        # Test Data.
-        self.url = 'svn+http://username:password@svn.example.com/'
-        # use_interactive is set to False to test that remote call options are
-        # properly added.
-        self.svn = Subversion(use_interactive=False)
-        self.rev_options = RevOptions(Subversion)
-        self.dest = '/tmp/test'
-
-    def assert_call_args(self, args):
-        assert self.call_subprocess_mock.call_args[0][0] == args
-
-    def test_obtain(self):
-        self.svn.obtain(self.dest, self.url)
-        self.assert_call_args(
-            ['svn', 'checkout', '-q', '--non-interactive', '--username',
-             'username', '--password', 'password',
-             'http://svn.example.com/', '/tmp/test'])
-
-    def test_export(self):
-        self.svn.export(self.dest, self.url)
-        self.assert_call_args(
-            ['svn', 'export', '--non-interactive', '--username', 'username',
-             '--password', 'password', 'http://svn.example.com/',
-             '/tmp/test'])
-
-    def test_fetch_new(self):
-        self.svn.fetch_new(self.dest, self.url, self.rev_options)
-        self.assert_call_args(
-            ['svn', 'checkout', '-q', '--non-interactive',
-             'svn+http://username:password@svn.example.com/',
-             '/tmp/test'])
-
-    def test_fetch_new_revision(self):
-        rev_options = RevOptions(Subversion, '123')
-        self.svn.fetch_new(self.dest, self.url, rev_options)
-        self.assert_call_args(
-            ['svn', 'checkout', '-q', '--non-interactive',
-             '-r', '123',
-             'svn+http://username:password@svn.example.com/',
-             '/tmp/test'])
-
-    def test_switch(self):
-        self.svn.switch(self.dest, self.url, self.rev_options)
-        self.assert_call_args(
-            ['svn', 'switch', '--non-interactive',
-             'svn+http://username:password@svn.example.com/',
-             '/tmp/test'])
-
-    def test_update(self):
-        self.svn.update(self.dest, self.url, self.rev_options)
-        self.assert_call_args(
-            ['svn', 'update', '--non-interactive', '/tmp/test'])
+@patch('pip._internal.vcs.call_subprocess')
+@pytest.mark.network
+def test_obtain_should_recognize_auth_info_url(call_subprocess_mock, script):
+    url = 'svn+http://username:password@svn.example.com/'
+    svn = Subversion()
+    svn.obtain(script.scratch_path / 'test', url=url)
+    assert call_subprocess_mock.call_args[0][0] == [
+        svn.name, 'checkout', '-q', '--username', 'username', '--password',
+        'password', 'http://svn.example.com/',
+        script.scratch_path / 'test',
+    ]
+
+
+@patch('pip._internal.vcs.call_subprocess')
+@pytest.mark.network
+def test_export_should_recognize_auth_info_url(call_subprocess_mock, script):
+    url = 'svn+http://username:password@svn.example.com/'
+    svn = Subversion()
+    svn.export(script.scratch_path / 'test', url=url)
+    assert call_subprocess_mock.call_args[0][0] == [
+        svn.name, 'export', '--username', 'username', '--password',
+        'password', 'http://svn.example.com/',
+        script.scratch_path / 'test',
+    ]
diff --git a/tests/unit/test_finder.py b/tests/unit/test_finder.py
index 3512b93a8..d8f40e0dd 100644
--- a/tests/unit/test_finder.py
+++ b/tests/unit/test_finder.py
@@ -133,7 +133,10 @@ class TestWheel:
         with pytest.raises(DistributionNotFound):
             finder.find_requirement(req, True)
 
-        assert 'Skipping link: invalid wheel filename:' in caplog.text
+        assert (
+            "invalid.whl; invalid wheel filename"
+            in caplog.text
+        )
 
     def test_not_find_wheel_not_supported(self, data, monkeypatch):
         """
diff --git a/tests/unit/test_index.py b/tests/unit/test_index.py
index 094c23af4..4323bc405 100644
--- a/tests/unit/test_index.py
+++ b/tests/unit/test_index.py
@@ -130,24 +130,6 @@ class TestCandidateEvaluator:
         actual = evaluator.evaluate_link(link, search=search)
         assert actual == expected
 
-    def test_evaluate_link__incompatible_wheel(self):
-        """
-        Test an incompatible wheel.
-        """
-        link = Link('https://example.com/sample-1.0-py2.py3-none-any.whl')
-        search = Search(
-            supplied='sample', canonical='sample', formats=['binary'],
-        )
-        # Pass an empty list for the valid tags to make sure nothing matches.
-        evaluator = CandidateEvaluator(
-            [], py_version_info=(3, 6, 4),
-        )
-        actual = evaluator.evaluate_link(link, search=search)
-        expected = (
-            False, "none of the wheel's tags match: py2-none-any, py3-none-any"
-        )
-        assert actual == expected
-
 
 def test_sort_locations_file_expand_dir(data):
     """
diff --git a/tests/unit/test_legacy_resolve.py b/tests/unit/test_legacy_resolve.py
index 4d7f27b20..e384e2349 100644
--- a/tests/unit/test_legacy_resolve.py
+++ b/tests/unit/test_legacy_resolve.py
@@ -1,65 +1,33 @@
 import logging
 
 import pytest
-from pip._vendor import pkg_resources
+from mock import patch
 
-from pip._internal.exceptions import (
-    NoneMetadataError, UnsupportedPythonVersion,
-)
+from pip._internal.exceptions import UnsupportedPythonVersion
 from pip._internal.legacy_resolve import _check_dist_requires_python
-from pip._internal.utils.packaging import get_requires_python
 
 
-# We need to inherit from DistInfoDistribution for the `isinstance()`
-# check inside `packaging.get_metadata()` to work.
-class FakeDist(pkg_resources.DistInfoDistribution):
+class FakeDist(object):
 
-    def __init__(self, metadata, metadata_name=None):
-        """
-        :param metadata: The value that dist.get_metadata() should return
-            for the `metadata_name` metadata.
-        :param metadata_name: The name of the metadata to store
-            (can be "METADATA" or "PKG-INFO").  Defaults to "METADATA".
-        """
-        if metadata_name is None:
-            metadata_name = 'METADATA'
+    def __init__(self, project_name):
+        self.project_name = project_name
 
-        self.project_name = 'my-project'
-        self.metadata_name = metadata_name
-        self.metadata = metadata
 
-    def __str__(self):
-        return '<distribution {!r}>'.format(self.project_name)
-
-    def has_metadata(self, name):
-        return (name == self.metadata_name)
-
-    def get_metadata(self, name):
-        assert name == self.metadata_name
-        return self.metadata
-
-
-def make_fake_dist(requires_python=None, metadata_name=None):
-    metadata = 'Name: test\n'
-    if requires_python is not None:
-        metadata += 'Requires-Python:{}'.format(requires_python)
-
-    return FakeDist(metadata, metadata_name=metadata_name)
+@pytest.fixture
+def dist():
+    return FakeDist('my-project')
 
 
+@patch('pip._internal.legacy_resolve.get_requires_python')
 class TestCheckDistRequiresPython(object):
 
     """
     Test _check_dist_requires_python().
     """
 
-    def test_compatible(self, caplog):
-        """
-        Test a Python version compatible with the dist's Requires-Python.
-        """
+    def test_compatible(self, mock_get_requires, caplog, dist):
         caplog.set_level(logging.DEBUG)
-        dist = make_fake_dist('== 3.6.5')
-
+        mock_get_requires.return_value = '== 3.6.5'
         _check_dist_requires_python(
             dist,
             version_info=(3, 6, 5),
@@ -67,11 +35,24 @@ class TestCheckDistRequiresPython(object):
         )
         assert not len(caplog.records)
 
-    def test_incompatible(self):
-        """
-        Test a Python version incompatible with the dist's Requires-Python.
-        """
-        dist = make_fake_dist('== 3.6.4')
+    def test_invalid_specifier(self, mock_get_requires, caplog, dist):
+        caplog.set_level(logging.DEBUG)
+        mock_get_requires.return_value = 'invalid'
+        _check_dist_requires_python(
+            dist,
+            version_info=(3, 6, 5),
+            ignore_requires_python=False,
+        )
+        assert len(caplog.records) == 1
+        record = caplog.records[0]
+        assert record.levelname == 'WARNING'
+        assert record.message == (
+            "Package 'my-project' has an invalid Requires-Python: "
+            "Invalid specifier: 'invalid'"
+        )
+
+    def test_incompatible(self, mock_get_requires, dist):
+        mock_get_requires.return_value = '== 3.6.4'
         with pytest.raises(UnsupportedPythonVersion) as exc:
             _check_dist_requires_python(
                 dist,
@@ -83,13 +64,11 @@ class TestCheckDistRequiresPython(object):
             "3.6.5 not in '== 3.6.4'"
         )
 
-    def test_incompatible_with_ignore_requires(self, caplog):
-        """
-        Test a Python version incompatible with the dist's Requires-Python
-        while passing ignore_requires_python=True.
-        """
+    def test_incompatible_with_ignore_requires(
+        self, mock_get_requires, caplog, dist,
+    ):
         caplog.set_level(logging.DEBUG)
-        dist = make_fake_dist('== 3.6.4')
+        mock_get_requires.return_value = '== 3.6.4'
         _check_dist_requires_python(
             dist,
             version_info=(3, 6, 5),
@@ -102,67 +81,3 @@ class TestCheckDistRequiresPython(object):
             "Ignoring failed Requires-Python check for package 'my-project': "
             "3.6.5 not in '== 3.6.4'"
         )
-
-    def test_none_requires_python(self, caplog):
-        """
-        Test a dist with Requires-Python None.
-        """
-        caplog.set_level(logging.DEBUG)
-        dist = make_fake_dist()
-        # Make sure our test setup is correct.
-        assert get_requires_python(dist) is None
-        assert len(caplog.records) == 0
-
-        # Then there is no exception and no log message.
-        _check_dist_requires_python(
-            dist,
-            version_info=(3, 6, 5),
-            ignore_requires_python=False,
-        )
-        assert len(caplog.records) == 0
-
-    def test_invalid_requires_python(self, caplog):
-        """
-        Test a dist with an invalid Requires-Python.
-        """
-        caplog.set_level(logging.DEBUG)
-        dist = make_fake_dist('invalid')
-        _check_dist_requires_python(
-            dist,
-            version_info=(3, 6, 5),
-            ignore_requires_python=False,
-        )
-        assert len(caplog.records) == 1
-        record = caplog.records[0]
-        assert record.levelname == 'WARNING'
-        assert record.message == (
-            "Package 'my-project' has an invalid Requires-Python: "
-            "Invalid specifier: 'invalid'"
-        )
-
-    @pytest.mark.parametrize('metadata_name', [
-        'METADATA',
-        'PKG-INFO',
-    ])
-    def test_empty_metadata_error(self, caplog, metadata_name):
-        """
-        Test dist.has_metadata() returning True and dist.get_metadata()
-        returning None.
-        """
-        dist = make_fake_dist(metadata_name=metadata_name)
-        dist.metadata = None
-
-        # Make sure our test setup is correct.
-        assert dist.has_metadata(metadata_name)
-        assert dist.get_metadata(metadata_name) is None
-
-        with pytest.raises(NoneMetadataError) as exc:
-            _check_dist_requires_python(
-                dist,
-                version_info=(3, 6, 5),
-                ignore_requires_python=False,
-            )
-        assert str(exc.value) == (
-            "None {} metadata found for distribution: "
-            "<distribution 'my-project'>".format(metadata_name)
-        )
diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py
index 1d97e65a1..3e9087fb5 100644
--- a/tests/unit/test_utils.py
+++ b/tests/unit/test_utils.py
@@ -22,6 +22,7 @@ from mock import Mock, patch
 from pip._internal.exceptions import (
     HashMismatch, HashMissing, InstallationError,
 )
+from pip._internal.utils.deprecation import PipDeprecationWarning, deprecated
 from pip._internal.utils.encoding import BOMS, auto_decode
 from pip._internal.utils.glibc import check_glibc_version
 from pip._internal.utils.hashes import Hashes, MissingHashes
@@ -1068,3 +1069,79 @@ def test_remove_auth_from_url(auth_url, expected_url):
 def test_redact_password_from_url(auth_url, expected_url):
     url = redact_password_from_url(auth_url)
     assert url == expected_url
+
+
+@pytest.fixture()
+def patch_deprecation_check_version():
+    # We do this, so that the deprecation tests are easier to write.
+    import pip._internal.utils.deprecation as d
+    old_version = d.current_version
+    d.current_version = "1.0"
+    yield
+    d.current_version = old_version
+
+
+@pytest.mark.usefixtures("patch_deprecation_check_version")
+@pytest.mark.parametrize("replacement", [None, "a magic 8 ball"])
+@pytest.mark.parametrize("gone_in", [None, "2.0"])
+@pytest.mark.parametrize("issue", [None, 988])
+def test_deprecated_message_contains_information(gone_in, replacement, issue):
+    with pytest.warns(PipDeprecationWarning) as record:
+        deprecated(
+            "Stop doing this!",
+            replacement=replacement,
+            gone_in=gone_in,
+            issue=issue,
+        )
+
+    assert len(record) == 1
+    message = record[0].message.args[0]
+
+    assert "DEPRECATION: Stop doing this!" in message
+    # Ensure non-None values are mentioned.
+    for item in [gone_in, replacement, issue]:
+        if item is not None:
+            assert str(item) in message
+
+
+@pytest.mark.usefixtures("patch_deprecation_check_version")
+@pytest.mark.parametrize("replacement", [None, "a magic 8 ball"])
+@pytest.mark.parametrize("issue", [None, 988])
+def test_deprecated_raises_error_if_too_old(replacement, issue):
+    with pytest.raises(PipDeprecationWarning) as exception:
+        deprecated(
+            "Stop doing this!",
+            gone_in="1.0",  # this matches the patched version.
+            replacement=replacement,
+            issue=issue,
+        )
+
+    message = exception.value.args[0]
+
+    assert "DEPRECATION: Stop doing this!" in message
+    assert "1.0" in message
+    # Ensure non-None values are mentioned.
+    for item in [replacement, issue]:
+        if item is not None:
+            assert str(item) in message
+
+
+@pytest.mark.usefixtures("patch_deprecation_check_version")
+def test_deprecated_message_reads_well():
+    with pytest.raises(PipDeprecationWarning) as exception:
+        deprecated(
+            "Stop doing this!",
+            gone_in="1.0",  # this matches the patched version.
+            replacement="to be nicer",
+            issue="100000",  # I hope we never reach this number.
+        )
+
+    message = exception.value.args[0]
+
+    assert message == (
+        "DEPRECATION: Stop doing this! "
+        "pip 1.0 will remove support for this functionality. "
+        "A possible replacement is to be nicer. "
+        "You can find discussion regarding this at "
+        "https://github.com/pypa/pip/issues/100000."
+    )
diff --git a/tests/unit/test_wheel.py b/tests/unit/test_wheel.py
index cae9ef35e..14cde104b 100644
--- a/tests/unit/test_wheel.py
+++ b/tests/unit/test_wheel.py
@@ -68,15 +68,6 @@ def make_test_install_req(base_name=None):
     return req
 
 
-@pytest.mark.parametrize('file_tag, expected', [
-    (('py27', 'none', 'any'), 'py27-none-any'),
-    (('cp33', 'cp32dmu', 'linux_x86_64'), 'cp33-cp32dmu-linux_x86_64'),
-])
-def test_format_tag(file_tag, expected):
-    actual = wheel.format_tag(file_tag)
-    assert actual == expected
-
-
 @pytest.mark.parametrize(
     "base_name, autobuilding, cache_available, expected",
     [

pip install -e .
parse_log_pytest
pytest
pytest pytest-cov pytest-rerunfailures pytest-timeout pytest-xdist freezegun mock pretend pyyaml setuptools>=39.2.0 scripttest virtualenv wheel
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
coverage==7.8.0
distlib==0.3.9
exceptiongroup==1.2.0
execnet==2.1.1
filelock==3.18.0
freezegun==1.5.1
iniconfig==1.1.1
mock==5.2.0
packaging==24.2
platformdirs==4.3.7
pluggy==1.5.0
pretend==1.0.9
pytest==8.3.4
pytest-cov==6.0.0
pytest-rerunfailures==15.0
pytest-timeout==2.3.1
pytest-xdist==3.6.1
python-dateutil==2.9.0.post0
PyYAML==6.0.2
scripttest==2.0
six==1.17.0
tomli==2.0.1
virtualenv==20.29.3

name: pip
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - exceptiongroup=1.2.0=py39h06a4308_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - packaging=24.2=py39h06a4308_0
  - pluggy=1.5.0=py39h06a4308_0
  - pytest=8.3.4=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py39h06a4308_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - coverage==7.8.0
      - distlib==0.3.9
      - execnet==2.1.1
      - filelock==3.18.0
      - freezegun==1.5.1
      - mock==5.2.0
      - pip==19.1.1
      - platformdirs==4.3.7
      - pretend==1.0.9
      - pytest-cov==6.0.0
      - pytest-rerunfailures==15.0
      - pytest-timeout==2.3.1
      - pytest-xdist==3.6.1
      - python-dateutil==2.9.0.post0
      - pyyaml==6.0.2
      - scripttest==2.0
      - six==1.17.0
      - virtualenv==20.29.3
prefix: /opt/conda/envs/pip

tests/unit/test_finder.py::TestWheel::test_skip_invalid_wheel_link tests/unit/test_utils.py::test_deprecated_message_contains_information[None-2.0-None] tests/unit/test_utils.py::test_deprecated_message_contains_information[None-2.0-a tests/unit/test_utils.py::test_deprecated_message_contains_information[988-2.0-None] tests/unit/test_utils.py::test_deprecated_message_contains_information[988-2.0-a tests/unit/test_utils.py::test_deprecated_raises_error_if_too_old[None-None] tests/unit/test_utils.py::test_deprecated_raises_error_if_too_old[None-a tests/unit/test_utils.py::test_deprecated_raises_error_if_too_old[988-None] tests/unit/test_utils.py::test_deprecated_raises_error_if_too_old[988-a tests/unit/test_utils.py::test_deprecated_message_reads_well
tests/unit/test_finder.py::TestCandidateEvaluator::test_evaluate_link__match[http:/yo/pytest-1.0.tar.gz-1.0] tests/unit/test_finder.py::TestCandidateEvaluator::test_evaluate_link__match[http:/yo/pytest-1.0-py2.py3-none-any.whl-1.0] tests/unit/test_finder.py::TestCandidateEvaluator::test_evaluate_link__substring_fails[http:/yo/pytest2-1.0.tar.gz-Missing tests/unit/test_finder.py::TestCandidateEvaluator::test_evaluate_link__substring_fails[http:/yo/pytest_xdist-1.0-py2.py3-none-any.whl-wrong tests/unit/test_utils.py::Tests_EgglinkPath::test_egglink_in_usersite_notvenv tests/unit/test_utils.py::Tests_EgglinkPath::test_egglink_in_usersite_venv_noglobal tests/unit/test_utils.py::Tests_EgglinkPath::test_egglink_in_usersite_venv_global tests/unit/test_utils.py::Tests_EgglinkPath::test_egglink_in_sitepkgs_notvenv tests/unit/test_utils.py::Tests_EgglinkPath::test_egglink_in_sitepkgs_venv_noglobal tests/unit/test_utils.py::Tests_EgglinkPath::test_egglink_in_sitepkgs_venv_global tests/unit/test_utils.py::Tests_EgglinkPath::test_egglink_in_both_notvenv tests/unit/test_utils.py::Tests_EgglinkPath::test_egglink_in_both_venv_noglobal tests/unit/test_utils.py::Tests_EgglinkPath::test_egglink_in_both_venv_global tests/unit/test_utils.py::Tests_EgglinkPath::test_noegglink_in_sitepkgs_notvenv tests/unit/test_utils.py::Tests_EgglinkPath::test_noegglink_in_sitepkgs_venv_noglobal tests/unit/test_utils.py::Tests_EgglinkPath::test_noegglink_in_sitepkgs_venv_global tests/unit/test_utils.py::TestUnpackArchives::test_unpack_tgz tests/unit/test_utils.py::TestUnpackArchives::test_unpack_zip
tests/unit/test_finder.py::test_no_mpkg tests/unit/test_finder.py::test_no_partial_name_match tests/unit/test_finder.py::test_tilde tests/unit/test_finder.py::test_duplicates_sort_ok tests/unit/test_finder.py::test_finder_detects_latest_find_links tests/unit/test_finder.py::test_incorrect_case_file_index tests/unit/test_finder.py::test_finder_detects_latest_already_satisfied_find_links tests/unit/test_finder.py::test_finder_detects_latest_already_satisfied_pypi_links tests/unit/test_finder.py::TestWheel::test_not_find_wheel_not_supported tests/unit/test_finder.py::TestWheel::test_find_wheel_supported tests/unit/test_finder.py::TestWheel::test_wheel_over_sdist_priority tests/unit/test_finder.py::TestWheel::test_existing_over_wheel_priority tests/unit/test_finder.py::TestWheel::test_link_sorting tests/unit/test_finder.py::TestWheel::test_link_sorting_wheels_with_build_tags tests/unit/test_finder.py::test_finder_priority_file_over_page tests/unit/test_finder.py::test_finder_priority_nonegg_over_eggfragments tests/unit/test_finder.py::test_finder_only_installs_stable_releases tests/unit/test_finder.py::test_finder_only_installs_data_require tests/unit/test_finder.py::test_finder_installs_pre_releases tests/unit/test_finder.py::test_finder_installs_dev_releases tests/unit/test_finder.py::test_finder_installs_pre_releases_with_version_spec tests/unit/test_finder.py::test_get_index_urls_locations tests/unit/test_finder.py::test_find_all_candidates_nothing tests/unit/test_finder.py::test_find_all_candidates_find_links tests/unit/test_finder.py::test_find_all_candidates_index tests/unit/test_finder.py::test_find_all_candidates_find_links_and_index tests/unit/test_index.py::test_check_link_requires_python[== tests/unit/test_index.py::test_check_link_requires_python[invalid-True] tests/unit/test_index.py::test_check_link_requires_python__incompatible_python[None-expected0] tests/unit/test_index.py::test_check_link_requires_python__incompatible_python[True-expected1] tests/unit/test_index.py::test_check_link_requires_python__invalid_requires tests/unit/test_index.py::TestCandidateEvaluator::test_init__py_version[version_info0-2.7] tests/unit/test_index.py::TestCandidateEvaluator::test_init__py_version[version_info1-3.6] tests/unit/test_index.py::TestCandidateEvaluator::test_init__py_version[version_info2-3.10] tests/unit/test_index.py::TestCandidateEvaluator::test_init__py_version_default tests/unit/test_index.py::TestCandidateEvaluator::test_evaluate_link[py_version_info0-None-expected0] tests/unit/test_index.py::TestCandidateEvaluator::test_evaluate_link[py_version_info1-None-expected1] tests/unit/test_index.py::TestCandidateEvaluator::test_evaluate_link[py_version_info2-True-expected2] tests/unit/test_index.py::test_sort_locations_file_expand_dir tests/unit/test_index.py::test_sort_locations_file_not_find_link tests/unit/test_index.py::test_sort_locations_non_existing_path tests/unit/test_index.py::TestLink::test_splitext tests/unit/test_index.py::TestLink::test_filename[http://yo/wheel.whl-wheel.whl] tests/unit/test_index.py::TestLink::test_filename[http://yo/wheel-wheel] tests/unit/test_index.py::TestLink::test_filename[http://yo/myproject-1.0%2Bfoobar.0-py2.py3-none-any.whl-myproject-1.0+foobar.0-py2.py3-none-any.whl] tests/unit/test_index.py::TestLink::test_no_ext tests/unit/test_index.py::TestLink::test_ext tests/unit/test_index.py::TestLink::test_ext_fragment tests/unit/test_index.py::TestLink::test_ext_query tests/unit/test_index.py::TestLink::test_is_wheel tests/unit/test_index.py::TestLink::test_is_wheel_false tests/unit/test_index.py::TestLink::test_fragments tests/unit/test_index.py::test_determine_base_url[<html></html>-https://example.com/-https://example.com/] tests/unit/test_index.py::test_determine_base_url[<html><head><base tests/unit/test_index.py::test_determine_base_url[<html><head><base><base tests/unit/test_index.py::test_secure_origin[http://pypi.org/something-trusted0-True] tests/unit/test_index.py::test_secure_origin[https://pypi.org/something-trusted1-False] tests/unit/test_index.py::test_secure_origin[git+http://pypi.org/something-trusted2-True] tests/unit/test_index.py::test_secure_origin[git+https://pypi.org/something-trusted3-False] tests/unit/test_index.py::test_secure_origin[git+ssh://git@pypi.org/something-trusted4-False] tests/unit/test_index.py::test_secure_origin[http://localhost-trusted5-False] tests/unit/test_index.py::test_secure_origin[http://127.0.0.1-trusted6-False] tests/unit/test_index.py::test_secure_origin[http://example.com/something/-trusted7-True] tests/unit/test_index.py::test_secure_origin[http://example.com/something/-trusted8-False] tests/unit/test_index.py::test_secure_origin[http://eXample.com/something/-trusted9-False] tests/unit/test_index.py::test_get_formatted_locations_basic_auth tests/unit/test_index.py::test_find_name_version_sep[pip-18.0-pip-3] tests/unit/test_index.py::test_find_name_version_sep[zope-interface-4.5.0-zope-interface-14] tests/unit/test_index.py::test_find_name_version_sep[Jinja2-2.10-jinja2-6] tests/unit/test_index.py::test_find_name_version_sep[zope.interface-4.5.0-zope-interface-14] tests/unit/test_index.py::test_find_name_version_sep[zope_interface-4.5.0-zope-interface-14] tests/unit/test_index.py::test_find_name_version_sep[foo-2-2-foo-3] tests/unit/test_index.py::test_find_name_version_sep[foo-2-2-foo-2-5] tests/unit/test_index.py::test_find_name_version_sep[foo--bar-1.0-foo-bar-8] tests/unit/test_index.py::test_find_name_version_sep[foo-_bar-1.0-foo-bar-8] tests/unit/test_index.py::test_find_name_version_sep[zope.interface--4.5.0-zope-interface-14] tests/unit/test_index.py::test_find_name_version_sep[zope.interface---zope-interface-14] tests/unit/test_index.py::test_find_name_version_sep[zope.interface--zope-interface-14] tests/unit/test_index.py::test_find_name_version_sep_failure[zope.interface4.5.0-zope-interface] tests/unit/test_index.py::test_find_name_version_sep_failure[zope.interface.4.5.0-zope-interface] tests/unit/test_index.py::test_find_name_version_sep_failure[zope.interface.-4.5.0-zope-interface] tests/unit/test_index.py::test_find_name_version_sep_failure[zope.interface-zope-interface] tests/unit/test_index.py::test_egg_info_matches[pip-18.0-pip-18.0] tests/unit/test_index.py::test_egg_info_matches[zope-interface-4.5.0-zope-interface-4.5.0] tests/unit/test_index.py::test_egg_info_matches[Jinja2-2.10-jinja2-2.10] tests/unit/test_index.py::test_egg_info_matches[zope.interface-4.5.0-zope-interface-4.5.0] tests/unit/test_index.py::test_egg_info_matches[zope_interface-4.5.0-zope-interface-4.5.0] tests/unit/test_index.py::test_egg_info_matches[foo-2-2-foo-2-2_0] tests/unit/test_index.py::test_egg_info_matches[foo-2-2-foo-2-2_1] tests/unit/test_index.py::test_egg_info_matches[zope.interface--4.5.0-zope-interface--4.5.0] tests/unit/test_index.py::test_egg_info_matches[zope.interface---zope-interface--] tests/unit/test_index.py::test_egg_info_matches[foo--bar-1.0-foo-bar-1.0] tests/unit/test_index.py::test_egg_info_matches[foo-_bar-1.0-foo-bar-1.0] tests/unit/test_index.py::test_egg_info_matches[the-package-name-8.19-does-not-match-None] tests/unit/test_index.py::test_egg_info_matches[zope.interface.-4.5.0-zope.interface-None] tests/unit/test_index.py::test_egg_info_matches[zope.interface--zope-interface-None] tests/unit/test_index.py::test_egg_info_matches[zope.interface4.5.0-zope-interface-None] tests/unit/test_index.py::test_egg_info_matches[zope.interface.4.5.0-zope-interface-None] tests/unit/test_index.py::test_egg_info_matches[zope.interface.-4.5.0-zope-interface-None] tests/unit/test_index.py::test_egg_info_matches[zope.interface-zope-interface-None] tests/unit/test_index.py::test_request_http_error tests/unit/test_index.py::test_request_retries tests/unit/test_index.py::test_clean_link[https://localhost.localdomain:8181/path/with tests/unit/test_index.py::test_clean_link[https://localhost.localdomain:8181/path/with%20quoted%20space/-https://localhost.localdomain:8181/path/with%20quoted%20space/] tests/unit/test_index.py::test_clean_link[https://127.0.0.1:8181/path/with tests/unit/test_index.py::test_clean_link[https://[fd00:0:0:236::100]:8181/path/with tests/unit/test_index.py::test_clean_link[https://localhost.localdomain:8181/path/with/query?request=test-https://localhost.localdomain:8181/path/with/query?request=test] tests/unit/test_index.py::test_clean_link[https://localhost.localdomain:8181/path:/with:/colon-https://localhost.localdomain:8181/path%3A/with%3A/colon] tests/unit/test_index.py::test_clean_link[https://localhost.localdomain/T:/path/-https://localhost.localdomain/T%3A/path/] tests/unit/test_index.py::test_clean_link[git+ssh://example.com/path tests/unit/test_index.py::test_clean_link_non_windows[file:///T:/path/with tests/unit/test_legacy_resolve.py::TestCheckDistRequiresPython::test_compatible tests/unit/test_legacy_resolve.py::TestCheckDistRequiresPython::test_invalid_specifier tests/unit/test_legacy_resolve.py::TestCheckDistRequiresPython::test_incompatible tests/unit/test_legacy_resolve.py::TestCheckDistRequiresPython::test_incompatible_with_ignore_requires tests/unit/test_utils.py::Tests_get_installed_distributions::test_editables_only tests/unit/test_utils.py::Tests_get_installed_distributions::test_exclude_editables tests/unit/test_utils.py::Tests_get_installed_distributions::test_include_globals tests/unit/test_utils.py::Tests_get_installed_distributions::test_user_only tests/unit/test_utils.py::Tests_get_installed_distributions::test_gte_py27_excludes tests/unit/test_utils.py::Tests_get_installed_distributions::test_freeze_excludes tests/unit/test_utils.py::test_rmtree_retries tests/unit/test_utils.py::test_rmtree_retries_for_3sec tests/unit/test_utils.py::Test_normalize_path::test_resolve_symlinks tests/unit/test_utils.py::TestHashes::test_success tests/unit/test_utils.py::TestHashes::test_failure tests/unit/test_utils.py::TestHashes::test_missing_hashes tests/unit/test_utils.py::TestHashes::test_unknown_hash tests/unit/test_utils.py::TestHashes::test_non_zero tests/unit/test_utils.py::TestEncoding::test_auto_decode_utf_16_le tests/unit/test_utils.py::TestEncoding::test_auto_decode_utf_16_be tests/unit/test_utils.py::TestEncoding::test_auto_decode_no_bom tests/unit/test_utils.py::TestEncoding::test_auto_decode_pep263_headers tests/unit/test_utils.py::TestEncoding::test_auto_decode_no_preferred_encoding tests/unit/test_utils.py::TestEncoding::test_all_encodings_are_valid[utf-8] tests/unit/test_utils.py::TestEncoding::test_all_encodings_are_valid[utf-16] tests/unit/test_utils.py::TestEncoding::test_all_encodings_are_valid[utf-16-be] tests/unit/test_utils.py::TestEncoding::test_all_encodings_are_valid[utf-16-le] tests/unit/test_utils.py::TestEncoding::test_all_encodings_are_valid[utf-32] tests/unit/test_utils.py::TestEncoding::test_all_encodings_are_valid[utf-32-be] tests/unit/test_utils.py::TestEncoding::test_all_encodings_are_valid[utf-32-le] tests/unit/test_utils.py::TestTempDirectory::test_symlinked_path tests/unit/test_utils.py::TestTempDirectory::test_deletes_readonly_files tests/unit/test_utils.py::TestTempDirectory::test_create_and_cleanup_work tests/unit/test_utils.py::TestTempDirectory::test_adjacent_directory_names[ABC] tests/unit/test_utils.py::TestTempDirectory::test_adjacent_directory_names[ABC.dist-info] tests/unit/test_utils.py::TestTempDirectory::test_adjacent_directory_names[_+-] tests/unit/test_utils.py::TestTempDirectory::test_adjacent_directory_names[_package] tests/unit/test_utils.py::TestTempDirectory::test_adjacent_directory_names[A......B] tests/unit/test_utils.py::TestTempDirectory::test_adjacent_directory_names[AB] tests/unit/test_utils.py::TestTempDirectory::test_adjacent_directory_names[A] tests/unit/test_utils.py::TestTempDirectory::test_adjacent_directory_names[2] tests/unit/test_utils.py::TestTempDirectory::test_adjacent_directory_exists[A] tests/unit/test_utils.py::TestTempDirectory::test_adjacent_directory_exists[ABC] tests/unit/test_utils.py::TestTempDirectory::test_adjacent_directory_exists[ABC.dist-info] tests/unit/test_utils.py::TestTempDirectory::test_adjacent_directory_exists[_+-] tests/unit/test_utils.py::TestTempDirectory::test_adjacent_directory_exists[_package] tests/unit/test_utils.py::TestTempDirectory::test_adjacent_directory_permission_error tests/unit/test_utils.py::TestGlibc::test_manylinux_check_glibc_version tests/unit/test_utils.py::TestGetProg::test_get_prog[/usr/bin/pip--pip] tests/unit/test_utils.py::TestGetProg::test_get_prog[-c-/usr/bin/python-/usr/bin/python tests/unit/test_utils.py::TestGetProg::test_get_prog[__main__.py-/usr/bin/python-/usr/bin/python tests/unit/test_utils.py::TestGetProg::test_get_prog[/usr/bin/pip3--pip3] tests/unit/test_utils.py::test_format_command_args[args0-pip tests/unit/test_utils.py::test_format_command_args[args1-foo tests/unit/test_utils.py::TestCallSubprocess::test_debug_logging tests/unit/test_utils.py::TestCallSubprocess::test_info_logging tests/unit/test_utils.py::TestCallSubprocess::test_info_logging__subprocess_error tests/unit/test_utils.py::TestCallSubprocess::test_info_logging_with_show_stdout_true tests/unit/test_utils.py::TestCallSubprocess::test_spinner_finish[0-False-None-20-expected0] tests/unit/test_utils.py::TestCallSubprocess::test_spinner_finish[0-False-None-10-expected1] tests/unit/test_utils.py::TestCallSubprocess::test_spinner_finish[0-True-None-10-expected2] tests/unit/test_utils.py::TestCallSubprocess::test_spinner_finish[0-True-None-20-expected3] tests/unit/test_utils.py::TestCallSubprocess::test_spinner_finish[0-True-None-30-expected4] tests/unit/test_utils.py::TestCallSubprocess::test_spinner_finish[3-False-None-20-expected5] tests/unit/test_utils.py::TestCallSubprocess::test_spinner_finish[3-False-extra_ok_returncodes6-20-expected6] tests/unit/test_utils.py::TestCallSubprocess::test_closes_stdin tests/unit/test_utils.py::test_split_auth_from_netloc[example.com-expected0] tests/unit/test_utils.py::test_split_auth_from_netloc[user@example.com-expected1] tests/unit/test_utils.py::test_split_auth_from_netloc[user:pass@example.com-expected2] tests/unit/test_utils.py::test_split_auth_from_netloc[user:@example.com-expected3] tests/unit/test_utils.py::test_split_auth_from_netloc[user:pass@word@example.com-expected4] tests/unit/test_utils.py::test_split_auth_from_netloc[user:pass:word@example.com-expected5] tests/unit/test_utils.py::test_split_auth_from_netloc[user%3Aname:%23%40%5E@example.com-expected6] tests/unit/test_utils.py::test_split_auth_netloc_from_url[http://example.com/path#anchor-expected0] tests/unit/test_utils.py::test_split_auth_netloc_from_url[http://user@example.com/path#anchor-expected1] tests/unit/test_utils.py::test_split_auth_netloc_from_url[http://user:pass@example.com/path#anchor-expected2] tests/unit/test_utils.py::test_split_auth_netloc_from_url[http://user:@example.com/path#anchor-expected3] tests/unit/test_utils.py::test_split_auth_netloc_from_url[http://user:pass@word@example.com/path#anchor-expected4] tests/unit/test_utils.py::test_split_auth_netloc_from_url[http://user:pass:word@example.com/path#anchor-expected5] tests/unit/test_utils.py::test_split_auth_netloc_from_url[http://user%3Aname:%23%40%5E@example.com/path#anchor-expected6] tests/unit/test_utils.py::test_redact_netloc[example.com-example.com] tests/unit/test_utils.py::test_redact_netloc[user@example.com-user@example.com] tests/unit/test_utils.py::test_redact_netloc[user:pass@example.com-user:****@example.com] tests/unit/test_utils.py::test_redact_netloc[user:@example.com-user:****@example.com] tests/unit/test_utils.py::test_redact_netloc[user:pass@word@example.com-user:****@example.com] tests/unit/test_utils.py::test_redact_netloc[user:pass:word@example.com-user:****@example.com] tests/unit/test_utils.py::test_redact_netloc[user%3Aname:%23%40%5E@example.com-user%3Aname:****@example.com] tests/unit/test_utils.py::test_remove_auth_from_url[https://user:pass@domain.tld/project/tags/v0.2-https://domain.tld/project/tags/v0.2] tests/unit/test_utils.py::test_remove_auth_from_url[https://domain.tld/project/tags/v0.2-https://domain.tld/project/tags/v0.2] tests/unit/test_utils.py::test_remove_auth_from_url[https://user:pass@domain.tld/svn/project/trunk@8181-https://domain.tld/svn/project/trunk@8181] tests/unit/test_utils.py::test_remove_auth_from_url[https://domain.tld/project/trunk@8181-https://domain.tld/project/trunk@8181] tests/unit/test_utils.py::test_remove_auth_from_url[git+https://pypi.org/something-git+https://pypi.org/something] tests/unit/test_utils.py::test_remove_auth_from_url[git+https://user:pass@pypi.org/something-git+https://pypi.org/something] tests/unit/test_utils.py::test_remove_auth_from_url[git+ssh://git@pypi.org/something-git+ssh://pypi.org/something] tests/unit/test_utils.py::test_redact_password_from_url[https://user@example.com/abc-https://user@example.com/abc] tests/unit/test_utils.py::test_redact_password_from_url[https://user:password@example.com-https://user:****@example.com] tests/unit/test_utils.py::test_redact_password_from_url[https://user:@example.com-https://user:****@example.com] tests/unit/test_utils.py::test_redact_password_from_url[https://example.com-https://example.com] tests/unit/test_utils.py::test_redact_password_from_url[https://user%3Aname:%23%40%5E@example.com-https://user%3Aname:****@example.com] tests/unit/test_utils.py::test_deprecated_message_contains_information[None-None-None] tests/unit/test_utils.py::test_deprecated_message_contains_information[None-None-a tests/unit/test_utils.py::test_deprecated_message_contains_information[988-None-None] tests/unit/test_utils.py::test_deprecated_message_contains_information[988-None-a tests/unit/test_wheel.py::test_contains_egg_info[pip-18.0-True] tests/unit/test_wheel.py::test_contains_egg_info[foo-2-2-True] tests/unit/test_wheel.py::test_contains_egg_info[im-valid-True] tests/unit/test_wheel.py::test_contains_egg_info[invalid-False] tests/unit/test_wheel.py::test_contains_egg_info[im_invalid-False] tests/unit/test_wheel.py::test_should_use_ephemeral_cache__issue_6197[pendulum-2.0.4-False-False-False] tests/unit/test_wheel.py::test_should_use_ephemeral_cache__issue_6197[pendulum-2.0.4-True-True-False] tests/unit/test_wheel.py::test_should_use_ephemeral_cache__issue_6197[pendulum-2.0.4-True-False-True] tests/unit/test_wheel.py::test_should_use_ephemeral_cache__issue_6197[pendulum-True-True-True] tests/unit/test_wheel.py::test_should_use_ephemeral_cache__issue_6197[pendulum-True-False-True] tests/unit/test_wheel.py::test_should_use_ephemeral_cache__disallow_binaries_and_vcs_checkout[False-True] tests/unit/test_wheel.py::test_should_use_ephemeral_cache__disallow_binaries_and_vcs_checkout[True-None] tests/unit/test_wheel.py::test_format_command_result__INFO tests/unit/test_wheel.py::test_format_command_result__DEBUG[output tests/unit/test_wheel.py::test_format_command_result__empty_output[DEBUG] tests/unit/test_wheel.py::test_format_command_result__empty_output[INFO] tests/unit/test_wheel.py::test_get_legacy_build_wheel_path tests/unit/test_wheel.py::test_get_legacy_build_wheel_path__no_names tests/unit/test_wheel.py::test_get_legacy_build_wheel_path__multiple_names tests/unit/test_wheel.py::test_get_entrypoints[pip tests/unit/test_wheel.py::test_get_entrypoints[pip:pip tests/unit/test_wheel.py::test_sorted_outrows[outrows0-expected0] tests/unit/test_wheel.py::test_sorted_outrows[outrows1-expected1] tests/unit/test_wheel.py::test_get_csv_rows_for_installed tests/unit/test_wheel.py::test_get_csv_rows_for_installed__long_lines tests/unit/test_wheel.py::test_wheel_version tests/unit/test_wheel.py::test_python_tag tests/unit/test_wheel.py::test_check_compatibility tests/unit/test_wheel.py::TestWheelFile::test_std_wheel_pattern tests/unit/test_wheel.py::TestWheelFile::test_wheel_pattern_multi_values tests/unit/test_wheel.py::TestWheelFile::test_wheel_with_build_tag tests/unit/test_wheel.py::TestWheelFile::test_single_digit_version tests/unit/test_wheel.py::TestWheelFile::test_non_pep440_version tests/unit/test_wheel.py::TestWheelFile::test_missing_version_raises tests/unit/test_wheel.py::TestWheelFile::test_invalid_filename_raises tests/unit/test_wheel.py::TestWheelFile::test_supported_single_version tests/unit/test_wheel.py::TestWheelFile::test_supported_multi_version tests/unit/test_wheel.py::TestWheelFile::test_not_supported_version tests/unit/test_wheel.py::TestWheelFile::test_supported_osx_version tests/unit/test_wheel.py::TestWheelFile::test_not_supported_osx_version tests/unit/test_wheel.py::TestWheelFile::test_supported_multiarch_darwin tests/unit/test_wheel.py::TestWheelFile::test_not_supported_multiarch_darwin tests/unit/test_wheel.py::TestWheelFile::test_support_index_min tests/unit/test_wheel.py::TestWheelFile::test_support_index_min_none tests/unit/test_wheel.py::TestWheelFile::test_unpack_wheel_no_flatten tests/unit/test_wheel.py::TestWheelFile::test_purelib_platlib tests/unit/test_wheel.py::TestWheelFile::test_version_underscore_conversion tests/unit/test_wheel.py::TestMoveWheelFiles::test_std_install tests/unit/test_wheel.py::TestMoveWheelFiles::test_install_prefix tests/unit/test_wheel.py::TestMoveWheelFiles::test_dist_info_contains_empty_dir tests/unit/test_wheel.py::TestWheelBuilder::test_skip_building_wheels tests/unit/test_wheel.py::TestMessageAboutScriptsNotOnPATH::test_no_script tests/unit/test_wheel.py::TestMessageAboutScriptsNotOnPATH::test_single_script__single_dir_not_on_PATH tests/unit/test_wheel.py::TestMessageAboutScriptsNotOnPATH::test_two_script__single_dir_not_on_PATH tests/unit/test_wheel.py::TestMessageAboutScriptsNotOnPATH::test_multi_script__multi_dir_not_on_PATH tests/unit/test_wheel.py::TestMessageAboutScriptsNotOnPATH::test_multi_script_all__multi_dir_not_on_PATH tests/unit/test_wheel.py::TestMessageAboutScriptsNotOnPATH::test_two_script__single_dir_on_PATH tests/unit/test_wheel.py::TestMessageAboutScriptsNotOnPATH::test_multi_script__multi_dir_on_PATH tests/unit/test_wheel.py::TestMessageAboutScriptsNotOnPATH::test_multi_script__single_dir_on_PATH tests/unit/test_wheel.py::TestMessageAboutScriptsNotOnPATH::test_single_script__single_dir_on_PATH tests/unit/test_wheel.py::TestMessageAboutScriptsNotOnPATH::test_PATH_check_case_insensitive_on_windows tests/unit/test_wheel.py::TestMessageAboutScriptsNotOnPATH::test_trailing_ossep_removal tests/unit/test_wheel.py::TestMessageAboutScriptsNotOnPATH::test_missing_PATH_env_treated_as_empty_PATH_env
news/6549.feature news/5082.feature src/pip/_internal/utils/deprecation.py src/pip/_internal/operations/freeze.py src/pip/_internal/exceptions.py news/6513.bugfix src/pip/_internal/wheel.py src/pip/_internal/index.py src/pip/_internal/vcs/subversion.py news/6121.feature src/pip/_internal/utils/packaging.py news/6386.bugfix
news/6549.feature news/5082.feature src/pip/_internal/utils/deprecation.py src/pip/_internal/operations/freeze.py src/pip/_internal/exceptions.py news/6513.bugfix src/pip/_internal/wheel.py src/pip/_internal/index.py src/pip/_internal/vcs/subversion.py news/6121.feature src/pip/_internal/utils/packaging.py news/6386.bugfix