Merge pull request #9335 from hugovk/rm-2

Remove redundant Python 2.7 code
This commit is contained in:
Pradyun Gedam 2020-12-23 17:49:30 +00:00 committed by GitHub
commit 1eebb12550
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
67 changed files with 177 additions and 535 deletions

View File

@ -74,10 +74,6 @@ repos:
- id: mypy - id: mypy
exclude: docs|tests exclude: docs|tests
args: ["--pretty"] args: ["--pretty"]
- id: mypy
name: mypy, for Python 2
exclude: noxfile.py|tools/automation/release|docs|tests
args: ["--pretty", "-2"]
- repo: https://github.com/pre-commit/pygrep-hooks - repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.6.0 rev: v1.6.0

View File

@ -79,7 +79,7 @@ To run tests without parallelization, run:
$ tox -e py36 $ tox -e py36
The example above runs tests against Python 3.6. You can also use other The example above runs tests against Python 3.6. You can also use other
versions like ``py27`` and ``pypy3``. versions like ``py39`` and ``pypy3``.
``tox`` has been configured to forward any additional arguments it is given to ``tox`` has been configured to forward any additional arguments it is given to
``pytest``. This enables the use of pytest's `rich CLI`_. As an example, you ``pytest``. This enables the use of pytest's `rich CLI`_. As an example, you

View File

@ -173,4 +173,3 @@ order to create one of these the changes should already be merged into the
.. _`get-pip repository`: https://github.com/pypa/get-pip .. _`get-pip repository`: https://github.com/pypa/get-pip
.. _`psf-salt repository`: https://github.com/python/psf-salt .. _`psf-salt repository`: https://github.com/python/psf-salt
.. _`CPython`: https://github.com/python/cpython .. _`CPython`: https://github.com/python/cpython
.. _`CPython 2.7 EOL date`: https://www.python.org/doc/sunset-python-2/

View File

