1
1
Fork 0
mirror of https://github.com/pypa/pip synced 2023-12-13 21:30:23 +01:00

Drop support for EOL Python 3.4 (2) (#6782)

Merge pull request #6782 from hugovk/rm-3.4
This commit is contained in:
Pradyun Gedam 2019-09-10 09:28:11 +05:30 committed by GitHub
commit ceaf514189
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 37 additions and 33 deletions

View file

@ -9,7 +9,7 @@ import os
import shutil import shutil
import sys import sys
from pip._vendor.six import text_type from pip._vendor.six import PY2, text_type
from pip._vendor.urllib3.util import IS_PYOPENSSL from pip._vendor.urllib3.util import IS_PYOPENSSL
from pip._internal.utils.typing import MYPY_CHECK_RUNNING from pip._internal.utils.typing import MYPY_CHECK_RUNNING
@ -47,10 +47,7 @@ logger = logging.getLogger(__name__)
HAS_TLS = (ssl is not None) or IS_PYOPENSSL HAS_TLS = (ssl is not None) or IS_PYOPENSSL
if sys.version_info >= (3, 4): if PY2:
uses_pycache = True
from importlib.util import cache_from_source
else:
import imp import imp
try: try:
@ -60,27 +57,29 @@ else:
cache_from_source = None cache_from_source = None
uses_pycache = cache_from_source is not None uses_pycache = cache_from_source is not None
if sys.version_info >= (3, 5):
backslashreplace_decode = "backslashreplace"
else: else:
# In version 3.4 and older, backslashreplace exists uses_pycache = True
from importlib.util import cache_from_source
if PY2:
# In Python 2.7, backslashreplace exists
# but does not support use for decoding. # but does not support use for decoding.
# We implement our own replace handler for this # We implement our own replace handler for this
# situation, so that we can consistently use # situation, so that we can consistently use
# backslash replacement for all versions. # backslash replacement for all versions.
def backslashreplace_decode_fn(err): def backslashreplace_decode_fn(err):
raw_bytes = (err.object[i] for i in range(err.start, err.end)) raw_bytes = (err.object[i] for i in range(err.start, err.end))
if sys.version_info[0] == 2: # Python 2 gave us characters - convert to numeric bytes
# Python 2 gave us characters - convert to numeric bytes raw_bytes = (ord(b) for b in raw_bytes)
raw_bytes = (ord(b) for b in raw_bytes)
return u"".join(u"\\x%x" % c for c in raw_bytes), err.end return u"".join(u"\\x%x" % c for c in raw_bytes), err.end
codecs.register_error( codecs.register_error(
"backslashreplace_decode", "backslashreplace_decode",
backslashreplace_decode_fn, backslashreplace_decode_fn,
) )
backslashreplace_decode = "backslashreplace_decode" backslashreplace_decode = "backslashreplace_decode"
else:
backslashreplace_decode = "backslashreplace"
def str_to_display(data, desc=None): def str_to_display(data, desc=None):
@ -156,14 +155,7 @@ def console_to_str(data):
return str_to_display(data, desc='Subprocess output') return str_to_display(data, desc='Subprocess output')
if sys.version_info >= (3,): if PY2:
def native_str(s, replace=False):
# type: (str, bool) -> str
if isinstance(s, bytes):
return s.decode('utf-8', 'replace' if replace else 'strict')
return s
else:
def native_str(s, replace=False): def native_str(s, replace=False):
# type: (str, bool) -> str # type: (str, bool) -> str
# Replace is ignored -- unicode to UTF-8 can't fail # Replace is ignored -- unicode to UTF-8 can't fail
@ -171,6 +163,13 @@ else:
return s.encode('utf-8') return s.encode('utf-8')
return s return s
else:
def native_str(s, replace=False):
# type: (str, bool) -> str
if isinstance(s, bytes):
return s.decode('utf-8', 'replace' if replace else 'strict')
return s
def get_path_uid(path): def get_path_uid(path):
# type: (str) -> int # type: (str) -> int
@ -202,17 +201,18 @@ def get_path_uid(path):
return file_uid return file_uid
if sys.version_info >= (3, 4): if PY2:
from importlib.machinery import EXTENSION_SUFFIXES
def get_extension_suffixes():
return EXTENSION_SUFFIXES
else:
from imp import get_suffixes from imp import get_suffixes
def get_extension_suffixes(): def get_extension_suffixes():
return [suffix[0] for suffix in get_suffixes()] return [suffix[0] for suffix in get_suffixes()]
else:
from importlib.machinery import EXTENSION_SUFFIXES
def get_extension_suffixes():
return EXTENSION_SUFFIXES
def expanduser(path): def expanduser(path):
# type: (str) -> str # type: (str) -> str

View file

@ -358,4 +358,4 @@ def in_memory_pip():
@pytest.fixture @pytest.fixture
def deprecated_python(): def deprecated_python():
"""Used to indicate whether pip deprecated this python version""" """Used to indicate whether pip deprecated this python version"""
return sys.version_info[:2] in [(3, 4), (2, 7)] return sys.version_info[:2] in [(2, 7)]

View file

@ -22,6 +22,6 @@ setup(
version='0.0.1', version='0.0.1',
packages=find_packages(), packages=find_packages(),
extras_require={ extras_require={
":python_version == '2.7' or python_version == '3.4'": ['simple'], ":python_version == '2.7'": ['simple'],
} }
) )

