Repository: pypa/pip

Issue:
Emit a warning when pip is used on Python 2.6
Python 2.6 is unmaintained by the Python core team, we should encourage users to upgrade.

<!-- Reviewable:start -->

[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/pypa/pip/3329)

<!-- Reviewable:end -->



Discussion:

Resolving patch:
diff --git a/pip/basecommand.py b/pip/basecommand.py
--- a/pip/basecommand.py
+++ b/pip/basecommand.py
@@ -5,6 +5,7 @@
 import os
 import sys
 import optparse
+import warnings
 
 from pip import cmdoptions
 from pip.index import PackageFinder
@@ -20,7 +21,7 @@
     SUCCESS, ERROR, UNKNOWN_ERROR, VIRTUALENV_NOT_FOUND,
     PREVIOUS_BUILD_DIR_ERROR,
 )
-from pip.utils import get_prog, normalize_path
+from pip.utils import deprecation, get_prog, normalize_path
 from pip.utils.logging import IndentingFormatter
 from pip.utils.outdated import pip_version_check
 
@@ -179,6 +180,14 @@ def main(self, args):
             ),
         })
 
+        if sys.version_info[:2] == (2, 6):
+            warnings.warn(
+                "Python 2.6 is no longer supported by the Python core team, "
+                "please upgrade your Python. A future version of pip will "
+                "drop support for Python 2.6",
+                deprecation.Python26DeprecationWarning
+            )
+
         # TODO: try to get these passing down from the command?
         #      without resorting to os.environ to hold these.
 
diff --git a/pip/utils/deprecation.py b/pip/utils/deprecation.py
--- a/pip/utils/deprecation.py
+++ b/pip/utils/deprecation.py
@@ -19,7 +19,15 @@ class RemovedInPip10Warning(PipDeprecationWarning, PendingDeprecationWarning):
     pass
 
 
-DEPRECATIONS = [RemovedInPip9Warning, RemovedInPip10Warning]
+class Python26DeprecationWarning(
+    PipDeprecationWarning, PendingDeprecationWarning
+):
+    pass
+
+
+DEPRECATIONS = [
+    RemovedInPip9Warning, RemovedInPip10Warning, Python26DeprecationWarning
+]
 
 
 # Warnings <-> Logging Integration


Test patch:
diff --git a/tests/functional/test_freeze.py b/tests/functional/test_freeze.py
--- a/tests/functional/test_freeze.py
+++ b/tests/functional/test_freeze.py
@@ -57,12 +57,10 @@ def test_freeze_basic(script):
     )
     result = script.pip('freeze', expect_stderr=True)
     expected = textwrap.dedent("""\
-        Script result: pip freeze
-        -- stdout: --------------------
         ...simple==2.0
         simple2==3.0...
         <BLANKLINE>""")
-    _check_output(result, expected)
+    _check_output(result.stdout, expected)
 
 
 @pytest.mark.svn
@@ -78,11 +76,9 @@ def test_freeze_svn(script, tmpdir):
     )
     result = script.pip('freeze', expect_stderr=True)
     expected = textwrap.dedent("""\
-        Script result: pip freeze
-        -- stdout: --------------------
         ...-e svn+...#egg=version_pkg-0.1-...
         ...""")
-    _check_output(result, expected)
+    _check_output(result.stdout, expected)
 
 
 @pytest.mark.git
@@ -106,13 +102,11 @@ def test_freeze_git_clone(script, tmpdir):
     result = script.pip('freeze', expect_stderr=True)
     expected = textwrap.dedent(
         """
-            Script result: ...pip freeze
-            -- stdout: --------------------
             ...-e git+...#egg=version_pkg-master
             ...
         """
     ).strip()
-    _check_output(result, expected)
+    _check_output(result.stdout, expected)
 
     result = script.pip(
         'freeze', '-f', '%s#egg=pip_test_package' % repo_dir,
@@ -120,14 +114,12 @@ def test_freeze_git_clone(script, tmpdir):
     )
     expected = textwrap.dedent(
         """
-            Script result: pip freeze -f %(repo)s#egg=pip_test_package
-            -- stdout: --------------------
             -f %(repo)s#egg=pip_test_package...
             -e git+...#egg=version_pkg-master
             ...
         """ % {'repo': repo_dir},
     ).strip()