@ -291,7 +291,7 @@ Since version 6.0, pip also supports specifiers containing `environment markers
:: ::
SomeProject ==5.4 ; python_version < '2.7' SomeProject ==5.4 ; python_version < '3.8'
SomeProject; sys_platform == 'win32' SomeProject; sys_platform == 'win32'
Since version 19.1, pip also supports `direct references Since version 19.1, pip also supports `direct references

View File

@ -41,8 +41,8 @@ Examples
$ python -m pip uninstall simplejson $ python -m pip uninstall simplejson
Uninstalling simplejson: Uninstalling simplejson:
/home/me/env/lib/python2.7/site-packages/simplejson /home/me/env/lib/python3.9/site-packages/simplejson
/home/me/env/lib/python2.7/site-packages/simplejson-2.2.1-py2.7.egg-info /home/me/env/lib/python3.9/site-packages/simplejson-2.2.1-py3.9.egg-info
Proceed (y/n)? y Proceed (y/n)? y
Successfully uninstalled simplejson Successfully uninstalled simplejson
@ -52,7 +52,7 @@ Examples
C:\> py -m pip uninstall simplejson C:\> py -m pip uninstall simplejson
Uninstalling simplejson: Uninstalling simplejson:
/home/me/env/lib/python2.7/site-packages/simplejson /home/me/env/lib/python3.9/site-packages/simplejson
/home/me/env/lib/python2.7/site-packages/simplejson-2.2.1-py2.7.egg-info /home/me/env/lib/python3.9/site-packages/simplejson-2.2.1-py3.9.egg-info
Proceed (y/n)? y Proceed (y/n)? y
Successfully uninstalled simplejson Successfully uninstalled simplejson

1
news/8802.removal.rst Normal file
View File

@ -0,0 +1 @@
Modernise the codebase after Python 2.

View File

@ -9,8 +9,6 @@ import os
import sys import sys
import traceback import traceback
from pip._vendor.six import PY2
from pip._internal.cli import cmdoptions from pip._internal.cli import cmdoptions
from pip._internal.cli.command_context import CommandContextMixIn from pip._internal.cli.command_context import CommandContextMixIn
from pip._internal.cli.parser import ConfigOptionParser, UpdatingDefaultsHelpFormatter from pip._internal.cli.parser import ConfigOptionParser, UpdatingDefaultsHelpFormatter
@ -183,7 +181,7 @@ class Command(CommandContextMixIn):
issue=8333, issue=8333,
) )
if '2020-resolver' in options.features_enabled and not PY2: if '2020-resolver' in options.features_enabled:
logger.warning( logger.warning(
"--use-feature=2020-resolver no longer has any effect, " "--use-feature=2020-resolver no longer has any effect, "
"since it is now the default dependency resolver in pip. " "since it is now the default dependency resolver in pip. "

View File

@ -7,16 +7,15 @@ from __future__ import absolute_import
import logging import logging
import optparse import optparse
import shutil
import sys import sys
import textwrap import textwrap
from distutils.util import strtobool from distutils.util import strtobool
from pip._vendor.contextlib2 import suppress from pip._vendor.contextlib2 import suppress
from pip._vendor.six import string_types
from pip._internal.cli.status_codes import UNKNOWN_ERROR from pip._internal.cli.status_codes import UNKNOWN_ERROR
from pip._internal.configuration import Configuration, ConfigurationError from pip._internal.configuration import Configuration, ConfigurationError
from pip._internal.utils.compat import get_terminal_size
from pip._internal.utils.misc import redact_auth_from_url from pip._internal.utils.misc import redact_auth_from_url
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -29,7 +28,7 @@ class PrettyHelpFormatter(optparse.IndentedHelpFormatter):
# help position must be aligned with __init__.parseopts.description # help position must be aligned with __init__.parseopts.description
kwargs['max_help_position'] = 30 kwargs['max_help_position'] = 30
kwargs['indent_increment'] = 1 kwargs['indent_increment'] = 1
kwargs['width'] = get_terminal_size()[0] - 2 kwargs['width'] = shutil.get_terminal_size()[0] - 2
optparse.IndentedHelpFormatter.__init__(self, *args, **kwargs) optparse.IndentedHelpFormatter.__init__(self, *args, **kwargs)
def format_option_strings(self, option): def format_option_strings(self, option):
@ -119,7 +118,7 @@ class UpdatingDefaultsHelpFormatter(PrettyHelpFormatter):
help_text = optparse.IndentedHelpFormatter.expand_default(self, option) help_text = optparse.IndentedHelpFormatter.expand_default(self, option)
if default_values and option.metavar == 'URL': if default_values and option.metavar == 'URL':
if isinstance(default_values, string_types): if isinstance(default_values, str):
default_values = [default_values] default_values = [default_values]
# If its not a list, we should abort and just return the help text # If its not a list, we should abort and just return the help text
@ -275,7 +274,7 @@ class ConfigOptionParser(CustomOptionParser):
defaults = self._update_defaults(self.defaults.copy()) # ours defaults = self._update_defaults(self.defaults.copy()) # ours
for option in self._get_all_options(): for option in self._get_all_options():
default = defaults.get(option.dest) default = defaults.get(option.dest)
if isinstance(default, string_types): if isinstance(default, str):
opt_str = option.get_opt_string() opt_str = option.get_opt_string()
defaults[option.dest] = option.check_value(opt_str, default) defaults[option.dest] = option.check_value(opt_str, default)
return optparse.Values(defaults) return optparse.Values(defaults)

View File

@ -4,7 +4,6 @@ import itertools
import sys import sys
from signal import SIGINT, default_int_handler, signal from signal import SIGINT, default_int_handler, signal
from pip._vendor import six
from pip._vendor.progress.bar import Bar, FillingCirclesBar, IncrementalBar from pip._vendor.progress.bar import Bar, FillingCirclesBar, IncrementalBar
from pip._vendor.progress.spinner import Spinner from pip._vendor.progress.spinner import Spinner
@ -36,8 +35,8 @@ def _select_progress_class(preferred, fallback):
# Collect all of the possible characters we want to use with the preferred # Collect all of the possible characters we want to use with the preferred
# bar. # bar.
characters = [ characters = [
getattr(preferred, "empty_fill", six.text_type()), getattr(preferred, "empty_fill", ""),
getattr(preferred, "fill", six.text_type()), getattr(preferred, "fill", ""),
] ]
characters += list(getattr(preferred, "phases", [])) characters += list(getattr(preferred, "phases", []))
@ -45,7 +44,7 @@ def _select_progress_class(preferred, fallback):
# of the given file, if this works then we'll assume that we can use the # of the given file, if this works then we'll assume that we can use the
# fancier bar and if not we'll fall back to the plaintext bar. # fancier bar and if not we'll fall back to the plaintext bar.
try: try:
six.text_type().join(characters).encode(encoding) "".join(characters).encode(encoding)
except UnicodeEncodeError: except UnicodeEncodeError:
return fallback return fallback
else: else:

View File

@ -9,8 +9,6 @@ import logging
import os import os
from functools import partial from functools import partial
from pip._vendor.six import PY2
from pip._internal.cli import cmdoptions from pip._internal.cli import cmdoptions
from pip._internal.cli.base_command import Command from pip._internal.cli.base_command import Command
from pip._internal.cli.command_context import CommandContextMixIn from pip._internal.cli.command_context import CommandContextMixIn
@ -200,14 +198,6 @@ class RequirementCommand(IndexGroupCommand):
def determine_resolver_variant(options): def determine_resolver_variant(options):
# type: (Values) -> str # type: (Values) -> str
"""Determines which resolver should be used, based on the given options.""" """Determines which resolver should be used, based on the given options."""
# We didn't want to change things for Python 2, since it's nearly done with
# and we're using performance improvements that only work on Python 3.
if PY2:
if '2020-resolver' in options.features_enabled:
return "2020-resolver"
else:
return "legacy"
if "legacy-resolver" in options.deprecated_features_enabled: if "legacy-resolver" in options.deprecated_features_enabled:
return "legacy" return "legacy"

View File

@ -3,8 +3,6 @@ from __future__ import absolute_import
import json import json
import logging import logging
from pip._vendor import six
from pip._internal.cli import cmdoptions from pip._internal.cli import cmdoptions
from pip._internal.cli.req_command import IndexGroupCommand from pip._internal.cli.req_command import IndexGroupCommand
from pip._internal.cli.status_codes import SUCCESS from pip._internal.cli.status_codes import SUCCESS
@ -315,13 +313,13 @@ def format_for_json(packages, options):
for dist in packages: for dist in packages:
info = { info = {
'name': dist.project_name, 'name': dist.project_name,
'version': six.text_type(dist.version), 'version': str(dist.version),
} }
if options.verbose >= 1: if options.verbose >= 1:
info['location'] = dist.location info['location'] = dist.location
info['installer'] = get_installer(dist) info['installer'] = get_installer(dist)
if options.outdated: if options.outdated:
info['latest_version'] = six.text_type(dist.latest_version) info['latest_version'] = str(dist.latest_version)
info['latest_filetype'] = dist.latest_filetype info['latest_filetype'] = dist.latest_filetype
data.append(info) data.append(info)
return json.dumps(data) return json.dumps(data)

View File

@ -1,6 +1,7 @@
from __future__ import absolute_import from __future__ import absolute_import
import logging import logging
import shutil
import sys import sys
import textwrap import textwrap
from collections import OrderedDict from collections import OrderedDict
@ -18,7 +19,6 @@ from pip._internal.cli.status_codes import NO_MATCHES_FOUND, SUCCESS
from pip._internal.exceptions import CommandError from pip._internal.exceptions import CommandError
from pip._internal.models.index import PyPI from pip._internal.models.index import PyPI
from pip._internal.network.xmlrpc import PipXmlrpcTransport from pip._internal.network.xmlrpc import PipXmlrpcTransport
from pip._internal.utils.compat import get_terminal_size
from pip._internal.utils.logging import indent_log from pip._internal.utils.logging import indent_log
from pip._internal.utils.misc import get_distribution, write_output from pip._internal.utils.misc import get_distribution, write_output
from pip._internal.utils.typing import MYPY_CHECK_RUNNING from pip._internal.utils.typing import MYPY_CHECK_RUNNING
@ -64,7 +64,7 @@ class SearchCommand(Command, SessionCommandMixin):
terminal_width = None terminal_width = None
if sys.stdout.isatty(): if sys.stdout.isatty():
terminal_width = get_terminal_size()[0] terminal_width = shutil.get_terminal_size()[0]
print_results(hits, terminal_width=terminal_width) print_results(hits, terminal_width=terminal_width)
if pypi_hits: if pypi_hits:

View File

@ -11,13 +11,12 @@ Some terminology:
A single word describing where the configuration key-value pair came from A single word describing where the configuration key-value pair came from
""" """
import configparser
import locale import locale
import logging import logging
import os import os
import sys import sys
from pip._vendor.six.moves import configparser
from pip._internal.exceptions import ( from pip._internal.exceptions import (
ConfigurationError, ConfigurationError,
ConfigurationFileCouldNotBeLoaded, ConfigurationFileCouldNotBeLoaded,

View File

@ -1,7 +1,5 @@
import abc import abc
from pip._vendor.six import add_metaclass
from pip._internal.utils.typing import MYPY_CHECK_RUNNING from pip._internal.utils.typing import MYPY_CHECK_RUNNING
if MYPY_CHECK_RUNNING: if MYPY_CHECK_RUNNING:
@ -13,8 +11,7 @@ if MYPY_CHECK_RUNNING:
from pip._internal.req import InstallRequirement from pip._internal.req import InstallRequirement
@add_metaclass(abc.ABCMeta) class AbstractDistribution(object, metaclass=abc.ABCMeta):
class AbstractDistribution(object):
"""A base class for handling installable artifacts. """A base class for handling installable artifacts.
The requirements for anything installable are as follows: The requirements for anything installable are as follows:
@ -29,7 +26,6 @@ class AbstractDistribution(object):
- we must be able to create a Distribution object exposing the - we must be able to create a Distribution object exposing the
above metadata. above metadata.
""" """
def __init__(self, req): def __init__(self, req):
# type: (InstallRequirement) -> None # type: (InstallRequirement) -> None
super(AbstractDistribution, self).__init__() super(AbstractDistribution, self).__init__()

View File

@ -4,25 +4,18 @@ from __future__ import absolute_import
from itertools import chain, groupby, repeat from itertools import chain, groupby, repeat
from pip._vendor.six import iteritems
from pip._internal.utils.typing import MYPY_CHECK_RUNNING from pip._internal.utils.typing import MYPY_CHECK_RUNNING
if MYPY_CHECK_RUNNING: if MYPY_CHECK_RUNNING:
import configparser
from hashlib import _Hash
from typing import Any, Dict, List, Optional, Text from typing import Any, Dict, List, Optional, Text
from pip._vendor.pkg_resources import Distribution from pip._vendor.pkg_resources import Distribution
from pip._vendor.requests.models import Request, Response from pip._vendor.requests.models import Request, Response
from pip._vendor.six import PY3
from pip._vendor.six.moves import configparser
from pip._internal.req.req_install import InstallRequirement from pip._internal.req.req_install import InstallRequirement
if PY3:
from hashlib import _Hash
else:
from hashlib import _hash as _Hash
class PipError(Exception): class PipError(Exception):
"""Base pip exception""" """Base pip exception"""
@ -346,7 +339,7 @@ class HashMismatch(HashError):
return chain([hash_name], repeat(' or')) return chain([hash_name], repeat(' or'))
lines = [] # type: List[str] lines = [] # type: List[str]
for hash_name, expecteds in iteritems(self.allowed): for hash_name, expecteds in self.allowed.items():
prefix = hash_then_or(hash_name) prefix = hash_then_or(hash_name)
lines.extend((' Expected {} {}'.format(next(prefix), e)) lines.extend((' Expected {} {}'.format(next(prefix), e))
for e in expecteds) for e in expecteds)

View File

@ -10,12 +10,12 @@ import mimetypes
import os import os
import re import re
from collections import OrderedDict from collections import OrderedDict
from urllib import parse as urllib_parse
from urllib import request as urllib_request
from pip._vendor import html5lib, requests from pip._vendor import html5lib, requests
from pip._vendor.distlib.compat import unescape from pip._vendor.distlib.compat import unescape
from pip._vendor.requests.exceptions import RetryError, SSLError from pip._vendor.requests.exceptions import RetryError, SSLError
from pip._vendor.six.moves.urllib import parse as urllib_parse
from pip._vendor.six.moves.urllib import request as urllib_request
from pip._internal.exceptions import NetworkConnectionError from pip._internal.exceptions import NetworkConnectionError
from pip._internal.models.link import Link from pip._internal.models.link import Link

View File

@ -1,9 +1,7 @@
""" PEP 610 """ """ PEP 610 """
import json import json
import re import re
from urllib import parse as urllib_parse
from pip._vendor import six
from pip._vendor.six.moves.urllib import parse as urllib_parse
from pip._internal.utils.typing import MYPY_CHECK_RUNNING from pip._internal.utils.typing import MYPY_CHECK_RUNNING
@ -35,8 +33,6 @@ def _get(d, expected_type, key, default=None):
if key not in d: if key not in d:
return default return default
value = d[key] value = d[key]
if six.PY2 and expected_type is str:
expected_type = six.string_types # type: ignore
if not isinstance(value, expected_type): if not isinstance(value, expected_type):
raise DirectUrlValidationError( raise DirectUrlValidationError(
"{!r} has unexpected type for {} (expected {})".format( "{!r} has unexpected type for {} (expected {})".format(

View File

@ -1,4 +1,4 @@
from pip._vendor.six.moves.urllib import parse as urllib_parse from urllib import parse as urllib_parse
class PackageIndex(object): class PackageIndex(object):

View File

@ -1,8 +1,7 @@
import os import os
import posixpath import posixpath
import re import re
from urllib import parse as urllib_parse
from pip._vendor.six.moves.urllib import parse as urllib_parse
from pip._internal.utils.filetypes import WHEEL_EXTENSION from pip._internal.utils.filetypes import WHEEL_EXTENSION
from pip._internal.utils.misc import ( from pip._internal.utils.misc import (

View File

@ -2,9 +2,9 @@ import itertools
import logging import logging
import os import os
import posixpath import posixpath
from urllib import parse as urllib_parse
from pip._vendor.packaging.utils import canonicalize_name from pip._vendor.packaging.utils import canonicalize_name
from pip._vendor.six.moves.urllib import parse as urllib_parse
from pip._internal.models.index import PyPI from pip._internal.models.index import PyPI
from pip._internal.utils.compat import has_tls from pip._internal.utils.compat import has_tls

View File

@ -5,10 +5,10 @@ providing credentials in the context of network requests.
""" """
import logging import logging
from urllib import parse as urllib_parse
from pip._vendor.requests.auth import AuthBase, HTTPBasicAuth from pip._vendor.requests.auth import AuthBase, HTTPBasicAuth
from pip._vendor.requests.utils import get_netrc_auth from pip._vendor.requests.utils import get_netrc_auth
from pip._vendor.six.moves.urllib import parse as urllib_parse
from pip._internal.utils.misc import ( from pip._internal.utils.misc import (
ask, ask,

View File

@ -8,7 +8,6 @@ from tempfile import NamedTemporaryFile
from zipfile import BadZipfile, ZipFile from zipfile import BadZipfile, ZipFile
from pip._vendor.requests.models import CONTENT_CHUNK_SIZE from pip._vendor.requests.models import CONTENT_CHUNK_SIZE
from pip._vendor.six.moves import range
from pip._internal.network.utils import HEADERS, raise_for_status, response_chunks from pip._internal.network.utils import HEADERS, raise_for_status, response_chunks
from pip._internal.utils.typing import MYPY_CHECK_RUNNING from pip._internal.utils.typing import MYPY_CHECK_RUNNING

View File

@ -13,13 +13,13 @@ import os
import platform import platform
import sys import sys
import warnings import warnings
from urllib import parse as urllib_parse
from pip._vendor import requests, six, urllib3 from pip._vendor import requests, six, urllib3
from pip._vendor.cachecontrol import CacheControlAdapter from pip._vendor.cachecontrol import CacheControlAdapter
from pip._vendor.requests.adapters import BaseAdapter, HTTPAdapter from pip._vendor.requests.adapters import BaseAdapter, HTTPAdapter
from pip._vendor.requests.models import Response from pip._vendor.requests.models import Response
from pip._vendor.requests.structures import CaseInsensitiveDict from pip._vendor.requests.structures import CaseInsensitiveDict
from pip._vendor.six.moves.urllib import parse as urllib_parse
from pip._vendor.urllib3.exceptions import InsecureRequestWarning from pip._vendor.urllib3.exceptions import InsecureRequestWarning
from pip import __version__ from pip import __version__

View File

@ -2,11 +2,11 @@
""" """
import logging import logging
from urllib import parse as urllib_parse
# NOTE: XMLRPC Client is not annotated in typeshed as on 2017-07-17, which is # NOTE: XMLRPC Client is not annotated in typeshed as on 2017-07-17, which is
# why we ignore the type on this import # why we ignore the type on this import
from pip._vendor.six.moves import xmlrpc_client # type: ignore from pip._vendor.six.moves import xmlrpc_client # type: ignore
from pip._vendor.six.moves.urllib import parse as urllib_parse
from pip._internal.exceptions import NetworkConnectionError from pip._internal.exceptions import NetworkConnectionError
from pip._internal.network.utils import raise_for_status from pip._internal.network.utils import raise_for_status

View File

@ -4,7 +4,6 @@ import collections
import logging import logging
import os import os
from pip._vendor import six
from pip._vendor.packaging.utils import canonicalize_name from pip._vendor.packaging.utils import canonicalize_name
from pip._vendor.pkg_resources import RequirementParseError from pip._vendor.pkg_resources import RequirementParseError
@ -162,7 +161,7 @@ def freeze(
# Warn about requirements that were included multiple times (in a # Warn about requirements that were included multiple times (in a
# single requirements file or in different requirements files). # single requirements file or in different requirements files).
for name, files in six.iteritems(req_files): for name, files in req_files.items():
if len(files) > 1: if len(files) > 1:
logger.warning("Requirement %s included multiple times [%s]", logger.warning("Requirement %s included multiple times [%s]",
name, ', '.join(sorted(set(files)))) name, ', '.join(sorted(set(files))))

View File

@ -15,14 +15,13 @@ import shutil
import sys import sys
import warnings import warnings
from base64 import urlsafe_b64encode from base64 import urlsafe_b64encode
from itertools import chain, starmap from itertools import chain, filterfalse, starmap
from zipfile import ZipFile from zipfile import ZipFile
from pip._vendor import pkg_resources from pip._vendor import pkg_resources
from pip._vendor.distlib.scripts import ScriptMaker from pip._vendor.distlib.scripts import ScriptMaker
from pip._vendor.distlib.util import get_export_entry from pip._vendor.distlib.util import get_export_entry
from pip._vendor.six import PY2, ensure_str, ensure_text, itervalues, reraise, text_type from pip._vendor.six import ensure_str, ensure_text, reraise
from pip._vendor.six.moves import filterfalse, map
from pip._internal.exceptions import InstallationError from pip._internal.exceptions import InstallationError
from pip._internal.locations import get_major_minor_version from pip._internal.locations import get_major_minor_version
@ -70,12 +69,12 @@ else:
from pip._internal.models.scheme import Scheme from pip._internal.models.scheme import Scheme
from pip._internal.utils.filesystem import NamedTemporaryFileResult from pip._internal.utils.filesystem import NamedTemporaryFileResult
RecordPath = NewType('RecordPath', text_type) RecordPath = NewType('RecordPath', str)
InstalledCSVRow = Tuple[RecordPath, str, Union[int, str]] InstalledCSVRow = Tuple[RecordPath, str, Union[int, str]]
class File(Protocol): class File(Protocol):
src_record_path = None # type: RecordPath src_record_path = None # type: RecordPath
dest_path = None # type: text_type dest_path = None # type: str
changed = None # type: bool changed = None # type: bool
def save(self): def save(self):
@ -87,7 +86,7 @@ logger = logging.getLogger(__name__)
def rehash(path, blocksize=1 << 20): def rehash(path, blocksize=1 << 20):
# type: (text_type, int) -> Tuple[str, str] # type: (str, int) -> Tuple[str, str]
"""Return (encoded_digest, length) for path using hashlib.sha256()""" """Return (encoded_digest, length) for path using hashlib.sha256()"""
h, length = hash_file(path, blocksize) h, length = hash_file(path, blocksize)
digest = 'sha256=' + urlsafe_b64encode( digest = 'sha256=' + urlsafe_b64encode(
@ -102,14 +101,11 @@ def csv_io_kwargs(mode):
"""Return keyword arguments to properly open a CSV file """Return keyword arguments to properly open a CSV file
in the given mode. in the given mode.
""" """
if PY2: return {'mode': mode, 'newline': '', 'encoding': 'utf-8'}
return {'mode': '{}b'.format(mode)}
else:
return {'mode': mode, 'newline': '', 'encoding': 'utf-8'}
def fix_script(path): def fix_script(path):
# type: (text_type) -> bool # type: (str) -> bool
"""Replace #!python with #!/path/to/python """Replace #!python with #!/path/to/python
Return True if file was changed. Return True if file was changed.
""" """
@ -257,12 +253,12 @@ def _normalized_outrows(outrows):
def _record_to_fs_path(record_path): def _record_to_fs_path(record_path):
# type: (RecordPath) -> text_type # type: (RecordPath) -> str
return record_path return record_path
def _fs_to_record_path(path, relative_to=None): def _fs_to_record_path(path, relative_to=None):
# type: (text_type, Optional[text_type]) -> RecordPath # type: (str, Optional[str]) -> RecordPath
if relative_to is not None: if relative_to is not None:
# On Windows, do not handle relative paths if they belong to different # On Windows, do not handle relative paths if they belong to different
# logical disks # logical disks
@ -307,7 +303,7 @@ def get_csv_rows_for_installed(
path = _fs_to_record_path(f, lib_dir) path = _fs_to_record_path(f, lib_dir)
digest, length = rehash(f) digest, length = rehash(f)
installed_rows.append((path, digest, length)) installed_rows.append((path, digest, length))
for installed_record_path in itervalues(installed): for installed_record_path in installed.values():
installed_rows.append((installed_record_path, '', '')) installed_rows.append((installed_record_path, '', ''))
return installed_rows return installed_rows
@ -400,7 +396,7 @@ def get_console_script_specs(console):
class ZipBackedFile(object): class ZipBackedFile(object):
def __init__(self, src_record_path, dest_path, zip_file): def __init__(self, src_record_path, dest_path, zip_file):
# type: (RecordPath, text_type, ZipFile) -> None # type: (RecordPath, str, ZipFile) -> None
self.src_record_path = src_record_path self.src_record_path = src_record_path
self.dest_path = dest_path self.dest_path = dest_path
self._zip_file = zip_file self._zip_file = zip_file
@ -408,12 +404,7 @@ class ZipBackedFile(object):
def _getinfo(self): def _getinfo(self):
# type: () -> ZipInfo # type: () -> ZipInfo
if not PY2: return self._zip_file.getinfo(self.src_record_path)
return self._zip_file.getinfo(self.src_record_path)
# Python 2 does not expose a way to detect a ZIP's encoding, but the
# wheel specification (PEP 427) explicitly mandates that paths should
# use UTF-8, so we assume it is true.
return self._zip_file.getinfo(self.src_record_path.encode("utf-8"))
def save(self): def save(self):
# type: () -> None # type: () -> None
@ -525,7 +516,7 @@ def _install_wheel(
generated = [] # type: List[str] generated = [] # type: List[str]
def record_installed(srcfile, destfile, modified=False): def record_installed(srcfile, destfile, modified=False):
# type: (RecordPath, text_type, bool) -> None # type: (RecordPath, str, bool) -> None
"""Map archive RECORD paths to installation RECORD paths.""" """Map archive RECORD paths to installation RECORD paths."""
newpath = _fs_to_record_path(destfile, lib_dir) newpath = _fs_to_record_path(destfile, lib_dir)
installed[srcfile] = newpath installed[srcfile] = newpath
@ -546,7 +537,7 @@ def _install_wheel(
return path.endswith("/") return path.endswith("/")
def assert_no_path_traversal(dest_dir_path, target_path): def assert_no_path_traversal(dest_dir_path, target_path):
# type: (text_type, text_type) -> None # type: (str, str) -> None
if not is_within_directory(dest_dir_path, target_path): if not is_within_directory(dest_dir_path, target_path):
message = ( message = (
"The wheel {!r} has a file {!r} trying to install" "The wheel {!r} has a file {!r} trying to install"
@ -557,7 +548,7 @@ def _install_wheel(
) )
def root_scheme_file_maker(zip_file, dest): def root_scheme_file_maker(zip_file, dest):
# type: (ZipFile, text_type) -> Callable[[RecordPath], File] # type: (ZipFile, str) -> Callable[[RecordPath], File]
def make_root_scheme_file(record_path): def make_root_scheme_file(record_path):
# type: (RecordPath) -> File # type: (RecordPath) -> File
normed_path = os.path.normpath(record_path) normed_path = os.path.normpath(record_path)
@ -675,7 +666,7 @@ def _install_wheel(
record_installed(file.src_record_path, file.dest_path, file.changed) record_installed(file.src_record_path, file.dest_path, file.changed)
def pyc_source_file_paths(): def pyc_source_file_paths():
# type: () -> Iterator[text_type] # type: () -> Iterator[str]
# We de-duplicate installation paths, since there can be overlap (e.g. # We de-duplicate installation paths, since there can be overlap (e.g.
# file in .data maps to same location as file in wheel root). # file in .data maps to same location as file in wheel root).
# Sorting installation paths makes it easier to reproduce and debug # Sorting installation paths makes it easier to reproduce and debug
@ -689,16 +680,10 @@ def _install_wheel(
yield full_installed_path yield full_installed_path
def pyc_output_path(path): def pyc_output_path(path):
# type: (text_type) -> text_type # type: (str) -> str
"""Return the path the pyc file would have been written to. """Return the path the pyc file would have been written to.
""" """
if PY2: return importlib.util.cache_from_source(path)
if sys.flags.optimize:
return path + 'o'
else:
return path + 'c'
else:
return importlib.util.cache_from_source(path)
# Compile all of the pyc files for the installed files # Compile all of the pyc files for the installed files
if pycompile: if pycompile:

View File

@ -10,7 +10,6 @@ import os
import shutil import shutil
from pip._vendor.packaging.utils import canonicalize_name from pip._vendor.packaging.utils import canonicalize_name
from pip._vendor.six import PY2
from pip._internal.distributions import make_distribution_for_install_requirement from pip._internal.distributions import make_distribution_for_install_requirement
from pip._internal.distributions.installed import InstalledDistribution from pip._internal.distributions.installed import InstalledDistribution
@ -51,26 +50,16 @@ if MYPY_CHECK_RUNNING:
from pip._internal.req.req_tracker import RequirementTracker from pip._internal.req.req_tracker import RequirementTracker
from pip._internal.utils.hashes import Hashes from pip._internal.utils.hashes import Hashes
if PY2: CopytreeKwargs = TypedDict(
CopytreeKwargs = TypedDict( 'CopytreeKwargs',
'CopytreeKwargs', {
{ 'copy_function': Callable[[str, str], None],
'ignore': Callable[[str, List[str]], List[str]], 'ignore': Callable[[str, List[str]], List[str]],
'symlinks': bool, 'ignore_dangling_symlinks': bool,
}, 'symlinks': bool,
total=False, },
) total=False,
else: )
CopytreeKwargs = TypedDict(
'CopytreeKwargs',
{
'copy_function': Callable[[str, str], None],
'ignore': Callable[[str, List[str]], List[str]],
'ignore_dangling_symlinks': bool,
'symlinks': bool,
},
total=False,
)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -177,14 +166,13 @@ def _copy_source_tree(source, target):
skipped += [target_basename] skipped += [target_basename]
return skipped return skipped
kwargs = dict(ignore=ignore, symlinks=True) # type: CopytreeKwargs shutil.copytree(
source,
if not PY2: target,
# Python 2 does not support copy_function, so we only ignore ignore=ignore,
# errors on special file copy in Python 3. symlinks=True,
kwargs['copy_function'] = _copy2_ignoring_special_files copy_function=_copy2_ignoring_special_files,
)
shutil.copytree(source, target, **kwargs)
def get_file_url( def get_file_url(

View File

@ -2,10 +2,9 @@ from __future__ import absolute_import
import io import io
import os import os
import sys
from collections import namedtuple from collections import namedtuple
from pip._vendor import six, toml from pip._vendor import toml
from pip._vendor.packaging.requirements import InvalidRequirement, Requirement from pip._vendor.packaging.requirements import InvalidRequirement, Requirement
from pip._internal.exceptions import InstallationError from pip._internal.exceptions import InstallationError
@ -19,19 +18,13 @@ def _is_list_of_str(obj):
# type: (Any) -> bool # type: (Any) -> bool
return ( return (
isinstance(obj, list) and isinstance(obj, list) and
all(isinstance(item, six.string_types) for item in obj) all(isinstance(item, str) for item in obj)
) )
def make_pyproject_path(unpacked_source_directory): def make_pyproject_path(unpacked_source_directory):
# type: (str) -> str # type: (str) -> str
path = os.path.join(unpacked_source_directory, 'pyproject.toml') return os.path.join(unpacked_source_directory, 'pyproject.toml')
# Python2 __file__ should not be unicode
if six.PY2 and isinstance(path, six.text_type):
path = path.encode(sys.getfilesystemencoding())
return path
BuildSystemDetails = namedtuple('BuildSystemDetails', [ BuildSystemDetails = namedtuple('BuildSystemDetails', [

View File

@ -8,9 +8,7 @@ import optparse
import os import os
import re import re
import shlex import shlex
import sys from urllib import parse as urllib_parse
from pip._vendor.six.moves.urllib import parse as urllib_parse
from pip._internal.cli import cmdoptions from pip._internal.cli import cmdoptions
from pip._internal.exceptions import InstallationError, RequirementsFileParseError from pip._internal.exceptions import InstallationError, RequirementsFileParseError
@ -410,10 +408,6 @@ def get_line_parser(finder):
defaults.format_control = finder.format_control defaults.format_control = finder.format_control
args_str, options_str = break_args_options(line) args_str, options_str = break_args_options(line)
# Prior to 2.7.3, shlex cannot deal with unicode entries
if sys.version_info < (2, 7, 3):
# https://github.com/python/mypy/issues/1174
options_str = options_str.encode('utf8') # type: ignore
# https://github.com/python/mypy/issues/1174 # https://github.com/python/mypy/issues/1174
opts, _ = parser.parse_args( opts, _ = parser.parse_args(

View File

@ -223,7 +223,7 @@ class InstallRequirement(object):
if self.satisfied_by is not None: if self.satisfied_by is not None:
s += ' in {}'.format(display_path(self.satisfied_by.location)) s += ' in {}'.format(display_path(self.satisfied_by.location))
if self.comes_from: if self.comes_from:
if isinstance(self.comes_from, six.string_types): if isinstance(self.comes_from, str):
comes_from = self.comes_from # type: Optional[str] comes_from = self.comes_from # type: Optional[str]
else: else:
comes_from = self.comes_from.from_path() comes_from = self.comes_from.from_path()
@ -334,7 +334,7 @@ class InstallRequirement(object):
return None return None
s = str(self.req) s = str(self.req)
if self.comes_from: if self.comes_from:
if isinstance(self.comes_from, six.string_types): if isinstance(self.comes_from, str):
comes_from = self.comes_from comes_from = self.comes_from
else: else:
comes_from = self.comes_from.from_path() comes_from = self.comes_from.from_path()
@ -480,10 +480,6 @@ class InstallRequirement(object):
assert self.source_dir, "No source dir for {}".format(self) assert self.source_dir, "No source dir for {}".format(self)
setup_py = os.path.join(self.unpacked_source_directory, 'setup.py') setup_py = os.path.join(self.unpacked_source_directory, 'setup.py')
# Python2 __file__ should not be unicode
if six.PY2 and isinstance(setup_py, six.text_type):
setup_py = setup_py.encode(sys.getfilesystemencoding())
return setup_py return setup_py
@property @property

View File

@ -6,12 +6,13 @@ import logging
import os import os
import sys import sys
import sysconfig import sysconfig
from importlib.util import cache_from_source
from pip._vendor import pkg_resources from pip._vendor import pkg_resources
from pip._internal.exceptions import UninstallationError from pip._internal.exceptions import UninstallationError
from pip._internal.locations import bin_py, bin_user from pip._internal.locations import bin_py, bin_user
from pip._internal.utils.compat import WINDOWS, cache_from_source, uses_pycache from pip._internal.utils.compat import WINDOWS
from pip._internal.utils.logging import indent_log from pip._internal.utils.logging import indent_log
from pip._internal.utils.misc import ( from pip._internal.utils.misc import (
FakeFile, FakeFile,
@ -363,7 +364,7 @@ class UninstallPathSet(object):
# __pycache__ files can show up after 'installed-files.txt' is created, # __pycache__ files can show up after 'installed-files.txt' is created,
# due to imports # due to imports
if os.path.splitext(path)[1] == '.py' and uses_pycache: if os.path.splitext(path)[1] == '.py':
self.add(cache_from_source(path)) self.add(cache_from_source(path))
def add_pth(self, pth_file, entry): def add_pth(self, pth_file, entry):
@ -609,7 +610,7 @@ class UninstallPthEntries(object):
# treats non-absolute paths with drive letter markings like c:foo\bar # treats non-absolute paths with drive letter markings like c:foo\bar
# as absolute paths. It also does not recognize UNC paths if they don't # as absolute paths. It also does not recognize UNC paths if they don't
# have more than "\\sever\share". Valid examples: "\\server\share\" or # have more than "\\sever\share". Valid examples: "\\server\share\" or
# "\\server\share\folder". Python 2.7.8+ support UNC in splitdrive. # "\\server\share\folder".
if WINDOWS and not os.path.splitdrive(entry)[0]: if WINDOWS and not os.path.splitdrive(entry)[0]:
entry = entry.replace('\\', '/') entry = entry.replace('\\', '/')
self.entries.add(entry) self.entries.add(entry)

View File

@ -11,15 +11,12 @@ import functools
import locale import locale
import logging import logging
import os import os
import shutil
import sys import sys
from pip._vendor.six import PY2, text_type
from pip._internal.utils.typing import MYPY_CHECK_RUNNING from pip._internal.utils.typing import MYPY_CHECK_RUNNING
if MYPY_CHECK_RUNNING: if MYPY_CHECK_RUNNING:
from typing import Callable, Optional, Protocol, Text, Tuple, TypeVar, Union from typing import Callable, Optional, Protocol, Text, TypeVar, Union
# Used in the @lru_cache polyfill. # Used in the @lru_cache polyfill.
F = TypeVar('F') F = TypeVar('F')
@ -41,47 +38,13 @@ except ImportError:
__all__ = [ __all__ = [
"ipaddress", "uses_pycache", "console_to_str", "ipaddress", "console_to_str",
"get_path_uid", "stdlib_pkgs", "WINDOWS", "samefile", "get_terminal_size", "get_path_uid", "stdlib_pkgs", "WINDOWS",
] ]
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
if PY2:
import imp
try:
cache_from_source = imp.cache_from_source # type: ignore
except AttributeError:
# does not use __pycache__
cache_from_source = None
uses_pycache = cache_from_source is not None
else:
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.
# We implement our own replace handler for this
# situation, so that we can consistently use
# backslash replacement for all versions.
def backslashreplace_decode_fn(err):
raw_bytes = (err.object[i] for i in range(err.start, err.end))
# Python 2 gave us characters - convert to numeric bytes
raw_bytes = (ord(b) for b in raw_bytes)
return u"".join(map(u"\\x{:x}".format, raw_bytes)), err.end
codecs.register_error(
"backslashreplace_decode",
backslashreplace_decode_fn,
)
backslashreplace_decode = "backslashreplace_decode"
else:
backslashreplace_decode = "backslashreplace"
def has_tls(): def has_tls():
# type: () -> bool # type: () -> bool
@ -114,7 +77,7 @@ def str_to_display(data, desc=None):
We also ensure that the output can be safely written to standard output We also ensure that the output can be safely written to standard output
without encoding errors. without encoding errors.
""" """
if isinstance(data, text_type): if isinstance(data, str):
return data return data
# Otherwise, data is a bytes object (str in Python 2). # Otherwise, data is a bytes object (str in Python 2).
@ -135,7 +98,7 @@ def str_to_display(data, desc=None):
desc or 'Bytes object', desc or 'Bytes object',
encoding, encoding,
) )
decoded_data = data.decode(encoding, errors=backslashreplace_decode) decoded_data = data.decode(encoding, errors="backslashreplace")
# Make sure we can print the output, by encoding it to the output # Make sure we can print the output, by encoding it to the output
# encoding with replacement of unencodable characters, and then # encoding with replacement of unencodable characters, and then
@ -226,60 +189,6 @@ WINDOWS = (sys.platform.startswith("win") or
(sys.platform == 'cli' and os.name == 'nt')) (sys.platform == 'cli' and os.name == 'nt'))
def samefile(file1, file2):
# type: (str, str) -> bool
"""Provide an alternative for os.path.samefile on Windows/Python2"""
if hasattr(os.path, 'samefile'):
return os.path.samefile(file1, file2)
else:
path1 = os.path.normcase(os.path.abspath(file1))
path2 = os.path.normcase(os.path.abspath(file2))
return path1 == path2
if hasattr(shutil, 'get_terminal_size'):
def get_terminal_size():
# type: () -> Tuple[int, int]
"""
Returns a tuple (x, y) representing the width(x) and the height(y)
in characters of the terminal window.
"""
return tuple(shutil.get_terminal_size()) # type: ignore
else:
def get_terminal_size():
# type: () -> Tuple[int, int]
"""
Returns a tuple (x, y) representing the width(x) and the height(y)
in characters of the terminal window.
"""
def ioctl_GWINSZ(fd):
try:
import fcntl
import struct
import termios
cr = struct.unpack_from(
'hh',
fcntl.ioctl(fd, termios.TIOCGWINSZ, '12345678')
)
except Exception:
return None
if cr == (0, 0):
return None
return cr
cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
if not cr:
if sys.platform != "win32":
try:
fd = os.open(os.ctermid(), os.O_RDONLY)
cr = ioctl_GWINSZ(fd)
os.close(fd)
except Exception:
pass
if not cr:
cr = (os.environ.get('LINES', 25), os.environ.get('COLUMNS', 80))
return int(cr[1]), int(cr[0])
# Fallback to noop_lru_cache in Python 2 # Fallback to noop_lru_cache in Python 2
# TODO: this can be removed when python 2 support is dropped! # TODO: this can be removed when python 2 support is dropped!
def noop_lru_cache(maxsize=None): def noop_lru_cache(maxsize=None):

View File

@ -12,7 +12,6 @@ from tempfile import NamedTemporaryFile
# NOTE: retrying is not annotated in typeshed as on 2017-07-17, which is # NOTE: retrying is not annotated in typeshed as on 2017-07-17, which is
# why we ignore the type on this import. # why we ignore the type on this import.
from pip._vendor.retrying import retry # type: ignore from pip._vendor.retrying import retry # type: ignore
from pip._vendor.six import PY2
from pip._internal.utils.compat import get_path_uid from pip._internal.utils.compat import get_path_uid
from pip._internal.utils.misc import format_size from pip._internal.utils.misc import format_size
@ -114,18 +113,7 @@ def adjacent_tmp_file(path, **kwargs):
_replace_retry = retry(stop_max_delay=1000, wait_fixed=250) _replace_retry = retry(stop_max_delay=1000, wait_fixed=250)
if PY2: replace = _replace_retry(os.replace)
@_replace_retry
def replace(src, dest):
# type: (str, str) -> None
try:
os.rename(src, dest)
except OSError:
os.remove(dest)
os.rename(src, dest)
else:
replace = _replace_retry(os.replace)
# test_writable_dir and _test_writable_dir_win are copied from Flit, # test_writable_dir and _test_writable_dir_win are copied from Flit,

View File

@ -2,21 +2,14 @@ from __future__ import absolute_import
import hashlib import hashlib
from pip._vendor.six import iteritems, iterkeys, itervalues
from pip._internal.exceptions import HashMismatch, HashMissing, InstallationError from pip._internal.exceptions import HashMismatch, HashMissing, InstallationError
from pip._internal.utils.misc import read_chunks from pip._internal.utils.misc import read_chunks
from pip._internal.utils.typing import MYPY_CHECK_RUNNING from pip._internal.utils.typing import MYPY_CHECK_RUNNING
if MYPY_CHECK_RUNNING: if MYPY_CHECK_RUNNING:
from hashlib import _Hash
from typing import BinaryIO, Dict, Iterator, List, NoReturn from typing import BinaryIO, Dict, Iterator, List, NoReturn
from pip._vendor.six import PY3
if PY3:
from hashlib import _Hash
else:
from hashlib import _hash as _Hash
# The recommended hash algo of the moment. Change this whenever the state of # The recommended hash algo of the moment. Change this whenever the state of
# the art changes; it won't hurt backward compatibility. # the art changes; it won't hurt backward compatibility.
@ -60,7 +53,7 @@ class Hashes(object):
# Otherwise only hashes that present in both objects are allowed. # Otherwise only hashes that present in both objects are allowed.
new = {} new = {}
for alg, values in iteritems(other._allowed): for alg, values in other._allowed.items():
if alg not in self._allowed: if alg not in self._allowed:
continue continue
new[alg] = [v for v in values if v in self._allowed[alg]] new[alg] = [v for v in values if v in self._allowed[alg]]
@ -89,7 +82,7 @@ class Hashes(object):
""" """
gots = {} gots = {}
for hash_name in iterkeys(self._allowed): for hash_name in self._allowed.keys():
try: try:
gots[hash_name] = hashlib.new(hash_name) gots[hash_name] = hashlib.new(hash_name)
except (ValueError, TypeError): except (ValueError, TypeError):
@ -98,10 +91,10 @@ class Hashes(object):
) )
for chunk in chunks: for chunk in chunks:
for hash in itervalues(gots): for hash in gots.values():
hash.update(chunk) hash.update(chunk)
for hash_name, got in iteritems(gots): for hash_name, got in gots.items():
if got.hexdigest() in self._allowed[hash_name]: if got.hexdigest() in self._allowed[hash_name]:
return return
self._raise(gots) self._raise(gots)

View File

@ -11,8 +11,6 @@ import os
import sys import sys
from logging import Filter, getLogger from logging import Filter, getLogger
from pip._vendor.six import PY2
from pip._internal.utils.compat import WINDOWS from pip._internal.utils.compat import WINDOWS
from pip._internal.utils.deprecation import DEPRECATION_MSG_PREFIX from pip._internal.utils.deprecation import DEPRECATION_MSG_PREFIX
from pip._internal.utils.misc import ensure_dir from pip._internal.utils.misc import ensure_dir
@ -62,30 +60,18 @@ class BrokenStdoutLoggingError(Exception):
pass pass
# BrokenPipeError does not exist in Python 2 and, in addition, manifests # BrokenPipeError manifests differently in Windows and non-Windows.
# differently in Windows and non-Windows.
if WINDOWS: if WINDOWS:
# In Windows, a broken pipe can show up as EINVAL rather than EPIPE: # In Windows, a broken pipe can show up as EINVAL rather than EPIPE:
# https://bugs.python.org/issue19612 # https://bugs.python.org/issue19612
# https://bugs.python.org/issue30418 # https://bugs.python.org/issue30418
if PY2:
def _is_broken_pipe_error(exc_class, exc):
"""See the docstring for non-Windows Python 3 below."""
return (exc_class is IOError and
exc.errno in (errno.EINVAL, errno.EPIPE))
else:
# In Windows, a broken pipe IOError became OSError in Python 3.
def _is_broken_pipe_error(exc_class, exc):
"""See the docstring for non-Windows Python 3 below."""
return ((exc_class is BrokenPipeError) or # noqa: F821
(exc_class is OSError and
exc.errno in (errno.EINVAL, errno.EPIPE)))
elif PY2:
def _is_broken_pipe_error(exc_class, exc): def _is_broken_pipe_error(exc_class, exc):
"""See the docstring for non-Windows Python 3 below.""" """See the docstring for non-Windows below."""
return (exc_class is IOError and exc.errno == errno.EPIPE) return ((exc_class is BrokenPipeError) or # noqa: F821
(exc_class is OSError and
exc.errno in (errno.EINVAL, errno.EPIPE)))
else: else:
# Then we are in the non-Windows Python 3 case. # Then we are in the non-Windows case.
def _is_broken_pipe_error(exc_class, exc): def _is_broken_pipe_error(exc_class, exc):
""" """
Return whether an exception is a broken pipe error. Return whether an exception is a broken pipe error.

View File

@ -16,7 +16,10 @@ import shutil
import stat import stat
import sys import sys
from collections import deque from collections import deque
from itertools import tee from io import StringIO
from itertools import filterfalse, tee, zip_longest
from urllib import parse as urllib_parse
from urllib.parse import unquote as urllib_unquote
from pip._vendor import pkg_resources from pip._vendor import pkg_resources
from pip._vendor.packaging.utils import canonicalize_name from pip._vendor.packaging.utils import canonicalize_name
@ -24,26 +27,17 @@ from pip._vendor.packaging.utils import canonicalize_name
# NOTE: retrying is not annotated in typeshed as on 2017-07-17, which is # NOTE: retrying is not annotated in typeshed as on 2017-07-17, which is
# why we ignore the type on this import. # why we ignore the type on this import.
from pip._vendor.retrying import retry # type: ignore from pip._vendor.retrying import retry # type: ignore
from pip._vendor.six import PY2, text_type
from pip._vendor.six.moves import filter, filterfalse, input, map, zip_longest
from pip._vendor.six.moves.urllib import parse as urllib_parse
from pip._vendor.six.moves.urllib.parse import unquote as urllib_unquote
from pip import __version__ from pip import __version__
from pip._internal.exceptions import CommandError from pip._internal.exceptions import CommandError
from pip._internal.locations import get_major_minor_version, site_packages, user_site from pip._internal.locations import get_major_minor_version, site_packages, user_site
from pip._internal.utils.compat import WINDOWS, expanduser, stdlib_pkgs, str_to_display from pip._internal.utils.compat import WINDOWS, expanduser, stdlib_pkgs
from pip._internal.utils.typing import MYPY_CHECK_RUNNING, cast from pip._internal.utils.typing import MYPY_CHECK_RUNNING, cast
from pip._internal.utils.virtualenv import ( from pip._internal.utils.virtualenv import (
running_under_virtualenv, running_under_virtualenv,
virtualenv_no_global, virtualenv_no_global,
) )
if PY2:
from io import BytesIO as StringIO
else:
from io import StringIO
if MYPY_CHECK_RUNNING: if MYPY_CHECK_RUNNING:
from typing import ( from typing import (
Any, Any,
@ -173,7 +167,7 @@ def path_to_display(path):
""" """
if path is None: if path is None:
return None return None
if isinstance(path, text_type): if isinstance(path, str):
return path return path
# Otherwise, path is a bytes object (str in Python 2). # Otherwise, path is a bytes object (str in Python 2).
try: try:
@ -181,17 +175,9 @@ def path_to_display(path):
except UnicodeDecodeError: except UnicodeDecodeError:
# Include the full bytes to make troubleshooting easier, even though # Include the full bytes to make troubleshooting easier, even though
# it may not be very human readable. # it may not be very human readable.
if PY2: # Silence the "F821 undefined name 'ascii'" flake8 error since
# Convert the bytes to a readable str representation using # ascii() is a built-in.
# repr(), and then convert the str to unicode. display_path = ascii(path) # noqa: F821
# Also, we add the prefix "b" to the repr() return value both
# to make the Python 2 output look like the Python 3 output, and
# to signal to the user that this is a bytes representation.
display_path = str_to_display('b{!r}'.format(path))
else:
# Silence the "F821 undefined name 'ascii'" flake8 error since
# in Python 3 ascii() is a built-in.
display_path = ascii(path) # noqa: F821
return display_path return display_path
@ -201,9 +187,6 @@ def display_path(path):
"""Gives the display value for a given path, making it relative to cwd """Gives the display value for a given path, making it relative to cwd
if possible.""" if possible."""
path = os.path.normcase(os.path.abspath(path)) path = os.path.normcase(os.path.abspath(path))
if sys.version_info[0] == 2:
path = path.decode(sys.getfilesystemencoding(), 'replace')
path = path.encode(sys.getdefaultencoding(), 'replace')
if path.startswith(os.getcwd() + os.path.sep): if path.startswith(os.getcwd() + os.path.sep):
path = '.' + path[len(os.getcwd()):] path = '.' + path[len(os.getcwd()):]
return path return path
@ -854,12 +837,6 @@ class HiddenText(object):
# just the raw, original string. # just the raw, original string.
return (self.secret == other.secret) return (self.secret == other.secret)
# We need to provide an explicit __ne__ implementation for Python 2.
# TODO: remove this when we drop PY2 support.
def __ne__(self, other):
# type: (Any) -> bool
return not self == other
def hide_value(value): def hide_value(value):
# type: (str) -> HiddenText # type: (str) -> HiddenText

View File

@ -23,8 +23,6 @@ from multiprocessing import Pool as ProcessPool
from multiprocessing.dummy import Pool as ThreadPool from multiprocessing.dummy import Pool as ThreadPool
from pip._vendor.requests.adapters import DEFAULT_POOLSIZE from pip._vendor.requests.adapters import DEFAULT_POOLSIZE
from pip._vendor.six import PY2
from pip._vendor.six.moves import map
from pip._internal.utils.typing import MYPY_CHECK_RUNNING from pip._internal.utils.typing import MYPY_CHECK_RUNNING
@ -100,7 +98,7 @@ def _map_multithread(func, iterable, chunksize=1):
return pool.imap_unordered(func, iterable, chunksize) return pool.imap_unordered(func, iterable, chunksize)
if LACK_SEM_OPEN or PY2: if LACK_SEM_OPEN:
map_multiprocess = map_multithread = _map_fallback map_multiprocess = map_multithread = _map_fallback
else: else:
map_multiprocess = _map_multiprocess map_multiprocess = _map_multiprocess

View File

@ -2,10 +2,9 @@ from __future__ import absolute_import
import logging import logging
import os import os
import shlex
import subprocess import subprocess
from pip._vendor.six.moves import shlex_quote
from pip._internal.cli.spinners import SpinnerInterface, open_spinner from pip._internal.cli.spinners import SpinnerInterface, open_spinner
from pip._internal.exceptions import InstallationError from pip._internal.exceptions import InstallationError
from pip._internal.utils.compat import console_to_str, str_to_display from pip._internal.utils.compat import console_to_str, str_to_display
@ -51,8 +50,8 @@ def format_command_args(args):
# has type unicode and includes a non-ascii character. (The type # has type unicode and includes a non-ascii character. (The type
# checker doesn't ensure the annotations are correct in all cases.) # checker doesn't ensure the annotations are correct in all cases.)
return ' '.join( return ' '.join(
shlex_quote(str(arg)) if isinstance(arg, HiddenText) shlex.quote(str(arg)) if isinstance(arg, HiddenText)
else shlex_quote(arg) for arg in args else shlex.quote(arg) for arg in args
) )

View File

@ -1,8 +1,7 @@
import os import os
import sys import sys
from urllib import parse as urllib_parse
from pip._vendor.six.moves.urllib import parse as urllib_parse from urllib import request as urllib_request
from pip._vendor.six.moves.urllib import request as urllib_request
from pip._internal.utils.typing import MYPY_CHECK_RUNNING from pip._internal.utils.typing import MYPY_CHECK_RUNNING

View File

@ -5,11 +5,11 @@ from __future__ import absolute_import
import logging import logging
from email.parser import Parser from email.parser import Parser
from zipfile import ZipFile from zipfile import BadZipFile, ZipFile
from pip._vendor.packaging.utils import canonicalize_name from pip._vendor.packaging.utils import canonicalize_name
from pip._vendor.pkg_resources import DistInfoDistribution from pip._vendor.pkg_resources import DistInfoDistribution
from pip._vendor.six import PY2, ensure_str from pip._vendor.six import ensure_str
from pip._internal.exceptions import UnsupportedWheel from pip._internal.exceptions import UnsupportedWheel
from pip._internal.utils.pkg_resources import DictMetadata from pip._internal.utils.pkg_resources import DictMetadata
@ -21,11 +21,6 @@ if MYPY_CHECK_RUNNING:
from pip._vendor.pkg_resources import Distribution from pip._vendor.pkg_resources import Distribution
if PY2:
from zipfile import BadZipfile as BadZipFile
else:
from zipfile import BadZipFile
VERSION_COMPATIBLE = (1, 0) VERSION_COMPATIBLE = (1, 0)

View File

@ -5,8 +5,7 @@ from __future__ import absolute_import
import logging import logging
import os import os
from urllib import parse as urllib_parse
from pip._vendor.six.moves.urllib import parse as urllib_parse
from pip._internal.utils.misc import display_path, rmtree from pip._internal.utils.misc import display_path, rmtree
from pip._internal.utils.subprocess import make_command from pip._internal.utils.subprocess import make_command

View File

@ -6,10 +6,10 @@ from __future__ import absolute_import
import logging import logging
import os.path import os.path
import re import re
from urllib import parse as urllib_parse
from urllib import request as urllib_request
from pip._vendor.packaging.version import parse as parse_version from pip._vendor.packaging.version import parse as parse_version
from pip._vendor.six.moves.urllib import parse as urllib_parse
from pip._vendor.six.moves.urllib import request as urllib_request
from pip._internal.exceptions import BadCommand, SubProcessError from pip._internal.exceptions import BadCommand, SubProcessError
from pip._internal.utils.misc import display_path, hide_url from pip._internal.utils.misc import display_path, hide_url

View File

@ -3,11 +3,10 @@
from __future__ import absolute_import from __future__ import absolute_import
import configparser
import logging import logging
import os import os
from pip._vendor.six.moves import configparser
from pip._internal.exceptions import BadCommand, SubProcessError from pip._internal.exceptions import BadCommand, SubProcessError
from pip._internal.utils.misc import display_path from pip._internal.utils.misc import display_path
from pip._internal.utils.subprocess import make_command from pip._internal.utils.subprocess import make_command

View File

@ -8,12 +8,12 @@ import os
import shutil import shutil
import subprocess import subprocess
import sys import sys
from urllib import parse as urllib_parse
from pip._vendor import pkg_resources from pip._vendor import pkg_resources
from pip._vendor.six.moves.urllib import parse as urllib_parse
from pip._internal.exceptions import BadCommand, InstallationError, SubProcessError from pip._internal.exceptions import BadCommand, InstallationError, SubProcessError
from pip._internal.utils.compat import console_to_str, samefile from pip._internal.utils.compat import console_to_str
from pip._internal.utils.logging import subprocess_logger from pip._internal.utils.logging import subprocess_logger
from pip._internal.utils.misc import ( from pip._internal.utils.misc import (
ask_path_exists, ask_path_exists,
@ -197,7 +197,7 @@ def find_path_to_setup_from_repo_root(location, repo_root):
) )
return None return None
if samefile(repo_root, location): if os.path.samefile(repo_root, location):
return None return None
return os.path.relpath(location, repo_root) return os.path.relpath(location, repo_root)
@ -289,9 +289,7 @@ class VcsSupport(object):
# Register more schemes with urlparse for various version control # Register more schemes with urlparse for various version control
# systems # systems
urllib_parse.uses_netloc.extend(self.schemes) urllib_parse.uses_netloc.extend(self.schemes)
# Python >= 2.7.4, 3.3 doesn't have uses_fragment urllib_parse.uses_fragment.extend(self.schemes)
if getattr(urllib_parse, 'uses_fragment', None):
urllib_parse.uses_fragment.extend(self.schemes)
super(VcsSupport, self).__init__() super(VcsSupport, self).__init__()
def __iter__(self): def __iter__(self):

View File

@ -10,7 +10,6 @@ import time
from contextlib import contextmanager from contextlib import contextmanager
import pytest import pytest
import six
from mock import patch from mock import patch
from pip._vendor.contextlib2 import ExitStack, nullcontext from pip._vendor.contextlib2 import ExitStack, nullcontext
from setuptools.wheel import Wheel from setuptools.wheel import Wheel
@ -73,15 +72,14 @@ def pytest_collection_modifyitems(config, items):
if item.get_closest_marker('network') is not None: if item.get_closest_marker('network') is not None:
item.add_marker(pytest.mark.flaky(reruns=3, reruns_delay=2)) item.add_marker(pytest.mark.flaky(reruns=3, reruns_delay=2))
if six.PY3: if (item.get_closest_marker('incompatible_with_test_venv') and
if (item.get_closest_marker('incompatible_with_test_venv') and config.getoption("--use-venv")):
config.getoption("--use-venv")): item.add_marker(pytest.mark.skip(
item.add_marker(pytest.mark.skip( 'Incompatible with test venv'))
'Incompatible with test venv')) if (item.get_closest_marker('incompatible_with_venv') and
if (item.get_closest_marker('incompatible_with_venv') and sys.prefix != sys.base_prefix):
sys.prefix != sys.base_prefix): item.add_marker(pytest.mark.skip(
item.add_marker(pytest.mark.skip( 'Incompatible with venv'))
'Incompatible with venv'))
module_path = os.path.relpath( module_path = os.path.relpath(
item.module.__file__, item.module.__file__,
@ -111,16 +109,10 @@ def resolver_variant(request):
features = set(os.environ.get("PIP_USE_FEATURE", "").split()) features = set(os.environ.get("PIP_USE_FEATURE", "").split())
deprecated_features = set(os.environ.get("PIP_USE_DEPRECATED", "").split()) deprecated_features = set(os.environ.get("PIP_USE_DEPRECATED", "").split())
if six.PY3: if resolver == "legacy":
if resolver == "legacy": deprecated_features.add("legacy-resolver")
deprecated_features.add("legacy-resolver")
else:
deprecated_features.discard("legacy-resolver")
else: else:
if resolver == "2020-resolver": deprecated_features.discard("legacy-resolver")
features.add("2020-resolver")
else:
features.discard("2020-resolver")
env = { env = {
"PIP_USE_FEATURE": " ".join(features), "PIP_USE_FEATURE": " ".join(features),
@ -141,7 +133,7 @@ def tmpdir_factory(request, tmpdir_factory):
# handle non-ASCII file names. This works around the problem by # handle non-ASCII file names. This works around the problem by
# passing a unicode object to rmtree(). # passing a unicode object to rmtree().
shutil.rmtree( shutil.rmtree(
six.text_type(tmpdir_factory.getbasetemp()), str(tmpdir_factory.getbasetemp()),
ignore_errors=True, ignore_errors=True,
) )
@ -166,7 +158,7 @@ def tmpdir(request, tmpdir):
# py.path.remove() uses str paths on Python 2 and cannot # py.path.remove() uses str paths on Python 2 and cannot
# handle non-ASCII file names. This works around the problem by # handle non-ASCII file names. This works around the problem by
# passing a unicode object to rmtree(). # passing a unicode object to rmtree().
shutil.rmtree(six.text_type(tmpdir), ignore_errors=True) shutil.rmtree(str(tmpdir), ignore_errors=True)
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
@ -337,7 +329,7 @@ def install_egg_link(venv, project_name, egg_info_dir):
def virtualenv_template(request, tmpdir_factory, pip_src, def virtualenv_template(request, tmpdir_factory, pip_src,
setuptools_install, coverage_install): setuptools_install, coverage_install):
if six.PY3 and request.config.getoption('--use-venv'): if request.config.getoption('--use-venv'):
venv_type = 'venv' venv_type = 'venv'
else: else:
venv_type = 'virtualenv' venv_type = 'virtualenv'
@ -474,10 +466,7 @@ class InMemoryPipResult(object):
class InMemoryPip(object): class InMemoryPip(object):
def pip(self, *args): def pip(self, *args):
orig_stdout = sys.stdout orig_stdout = sys.stdout
if six.PY3: stdout = io.StringIO()
stdout = io.StringIO()
else:
stdout = io.BytesIO()
sys.stdout = stdout sys.stdout = stdout
try: try:
returncode = pip_entry_point(list(args)) returncode = pip_entry_point(list(args))

View File

@ -4,7 +4,6 @@ import textwrap
from hashlib import sha256 from hashlib import sha256
import pytest import pytest
from pip._vendor.six import PY2
from pip._internal.cli.status_codes import ERROR from pip._internal.cli.status_codes import ERROR
from pip._internal.utils.urls import path_to_url from pip._internal.utils.urls import path_to_url
@ -490,7 +489,6 @@ def make_wheel_with_python_requires(script, package_name, python_requires):
package_dir.joinpath('setup.py').write_text(text) package_dir.joinpath('setup.py').write_text(text)
script.run( script.run(
'python', 'setup.py', 'bdist_wheel', '--universal', cwd=package_dir, 'python', 'setup.py', 'bdist_wheel', '--universal', cwd=package_dir,
allow_stderr_warning=PY2,
) )
file_name = '{}-1.0-py2.py3-none-any.whl'.format(package_name) file_name = '{}-1.0-py2.py3-none-any.whl'.format(package_name)

View File

@ -9,7 +9,6 @@ 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._internal.cli.status_codes import ERROR, SUCCESS from pip._internal.cli.status_codes import ERROR, SUCCESS
from pip._internal.models.index import PyPI, TestPyPI from pip._internal.models.index import PyPI, TestPyPI
@ -26,8 +25,6 @@ from tests.lib import (
pyversion, pyversion,
pyversion_tuple, pyversion_tuple,
requirements_file, requirements_file,
skip_if_not_python2,
skip_if_python2,
windows_workaround_7667, windows_workaround_7667,
) )
from tests.lib.filesystem import make_socket_file from tests.lib.filesystem import make_socket_file
@ -658,22 +655,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
@skip_if_not_python2
@pytest.mark.xfail
def test_install_argparse_shadowed(script):
# When argparse is in the stdlib, we support installing it
# even though that's pretty useless because older packages did need to
# depend on it, and not having its metadata will cause pkg_resources
# requirements checks to fail // trigger easy-install, both of which are
# bad.
# XXX: Note, this test hits the outside-environment check, not the
# in-stdlib check, because our tests run in virtualenvs...
result = script.pip('install', 'argparse>=1.4')
assert "Not uninstalling argparse" in result.stdout
@pytest.mark.network @pytest.mark.network
@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.
@ -1568,7 +1550,7 @@ def test_install_incompatible_python_requires_wheel(script, with_wheel):
""")) """))
script.run( script.run(
'python', 'setup.py', 'bdist_wheel', '--universal', 'python', 'setup.py', 'bdist_wheel', '--universal',
cwd=pkga_path, allow_stderr_warning=PY2, cwd=pkga_path,
) )
result = script.pip('install', './pkga/dist/pkga-0.1-py2.py3-none-any.whl', result = script.pip('install', './pkga/dist/pkga-0.1-py2.py3-none-any.whl',
expect_error=True) expect_error=True)
@ -1837,7 +1819,6 @@ def test_install_yanked_file_and_print_warning(script, data):
assert 'Successfully installed simple-3.0\n' in result.stdout, str(result) assert 'Successfully installed simple-3.0\n' in result.stdout, str(result)
@skip_if_python2
@pytest.mark.parametrize("install_args", [ @pytest.mark.parametrize("install_args", [
(), (),
("--trusted-host", "localhost"), ("--trusted-host", "localhost"),

View File

@ -5,7 +5,6 @@ import textwrap
import pytest import pytest
from tests.lib import skip_if_python2
from tests.lib.server import ( from tests.lib.server import (
authorization_response, authorization_response,
file_response, file_response,
@ -130,7 +129,6 @@ def test_command_line_appends_correctly(script, data):
), 'stdout: {}'.format(result.stdout) ), 'stdout: {}'.format(result.stdout)
@skip_if_python2
def test_config_file_override_stack( def test_config_file_override_stack(
script, virtualenv, mock_server, shared_data script, virtualenv, mock_server, shared_data
): ):
@ -249,7 +247,6 @@ def test_prompt_for_authentication(script, data, cert_factory):
result.stdout, str(result) result.stdout, str(result)
@skip_if_python2
def test_do_not_prompt_for_authentication(script, data, cert_factory): def test_do_not_prompt_for_authentication(script, data, cert_factory):
"""Test behaviour if --no-input option is given while installing """Test behaviour if --no-input option is given while installing
from a index url requiring authentication from a index url requiring authentication

View File

@ -1,7 +1,6 @@
import os import os
import textwrap import textwrap
from urllib import parse as urllib_parse
from pip._vendor.six.moves.urllib import parse as urllib_parse
def test_find_links_relative_path(script, data, with_wheel): def test_find_links_relative_path(script, data, with_wheel):

View File

@ -8,7 +8,7 @@ import shutil
import pytest import pytest
from tests.lib import create_basic_wheel_for_package, skip_if_python2 from tests.lib import create_basic_wheel_for_package
from tests.lib.path import Path from tests.lib.path import Path
from tests.lib.wheel import make_wheel from tests.lib.wheel import make_wheel
@ -118,7 +118,6 @@ def test_basic_install_from_wheel_file(script, data):
# Installation seems to work, but scripttest fails to check. # Installation seems to work, but scripttest fails to check.
# I really don't care now since we're desupporting it soon anyway. # I really don't care now since we're desupporting it soon anyway.
@skip_if_python2
def test_basic_install_from_unicode_wheel(script, data): def test_basic_install_from_unicode_wheel(script, data):
""" """
Test installing from a wheel (that has a script) Test installing from a wheel (that has a script)
@ -394,8 +393,6 @@ def test_install_from_wheel_gen_uppercase_entrypoint(
assert bool(os.access(script.base_path / wrapper_file, os.X_OK)) assert bool(os.access(script.base_path / wrapper_file, os.X_OK))
# pkg_resources.EntryPoint() does not parse unicode correctly on Python 2.
@skip_if_python2
def test_install_from_wheel_gen_unicode_entrypoint(script): def test_install_from_wheel_gen_unicode_entrypoint(script):
make_wheel( make_wheel(
"script_wheel_unicode", "script_wheel_unicode",
@ -651,8 +648,6 @@ def test_wheel_installs_ok_with_badly_encoded_irrelevant_dist_info_file(
) )
# Metadata is not decoded on Python 2.
@skip_if_python2
def test_wheel_install_fails_with_badly_encoded_metadata(script): def test_wheel_install_fails_with_badly_encoded_metadata(script):
package = create_basic_wheel_for_package( package = create_basic_wheel_for_package(
script, script,

View File

@ -1,10 +1,7 @@
import platform
import textwrap import textwrap
import pytest import pytest
from tests.lib import skip_if_not_python2, skip_if_python2
@pytest.fixture @pytest.fixture
def warnings_demo(tmpdir): def warnings_demo(tmpdir):
@ -37,33 +34,11 @@ DEPRECATION_TEXT = "drop support for Python 2.7"
CPYTHON_DEPRECATION_TEXT = "January 1st, 2020" CPYTHON_DEPRECATION_TEXT = "January 1st, 2020"
@skip_if_python2
def test_version_warning_is_not_shown_if_python_version_is_not_2(script): def test_version_warning_is_not_shown_if_python_version_is_not_2(script):
result = script.pip("debug", allow_stderr_warning=True) result = script.pip("debug", allow_stderr_warning=True)
assert DEPRECATION_TEXT not in result.stderr, str(result) assert DEPRECATION_TEXT not in result.stderr, str(result)
assert CPYTHON_DEPRECATION_TEXT not in result.stderr, str(result) assert CPYTHON_DEPRECATION_TEXT not in result.stderr, str(result)
@skip_if_python2
def test_flag_does_nothing_if_python_version_is_not_2(script): def test_flag_does_nothing_if_python_version_is_not_2(script):
script.pip("list", "--no-python-version-warning") script.pip("list", "--no-python-version-warning")
@skip_if_not_python2
def test_version_warning_is_shown_if_python_version_is_2(script):
result = script.pip("debug", allow_stderr_warning=True)
assert DEPRECATION_TEXT in result.stderr, str(result)
if platform.python_implementation() == 'CPython':
assert CPYTHON_DEPRECATION_TEXT in result.stderr, str(result)
else:
assert CPYTHON_DEPRECATION_TEXT not in result.stderr, str(result)
@skip_if_not_python2
def test_version_warning_is_not_shown_when_flag_is_passed(script):
result = script.pip(
"debug", "--no-python-version-warning", allow_stderr_warning=True
)
assert DEPRECATION_TEXT not in result.stderr, str(result)
assert CPYTHON_DEPRECATION_TEXT not in result.stderr, str(result)
assert "--no-python-version-warning" not in result.stderr

View File

@ -15,7 +15,7 @@ from textwrap import dedent
from zipfile import ZipFile from zipfile import ZipFile
import pytest import pytest
from pip._vendor.six import PY2, ensure_binary, text_type from pip._vendor.six import ensure_binary
from scripttest import FoundDir, TestFileEnvironment from scripttest import FoundDir, TestFileEnvironment
from pip._internal.index.collector import LinkCollector from pip._internal.index.collector import LinkCollector
@ -1099,15 +1099,12 @@ def create_basic_sdist_for_package(
path.parent.mkdir(exist_ok=True, parents=True) path.parent.mkdir(exist_ok=True, parents=True)
path.write_bytes(ensure_binary(files[fname])) path.write_bytes(ensure_binary(files[fname]))
# The base_dir cast is required to make `shutil.make_archive()` use
# Unicode paths on Python 2, making it able to properly archive
# files with non-ASCII names.
retval = script.scratch_path / archive_name retval = script.scratch_path / archive_name
generated = shutil.make_archive( generated = shutil.make_archive(
retval, retval,
'gztar', 'gztar',
root_dir=script.temp_path, root_dir=script.temp_path,
base_dir=text_type(os.curdir), base_dir=os.curdir,
) )
shutil.move(generated, retval) shutil.move(generated, retval)
@ -1164,10 +1161,6 @@ def need_mercurial(fn):
)(fn)) )(fn))
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")
# Workaround for test failures after new wheel release. # Workaround for test failures after new wheel release.
windows_workaround_7667 = pytest.mark.skipif( windows_workaround_7667 = pytest.mark.skipif(
"sys.platform == 'win32' and sys.version_info < (3,)", "sys.platform == 'win32' and sys.version_info < (3,)",

View File

@ -2,8 +2,7 @@ from __future__ import absolute_import
import os import os
import subprocess import subprocess
from urllib import request as urllib_request
from pip._vendor.six.moves.urllib import request as urllib_request
from pip._internal.utils.misc import hide_url from pip._internal.utils.misc import hide_url
from pip._internal.utils.typing import MYPY_CHECK_RUNNING from pip._internal.utils.typing import MYPY_CHECK_RUNNING

View File

@ -5,9 +5,6 @@ from __future__ import absolute_import
import glob import glob
import os import os
import shutil
from pip._vendor import six
try: try:
from os import supports_fd from os import supports_fd
@ -15,11 +12,7 @@ except ImportError:
supports_fd = set() supports_fd = set()
class Path(str):
_base = six.text_type if os.path.supports_unicode_filenames else str
class Path(_base):
""" """
Models a path in an object oriented way. Models a path in an object oriented way.
""" """
@ -32,8 +25,8 @@ class Path(_base):
def __new__(cls, *paths): def __new__(cls, *paths):
if len(paths): if len(paths):
return _base.__new__(cls, os.path.join(*paths)) return str.__new__(cls, os.path.join(*paths))
return _base.__new__(cls) return str.__new__(cls)
def __div__(self, path): def __div__(self, path):
""" """
@ -71,20 +64,20 @@ class Path(_base):
>>> Path('/home/a') + 'bc.d' >>> Path('/home/a') + 'bc.d'
'/home/abc.d' '/home/abc.d'
""" """
return Path(_base(self) + path) return Path(str(self) + path)
def __radd__(self, path): def __radd__(self, path):
""" """
>>> '/home/a' + Path('bc.d') >>> '/home/a' + Path('bc.d')
'/home/abc.d' '/home/abc.d'
""" """
return Path(path + _base(self)) return Path(path + str(self))
def __repr__(self): def __repr__(self):
return u"Path({inner})".format(inner=_base.__repr__(self)) return u"Path({inner})".format(inner=str.__repr__(self))
def __hash__(self): def __hash__(self):
return _base.__hash__(self) return str.__hash__(self)
@property @property
def name(self): def name(self):

View File

@ -5,7 +5,7 @@ from email import message_from_string
from functools import partial from functools import partial
from zipfile import ZipFile from zipfile import ZipFile
from pip._vendor.six import ensure_text, iteritems from pip._vendor.six import ensure_text
from pip._internal.utils.typing import MYPY_CHECK_RUNNING from pip._internal.utils.typing import MYPY_CHECK_RUNNING
from tests.lib.wheel import ( from tests.lib.wheel import (
@ -182,7 +182,7 @@ def test_make_wheel_default_record():
], ],
"simple-0.1.0.dist-info/RECORD": ["", ""], "simple-0.1.0.dist-info/RECORD": ["", ""],
} }
for name, values in iteritems(expected): for name, values in expected.items():
assert records[name] == values, name assert records[name] == values, name
# WHEEL and METADATA aren't constructed in a stable way, so just spot # WHEEL and METADATA aren't constructed in a stable way, so just spot
@ -191,7 +191,7 @@ def test_make_wheel_default_record():
"simple-0.1.0.dist-info/METADATA": "51", "simple-0.1.0.dist-info/METADATA": "51",
"simple-0.1.0.dist-info/WHEEL": "104", "simple-0.1.0.dist-info/WHEEL": "104",
} }
for name, length in iteritems(expected_variable): for name, length in expected_variable.items():
assert records[name][0].startswith("sha256="), name assert records[name][0].startswith("sha256="), name
assert records[name][1] == length, name assert records[name][1] == length, name

View File

@ -4,15 +4,12 @@ import compileall
import shutil import shutil
import sys import sys
import textwrap import textwrap
import venv as _venv
import six
import virtualenv as _virtualenv import virtualenv as _virtualenv
from .path import Path from .path import Path
if six.PY3:
import venv as _venv
class VirtualEnvironment(object): class VirtualEnvironment(object):
""" """
@ -37,8 +34,7 @@ class VirtualEnvironment(object):
self.site = Path(lib) / 'site-packages' self.site = Path(lib) / 'site-packages'
# Workaround for https://github.com/pypa/virtualenv/issues/306 # Workaround for https://github.com/pypa/virtualenv/issues/306
if hasattr(sys, "pypy_version_info"): if hasattr(sys, "pypy_version_info"):
version_fmt = '{0}' if six.PY3 else '{0}.{1}' version_dir = '{0}'.format(*sys.version_info)
version_dir = version_fmt.format(*sys.version_info)
self.lib = Path(home, 'lib-python', version_dir) self.lib = Path(home, 'lib-python', version_dir)
else: else:
self.lib = Path(lib) self.lib = Path(lib)

View File

@ -13,7 +13,7 @@ from zipfile import ZipFile
import csv23 import csv23
from pip._vendor.requests.structures import CaseInsensitiveDict from pip._vendor.requests.structures import CaseInsensitiveDict
from pip._vendor.six import ensure_binary, ensure_text, iteritems from pip._vendor.six import ensure_binary, ensure_text
from pip._internal.utils.typing import MYPY_CHECK_RUNNING from pip._internal.utils.typing import MYPY_CHECK_RUNNING
from tests.lib.path import Path from tests.lib.path import Path
@ -68,7 +68,7 @@ def message_from_dict(headers):
List values are converted into repeated headers in the result. List values are converted into repeated headers in the result.
""" """
message = Message() message = Message()
for name, value in iteritems(headers): for name, value in headers.items():
if isinstance(value, list): if isinstance(value, list):
for v in value: for v in value:
message[name] = v message[name] = v
@ -161,7 +161,7 @@ def make_entry_points_file(
entry_points_data["console_scripts"] = console_scripts entry_points_data["console_scripts"] = console_scripts
lines = [] lines = []
for section, values in iteritems(entry_points_data): for section, values in entry_points_data.items():
lines.append("[{}]".format(section)) lines.append("[{}]".format(section))
lines.extend(values) lines.extend(values)
@ -175,7 +175,7 @@ def make_files(files):
# type: (Dict[str, AnyStr]) -> List[File] # type: (Dict[str, AnyStr]) -> List[File]
return [ return [
File(name, ensure_binary(contents)) File(name, ensure_binary(contents))
for name, contents in iteritems(files) for name, contents in files.items()
] ]
@ -184,7 +184,7 @@ def make_metadata_files(name, version, files):
get_path = partial(dist_info_path, name, version) get_path = partial(dist_info_path, name, version)
return [ return [
File(get_path(name), ensure_binary(contents)) File(get_path(name), ensure_binary(contents))
for name, contents in iteritems(files) for name, contents in files.items()
] ]
@ -193,7 +193,7 @@ def make_data_files(name, version, files):
data_dir = "{}-{}.data".format(name, version) data_dir = "{}-{}.data".format(name, version)
return [ return [
File("{}/{}".format(data_dir, name), ensure_binary(contents)) File("{}/{}".format(data_dir, name), ensure_binary(contents))
for name, contents in iteritems(files) for name, contents in files.items()
] ]

View File

@ -3,13 +3,13 @@ import os.path
import re import re
import uuid import uuid
from textwrap import dedent from textwrap import dedent
from urllib import request as urllib_request
import mock import mock
import pretend import pretend
import pytest import pytest
from mock import Mock, patch from mock import Mock, patch
from pip._vendor import html5lib, requests from pip._vendor import html5lib, requests
from pip._vendor.six.moves.urllib import request as urllib_request
from pip._internal.exceptions import NetworkConnectionError from pip._internal.exceptions import NetworkConnectionError
from pip._internal.index.collector import ( from pip._internal.index.collector import (
@ -30,7 +30,7 @@ from pip._internal.index.collector import (
from pip._internal.models.index import PyPI from pip._internal.models.index import PyPI
from pip._internal.models.link import Link from pip._internal.models.link import Link
from pip._internal.network.session import PipSession from pip._internal.network.session import PipSession
from tests.lib import make_test_link_collector, skip_if_python2 from tests.lib import make_test_link_collector
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -406,7 +406,6 @@ def test_parse_links__yanked_reason(anchor_html, expected):
assert actual == expected assert actual == expected
@skip_if_python2
def test_parse_links_caches_same_page_by_url(): def test_parse_links_caches_same_page_by_url():
html = ( html = (
'<html><head><meta charset="utf-8"><head>' '<html><head><meta charset="utf-8"><head>'

View File

@ -1,10 +1,8 @@
import errno
import logging import logging
from threading import Thread from threading import Thread
import pytest import pytest
from mock import patch from mock import patch
from pip._vendor.six import PY2
from pip._internal.utils.logging import ( from pip._internal.utils.logging import (
BrokenStdoutLoggingError, BrokenStdoutLoggingError,
@ -17,19 +15,6 @@ from pip._internal.utils.misc import captured_stderr, captured_stdout
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# This is a Python 2/3 compatibility helper.
def _make_broken_pipe_error():
"""
Return an exception object representing a broken pipe.
"""
if PY2:
# This is one way a broken pipe error can show up in Python 2
# (a non-Windows example in this case).
return IOError(errno.EPIPE, 'Broken pipe')
return BrokenPipeError() # noqa: F821
class TestIndentingFormatter(object): class TestIndentingFormatter(object):
"""Test ``pip._internal.utils.logging.IndentingFormatter``.""" """Test ``pip._internal.utils.logging.IndentingFormatter``."""
@ -146,7 +131,7 @@ class TestColorizedStreamHandler(object):
with captured_stderr() as stderr: with captured_stderr() as stderr:
handler = ColorizedStreamHandler(stream=stderr) handler = ColorizedStreamHandler(stream=stderr)
with patch('sys.stderr.flush') as mock_flush: with patch('sys.stderr.flush') as mock_flush:
mock_flush.side_effect = _make_broken_pipe_error() mock_flush.side_effect = BrokenPipeError()
# The emit() call raises no exception. # The emit() call raises no exception.
handler.emit(record) handler.emit(record)
@ -154,13 +139,9 @@ class TestColorizedStreamHandler(object):
assert err_text.startswith('my error') assert err_text.startswith('my error')
# Check that the logging framework tried to log the exception. # Check that the logging framework tried to log the exception.
if PY2: assert 'Logging error' in err_text
assert 'IOError: [Errno 32] Broken pipe' in err_text assert 'BrokenPipeError' in err_text
assert 'Logged from file' in err_text assert "Message: 'my error'" in err_text
else:
assert 'Logging error' in err_text
assert 'BrokenPipeError' in err_text
assert "Message: 'my error'" in err_text
def test_broken_pipe_in_stdout_write(self): def test_broken_pipe_in_stdout_write(self):
""" """
@ -173,7 +154,7 @@ class TestColorizedStreamHandler(object):
with captured_stdout() as stdout: with captured_stdout() as stdout:
handler = ColorizedStreamHandler(stream=stdout) handler = ColorizedStreamHandler(stream=stdout)
with patch('sys.stdout.write') as mock_write: with patch('sys.stdout.write') as mock_write:
mock_write.side_effect = _make_broken_pipe_error() mock_write.side_effect = BrokenPipeError()
with pytest.raises(BrokenStdoutLoggingError): with pytest.raises(BrokenStdoutLoggingError):
handler.emit(record) handler.emit(record)
@ -188,7 +169,7 @@ class TestColorizedStreamHandler(object):
with captured_stdout() as stdout: with captured_stdout() as stdout:
handler = ColorizedStreamHandler(stream=stdout) handler = ColorizedStreamHandler(stream=stdout)
with patch('sys.stdout.flush') as mock_flush: with patch('sys.stdout.flush') as mock_flush:
mock_flush.side_effect = _make_broken_pipe_error() mock_flush.side_effect = BrokenPipeError()
with pytest.raises(BrokenStdoutLoggingError): with pytest.raises(BrokenStdoutLoggingError):
handler.emit(record) handler.emit(record)

View File

@ -6,7 +6,6 @@ import textwrap
import pytest import pytest
from mock import patch from mock import patch
from pip._vendor.six import PY2
from pretend import stub from pretend import stub
import pip._internal.req.req_file # this will be monkeypatched import pip._internal.req.req_file # this will be monkeypatched
@ -220,12 +219,11 @@ class TestProcessLine(object):
line_number=3 line_number=3
) )
package_name = "u'my-package=1.0'" if PY2 else "'my-package=1.0'"
expected = ( expected = (
"Invalid requirement: {} " "Invalid requirement: 'my-package=1.0' "
'(from line 3 of path/requirements.txt)\n' '(from line 3 of path/requirements.txt)\n'
'Hint: = is not a valid operator. Did you mean == ?' 'Hint: = is not a valid operator. Did you mean == ?'
).format(package_name) )
assert str(exc.value) == expected assert str(exc.value) == expected
def test_yield_line_requirement(self, line_processor): def test_yield_line_requirement(self, line_processor):

View File

@ -1,8 +1,8 @@
import os import os
import sys import sys
from urllib import request as urllib_request
import pytest import pytest
from pip._vendor.six.moves.urllib import request as urllib_request
from pip._internal.utils.urls import get_url_scheme, path_to_url, url_to_path from pip._internal.utils.urls import get_url_scheme, path_to_url, url_to_path

View File

@ -5,11 +5,9 @@ from importlib import import_module
from math import factorial from math import factorial
from sys import modules from sys import modules
from pip._vendor.six import PY2
from pip._vendor.six.moves import map
from pytest import mark from pytest import mark
DUNDER_IMPORT = '__builtin__.__import__' if PY2 else 'builtins.__import__' DUNDER_IMPORT = 'builtins.__import__'
FUNC, ITERABLE = factorial, range(42) FUNC, ITERABLE = factorial, range(42)
MAPS = 'map_multiprocess', 'map_multithread' MAPS = 'map_multiprocess', 'map_multithread'
_import = __import__ _import = __import__
@ -63,9 +61,8 @@ def test_lack_sem_open(name, monkeypatch):
def test_have_sem_open(name, monkeypatch): def test_have_sem_open(name, monkeypatch):
"""Test fallback when sem_open is available.""" """Test fallback when sem_open is available."""
monkeypatch.setattr(DUNDER_IMPORT, have_sem_open) monkeypatch.setattr(DUNDER_IMPORT, have_sem_open)
impl = '_map_fallback' if PY2 else '_{}'.format(name)
with tmp_import_parallel() as parallel: with tmp_import_parallel() as parallel:
assert getattr(parallel, name) is getattr(parallel, impl) assert getattr(parallel, name) is getattr(parallel, '_{}'.format(name))
@mark.parametrize('name', MAPS) @mark.parametrize('name', MAPS)

View File

@ -6,7 +6,6 @@ from pip._vendor.six import ensure_binary
from pip._internal.utils.packaging import get_metadata, get_requires_python from pip._internal.utils.packaging import get_metadata, get_requires_python
from pip._internal.utils.pkg_resources import DictMetadata from pip._internal.utils.pkg_resources import DictMetadata
from tests.lib import skip_if_python2
def test_dict_metadata_works(): def test_dict_metadata_works():
@ -45,8 +44,6 @@ def test_dict_metadata_works():
assert requires_python == get_requires_python(dist) assert requires_python == get_requires_python(dist)
# Metadata is not decoded on Python 2, so no chance for error.
@skip_if_python2
def test_dict_metadata_throws_on_bad_unicode(): def test_dict_metadata_throws_on_bad_unicode():
metadata = DictMetadata({ metadata = DictMetadata({
"METADATA": b"\xff" "METADATA": b"\xff"

View File

@ -9,7 +9,6 @@ from pip._vendor.contextlib2 import ExitStack
from pip._internal.exceptions import UnsupportedWheel from pip._internal.exceptions import UnsupportedWheel
from pip._internal.utils import wheel from pip._internal.utils import wheel
from pip._internal.utils.typing import MYPY_CHECK_RUNNING from pip._internal.utils.typing import MYPY_CHECK_RUNNING
from tests.lib import skip_if_python2
if MYPY_CHECK_RUNNING: if MYPY_CHECK_RUNNING:
from tests.lib.path import Path from tests.lib.path import Path
@ -88,7 +87,6 @@ def test_wheel_metadata_fails_missing_wheel(tmpdir, zip_dir):
assert "could not read" in str(e.value) assert "could not read" in str(e.value)
@skip_if_python2
def test_wheel_metadata_fails_on_bad_encoding(tmpdir, zip_dir): def test_wheel_metadata_fails_on_bad_encoding(tmpdir, zip_dir):
dist_info_dir = tmpdir / "simple-0.1.0.dist-info" dist_info_dir = tmpdir / "simple-0.1.0.dist-info"
dist_info_dir.mkdir() dist_info_dir.mkdir()

View File

@ -2,10 +2,9 @@
Contains functional tests of the Mercurial class. Contains functional tests of the Mercurial class.
""" """
import configparser
import os import os
from pip._vendor.six.moves import configparser
from pip._internal.utils.misc import hide_url from pip._internal.utils.misc import hide_url
from pip._internal.vcs.mercurial import Mercurial from pip._internal.vcs.mercurial import Mercurial
from tests.lib import need_mercurial from tests.lib import need_mercurial

View File

@ -25,7 +25,7 @@ from pip._internal.utils.compat import WINDOWS
from pip._internal.utils.misc import hash_file from pip._internal.utils.misc import hash_file
from pip._internal.utils.unpacking import unpack_file from pip._internal.utils.unpacking import unpack_file
from pip._internal.utils.wheel import pkg_resources_distribution_for_wheel from pip._internal.utils.wheel import pkg_resources_distribution_for_wheel
from tests.lib import DATA_DIR, assert_paths_equal, skip_if_python2 from tests.lib import DATA_DIR, assert_paths_equal
from tests.lib.wheel import make_wheel from tests.lib.wheel import make_wheel
@ -83,7 +83,7 @@ def test_get_legacy_build_wheel_path__multiple_names(caplog):
[ [
u"pip = pip._internal.main:pip", u"pip = pip._internal.main:pip",
u"pip:pip = pip._internal.main:pip", u"pip:pip = pip._internal.main:pip",
pytest.param(u"進入點 = 套件.模組:函式", marks=skip_if_python2), u"進入點 = 套件.模組:函式",
], ],
) )
def test_get_entrypoints(console_scripts): def test_get_entrypoints(console_scripts):

View File

@ -2,7 +2,7 @@
minversion = 3.4.0 minversion = 3.4.0
envlist = envlist =
docs, packaging, lint, vendoring, docs, packaging, lint, vendoring,
py27, py35, py36, py37, py38, py39, pypy, pypy3 py36, py37, py38, py39, pypy3
[helpers] [helpers]
# Wrapper for calls to pip that make sure the version being used is the # Wrapper for calls to pip that make sure the version being used is the