View file

@ -7,6 +7,7 @@ import textwrap
from os.path import curdir, join, pardir from os.path import curdir, join, pardir
import pytest import pytest
from pip._vendor.six import PY2
from pip import __version__ as pip_current_version from pip import __version__ as pip_current_version
from pip._internal import pep425tags from pip._internal import pep425tags
@ -29,6 +30,9 @@ from tests.lib.filesystem import make_socket_file
from tests.lib.local_repos import local_checkout from tests.lib.local_repos import local_checkout
from tests.lib.path import Path from tests.lib.path import Path
skip_if_python2 = pytest.mark.skipif(PY2, reason="Non-Python 2 only")
skip_if_not_python2 = pytest.mark.skipif(not PY2, reason="Python 2 only")
@pytest.mark.parametrize('command', ('install', 'wheel')) @pytest.mark.parametrize('command', ('install', 'wheel'))
@pytest.mark.parametrize('variant', ('missing_setuptools', 'bad_setuptools')) @pytest.mark.parametrize('variant', ('missing_setuptools', 'bad_setuptools'))
@ -561,7 +565,7 @@ def test_editable_install__local_dir_no_setup_py_with_pyproject(
assert 'A "pyproject.toml" file was found' in msg assert 'A "pyproject.toml" file was found' in msg
@pytest.mark.skipif("sys.version_info >= (3,4)") @skip_if_not_python2
@pytest.mark.xfail @pytest.mark.xfail
def test_install_argparse_shadowed(script): def test_install_argparse_shadowed(script):
# When argparse is in the stdlib, we support installing it # When argparse is in the stdlib, we support installing it
@ -576,7 +580,7 @@ def test_install_argparse_shadowed(script):
@pytest.mark.network @pytest.mark.network
@pytest.mark.skipif("sys.version_info < (3,4)") @skip_if_python2
def test_upgrade_argparse_shadowed(script): def test_upgrade_argparse_shadowed(script):
# If argparse is installed - even if shadowed for imported - we support # If argparse is installed - even if shadowed for imported - we support
# upgrading it and properly remove the older versions files. # upgrading it and properly remove the older versions files.

View file

@ -99,7 +99,7 @@ class TestRequirementSet(object):
reqset, reqset,
) )
# TODO: Update test when Python 2.7 or Python 3.4 is dropped. # TODO: Update test when Python 2.7 is dropped.
def test_environment_marker_extras(self, data): def test_environment_marker_extras(self, data):
""" """
Test that the environment marker extras are used with Test that the environment marker extras are used with
@ -115,7 +115,7 @@ class TestRequirementSet(object):
resolver = self._basic_resolver(finder) resolver = self._basic_resolver(finder)
resolver.resolve(reqset) resolver.resolve(reqset)
# This is hacky but does test both case in py2 and py3 # This is hacky but does test both case in py2 and py3
if sys.version_info[:2] in ((2, 7), (3, 4)): if sys.version_info[:2] == (2, 7):
assert reqset.has_requirement('simple') assert reqset.has_requirement('simple')
else: else:
assert not reqset.has_requirement('simple') assert not reqset.has_requirement('simple')