-    _check_output(result, expected)
+    _check_output(result.stdout, expected)
 
     # Check that slashes in branch or tag names are translated.
     # See also issue #1083: https://github.com/pypa/pip/issues/1083
@@ -145,13 +137,11 @@ def test_freeze_git_clone(script, tmpdir):
     result = script.pip('freeze', expect_stderr=True)
     expected = textwrap.dedent(
         """
-            Script result: ...pip freeze
-            -- stdout: --------------------
             ...-e ...@...#egg=version_pkg-branch_name_with_slash...
             ...
         """
     ).strip()
-    _check_output(result, expected)
+    _check_output(result.stdout, expected)
 
 
 @pytest.mark.git
@@ -177,13 +167,11 @@ def test_freeze_git_clone_srcdir(script, tmpdir):
     result = script.pip('freeze', expect_stderr=True)
     expected = textwrap.dedent(
         """
-            Script result: ...pip freeze
-            -- stdout: --------------------
             ...-e git+...#egg=version_pkg-master&subdirectory=subdir
             ...
         """
     ).strip()
-    _check_output(result, expected)
+    _check_output(result.stdout, expected)
 
     result = script.pip(
         'freeze', '-f', '%s#egg=pip_test_package' % repo_dir,
@@ -191,14 +179,12 @@ def test_freeze_git_clone_srcdir(script, tmpdir):
     )
     expected = textwrap.dedent(
         """
-            Script result: pip freeze -f %(repo)s#egg=pip_test_package
-            -- stdout: --------------------
             -f %(repo)s#egg=pip_test_package...
             -e git+...#egg=version_pkg-master&subdirectory=subdir
             ...
         """ % {'repo': repo_dir},
     ).strip()
-    _check_output(result, expected)
+    _check_output(result.stdout, expected)
 
 
 @pytest.mark.mercurial
@@ -223,13 +209,11 @@ def test_freeze_mercurial_clone(script, tmpdir):
     result = script.pip('freeze', expect_stderr=True)
     expected = textwrap.dedent(
         """
-            Script result: ...pip freeze
-            -- stdout: --------------------
             ...-e hg+...#egg=version_pkg-dev
             ...
         """
     ).strip()
-    _check_output(result, expected)
+    _check_output(result.stdout, expected)
 
     result = script.pip(
         'freeze', '-f', '%s#egg=pip_test_package' % repo_dir,
@@ -237,14 +221,12 @@ def test_freeze_mercurial_clone(script, tmpdir):
     )
     expected = textwrap.dedent(
         """
-            Script result: pip freeze -f %(repo)s#egg=pip_test_package
-            -- stdout: --------------------
             -f %(repo)s#egg=pip_test_package...
             ...-e hg+...#egg=version_pkg-dev
             ...
         """ % {'repo': repo_dir},
     ).strip()
-    _check_output(result, expected)
+    _check_output(result.stdout, expected)
 
 
 @pytest.mark.bzr
@@ -268,11 +250,9 @@ def test_freeze_bazaar_clone(script, tmpdir):
     )
     result = script.pip('freeze', expect_stderr=True)
     expected = textwrap.dedent("""\
-        Script result: ...pip freeze
-        -- stdout: --------------------
         ...-e bzr+file://...@1#egg=version_pkg-0.1-...
         ...""")
-    _check_output(result, expected)
+    _check_output(result.stdout, expected)
 
     result = script.pip(
         'freeze', '-f',
@@ -280,12 +260,10 @@ def test_freeze_bazaar_clone(script, tmpdir):
         expect_stderr=True,
     )
     expected = textwrap.dedent("""\
-        Script result: ...pip freeze -f %(repo)s/#egg=django-wikiapp
-        -- stdout: --------------------
         -f %(repo)s/#egg=django-wikiapp
         ...-e bzr+file://...@...#egg=version_pkg-...
         ...""" % {'repo': checkout_path})
-    _check_output(result, expected)
+    _check_output(result.stdout, expected)
 
 
 def test_freeze_with_local_option(script):
@@ -296,8 +274,6 @@ def test_freeze_with_local_option(script):
     result = script.pip_install_local('initools==0.2')
     result = script.pip('freeze', expect_stderr=True)
     expected = textwrap.dedent("""\
-        Script result: ...pip freeze
-        -- stdout: --------------------
         INITools==0.2
         wsgiref==...
         <BLANKLINE>""")
@@ -311,11 +287,9 @@ def test_freeze_with_local_option(script):
 
     result = script.pip('freeze', '--local', expect_stderr=True)
     expected = textwrap.dedent("""\
-        Script result: ...pip freeze --local
-        -- stdout: --------------------
         INITools==0.2
         <BLANKLINE>""")
-    _check_output(result, expected)
+    _check_output(result.stdout, expected)
 
 
 def test_freeze_with_requirement_option(script):
@@ -347,15 +321,14 @@ def test_freeze_with_requirement_option(script):
         expect_stderr=True,
     )
     expected = """\
-Script result: pip freeze --requirement hint.txt
--- stderr: --------------------
-Requirement file contains NoExist==4.2, but that package is not installed
-
--- stdout: --------------------
 INITools==0.2
 simple==3.0
 """ + ignores + "## The following requirements were added by pip freeze:..."
-    _check_output(result, expected)
+    _check_output(result.stdout, expected)
+    assert (
+        "Requirement file contains NoExist==4.2, but that package is not "
+        "installed"
+    ) in result.stderr
 
 
 def test_freeze_user(script, virtualenv):
@@ -367,9 +340,7 @@ def test_freeze_user(script, virtualenv):
     script.pip_install_local('simple2==3.0')
     result = script.pip('freeze', '--user', expect_stderr=True)
     expected = textwrap.dedent("""\
-        Script result: pip freeze --user
-        -- stdout: --------------------
         simple==2.0
         <BLANKLINE>""")
-    _check_output(result, expected)
+    _check_output(result.stdout, expected)
     assert 'simple2' not in result.stdout
diff --git a/tests/functional/test_install.py b/tests/functional/test_install.py
--- a/tests/functional/test_install.py
+++ b/tests/functional/test_install.py
@@ -17,7 +17,7 @@
 
 
 def test_without_setuptools(script, data):
-    script.run("pip", "uninstall", "setuptools", "-y")
+    script.pip("uninstall", "setuptools", "-y")
     result = script.run(
         "python", "-c",
         "import pip; pip.main(["
diff --git a/tests/functional/test_install_upgrade.py b/tests/functional/test_install_upgrade.py
--- a/tests/functional/test_install_upgrade.py
+++ b/tests/functional/test_install_upgrade.py
@@ -354,11 +354,15 @@ def test_from_distribute_6_to_setuptools_7(
         )
         result = self.script.run(
             self.ve_bin / 'pip', 'install', '--no-index',
-            '--find-links=%s' % data.find_links, '-U', 'distribute'
+            '--find-links=%s' % data.find_links, '-U', 'distribute',
+            expect_stderr=True if sys.version_info[:2] == (2, 6) else False,
         )
         assert (
             "Found existing installation: distribute 0.6.34" in result.stdout
         )
-        result = self.script.run(self.ve_bin / 'pip', 'list')
+        result = self.script.run(
+            self.ve_bin / 'pip', 'list',
+            expect_stderr=True if sys.version_info[:2] == (2, 6) else False,
+        )
         assert "setuptools (0.9.8)" in result.stdout
         assert "distribute (0.7.3)" in result.stdout
diff --git a/tests/lib/__init__.py b/tests/lib/__init__.py
--- a/tests/lib/__init__.py
+++ b/tests/lib/__init__.py
@@ -334,6 +334,9 @@ def pip(self, *args, **kwargs):
         if (pyversion_tuple < (2, 7, 9) and
                 args and args[0] in ('search', 'install', 'download')):
             kwargs['expect_stderr'] = True
+        # Python 2.6 is deprecated and we emit a warning on it.
+        if pyversion_tuple[:2] == (2, 6):
+            kwargs['expect_stderr'] = True
 
         return self.run("pip", *args, **kwargs)