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
exclude: docs|tests
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
rev: v1.6.0

View File

@ -79,7 +79,7 @@ To run tests without parallelization, run:
$ tox -e py36
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
``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
.. _`psf-salt repository`: https://github.com/python/psf-salt
.. _`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'
Since version 19.1, pip also supports `direct references

View File

@ -41,8 +41,8 @@ Examples
$ python -m pip uninstall simplejson
Uninstalling simplejson:
/home/me/env/lib/python2.7/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
/home/me/env/lib/python3.9/site-packages/simplejson-2.2.1-py3.9.egg-info
Proceed (y/n)? y
Successfully uninstalled simplejson
@ -52,7 +52,7 @@ Examples
C:\> py -m pip uninstall simplejson
Uninstalling simplejson:
/home/me/env/lib/python2.7/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
/home/me/env/lib/python3.9/site-packages/simplejson-2.2.1-py3.9.egg-info
Proceed (y/n)? y
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 traceback
from pip._vendor.six import PY2
from pip._internal.cli import cmdoptions
from pip._internal.cli.command_context import CommandContextMixIn
from pip._internal.cli.parser import ConfigOptionParser, UpdatingDefaultsHelpFormatter
@ -183,7 +181,7 @@ class Command(CommandContextMixIn):
issue=8333,
)
if '2020-resolver' in options.features_enabled and not PY2:
if '2020-resolver' in options.features_enabled:
logger.warning(
"--use-feature=2020-resolver no longer has any effect, "
"since it is now the default dependency resolver in pip. "

View File

@ -7,16 +7,15 @@ from __future__ import absolute_import
import logging
import optparse
import shutil
import sys
import textwrap
from distutils.util import strtobool
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.configuration import Configuration, ConfigurationError
from pip._internal.utils.compat import get_terminal_size
from pip._internal.utils.misc import redact_auth_from_url
logger = logging.getLogger(__name__)
@ -29,7 +28,7 @@ class PrettyHelpFormatter(optparse.IndentedHelpFormatter):
# help position must be aligned with __init__.parseopts.description
kwargs['max_help_position'] = 30
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)
def format_option_strings(self, option):
@ -119,7 +118,7 @@ class UpdatingDefaultsHelpFormatter(PrettyHelpFormatter):
help_text = optparse.IndentedHelpFormatter.expand_default(self, option)
if default_values and option.metavar == 'URL':
if isinstance(default_values, string_types):
if isinstance(default_values, str):
default_values = [default_values]
# 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
for option in self._get_all_options():
default = defaults.get(option.dest)
if isinstance(default, string_types):
if isinstance(default, str):
opt_str = option.get_opt_string()
defaults[option.dest] = option.check_value(opt_str, default)
return optparse.Values(defaults)

View File

@ -4,7 +4,6 @@ import itertools
import sys
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.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
# bar.
characters = [
getattr(preferred, "empty_fill", six.text_type()),
getattr(preferred, "fill", six.text_type()),
getattr(preferred, "empty_fill", ""),
getattr(preferred, "fill", ""),
]
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
# fancier bar and if not we'll fall back to the plaintext bar.
try:
six.text_type().join(characters).encode(encoding)
"".join(characters).encode(encoding)
except UnicodeEncodeError:
return fallback
else:

View File

@ -9,8 +9,6 @@ import logging
import os
from functools import partial
from pip._vendor.six import PY2
from pip._internal.cli import cmdoptions
from pip._internal.cli.base_command import Command
from pip._internal.cli.command_context import CommandContextMixIn
@ -200,14 +198,6 @@ class RequirementCommand(IndexGroupCommand):
def determine_resolver_variant(options):
# type: (Values) -> str
"""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:
return "legacy"

View File

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

View File

@ -1,6 +1,7 @@
from __future__ import absolute_import
import logging
import shutil
import sys
import textwrap
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.models.index import PyPI
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.misc import get_distribution, write_output
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
@ -64,7 +64,7 @@ class SearchCommand(Command, SessionCommandMixin):
terminal_width = None
if sys.stdout.isatty():
terminal_width = get_terminal_size()[0]
terminal_width = shutil.get_terminal_size()[0]
print_results(hits, terminal_width=terminal_width)
if pypi_hits:

View File

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

View File

@ -1,7 +1,5 @@
import abc
from pip._vendor.six import add_metaclass
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
if MYPY_CHECK_RUNNING:
@ -13,8 +11,7 @@ if MYPY_CHECK_RUNNING:
from pip._internal.req import InstallRequirement
@add_metaclass(abc.ABCMeta)
class AbstractDistribution(object):
class AbstractDistribution(object, metaclass=abc.ABCMeta):
"""A base class for handling installable artifacts.
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
above metadata.
"""
def __init__(self, req):
# type: (InstallRequirement) -> None
super(AbstractDistribution, self).__init__()

View File

@ -4,25 +4,18 @@ from __future__ import absolute_import
from itertools import chain, groupby, repeat
from pip._vendor.six import iteritems
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
if MYPY_CHECK_RUNNING:
import configparser
from hashlib import _Hash
from typing import Any, Dict, List, Optional, Text
from pip._vendor.pkg_resources import Distribution
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
if PY3:
from hashlib import _Hash
else:
from hashlib import _hash as _Hash
class PipError(Exception):
"""Base pip exception"""
@ -346,7 +339,7 @@ class HashMismatch(HashError):
return chain([hash_name], repeat(' or'))
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)
lines.extend((' Expected {} {}'.format(next(prefix), e))
for e in expecteds)

View File

@ -10,12 +10,12 @@ import mimetypes
import os
import re
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.distlib.compat import unescape
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.models.link import Link

View File

@ -1,9 +1,7 @@
""" PEP 610 """
import json
import re
from pip._vendor import six
from pip._vendor.six.moves.urllib import parse as urllib_parse
from urllib import parse as urllib_parse
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:
return default
value = d[key]
if six.PY2 and expected_type is str:
expected_type = six.string_types # type: ignore
if not isinstance(value, expected_type):
raise DirectUrlValidationError(
"{!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):

View File

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

View File

@ -2,9 +2,9 @@ import itertools
import logging
import os
import posixpath
from urllib import parse as urllib_parse
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.utils.compat import has_tls

View File

@ -5,10 +5,10 @@ providing credentials in the context of network requests.
"""
import logging
from urllib import parse as urllib_parse
from pip._vendor.requests.auth import AuthBase, HTTPBasicAuth
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 (
ask,

View File

@ -8,7 +8,6 @@ from tempfile import NamedTemporaryFile
from zipfile import BadZipfile, ZipFile
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.utils.typing import MYPY_CHECK_RUNNING

View File

@ -13,13 +13,13 @@ import os
import platform
import sys
import warnings
from urllib import parse as urllib_parse
from pip._vendor import requests, six, urllib3
from pip._vendor.cachecontrol import CacheControlAdapter
from pip._vendor.requests.adapters import BaseAdapter, HTTPAdapter
from pip._vendor.requests.models import Response
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 import __version__

View File

@ -2,11 +2,11 @@
"""
import logging
from urllib import parse as urllib_parse
# NOTE: XMLRPC Client is not annotated in typeshed as on 2017-07-17, which is
# why we ignore the type on this import
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.network.utils import raise_for_status

View File

@ -4,7 +4,6 @@ import collections
import logging
import os
from pip._vendor import six
from pip._vendor.packaging.utils import canonicalize_name
from pip._vendor.pkg_resources import RequirementParseError
@ -162,7 +161,7 @@ def freeze(
# Warn about requirements that were included multiple times (in a
# 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:
logger.warning("Requirement %s included multiple times [%s]",
name, ', '.join(sorted(set(files))))

View File

@ -15,14 +15,13 @@ import shutil
import sys
import warnings
from base64 import urlsafe_b64encode
from itertools import chain, starmap
from itertools import chain, filterfalse, starmap
from zipfile import ZipFile
from pip._vendor import pkg_resources
from pip._vendor.distlib.scripts import ScriptMaker
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.moves import filterfalse, map
from pip._vendor.six import ensure_str, ensure_text, reraise
from pip._internal.exceptions import InstallationError
from pip._internal.locations import get_major_minor_version
@ -70,12 +69,12 @@ else:
from pip._internal.models.scheme import Scheme
from pip._internal.utils.filesystem import NamedTemporaryFileResult
RecordPath = NewType('RecordPath', text_type)
RecordPath = NewType('RecordPath', str)
InstalledCSVRow = Tuple[RecordPath, str, Union[int, str]]
class File(Protocol):
src_record_path = None # type: RecordPath
dest_path = None # type: text_type
dest_path = None # type: str
changed = None # type: bool
def save(self):
@ -87,7 +86,7 @@ logger = logging.getLogger(__name__)
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()"""
h, length = hash_file(path, blocksize)
digest = 'sha256=' + urlsafe_b64encode(
@ -102,14 +101,11 @@ def csv_io_kwargs(mode):
"""Return keyword arguments to properly open a CSV file
in the given mode.
"""
if PY2:
return {'mode': '{}b'.format(mode)}
else:
return {'mode': mode, 'newline': '', 'encoding': 'utf-8'}
return {'mode': mode, 'newline': '', 'encoding': 'utf-8'}
def fix_script(path):
# type: (text_type) -> bool
# type: (str) -> bool
"""Replace #!python with #!/path/to/python
Return True if file was changed.
"""
@ -257,12 +253,12 @@ def _normalized_outrows(outrows):
def _record_to_fs_path(record_path):
# type: (RecordPath) -> text_type
# type: (RecordPath) -> str
return record_path
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:
# On Windows, do not handle relative paths if they belong to different
# logical disks
@ -307,7 +303,7 @@ def get_csv_rows_for_installed(
path = _fs_to_record_path(f, lib_dir)
digest, length = rehash(f)
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, '', ''))
return installed_rows
@ -400,7 +396,7 @@ def get_console_script_specs(console):
class ZipBackedFile(object):
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.dest_path = dest_path
self._zip_file = zip_file
@ -408,12 +404,7 @@ class ZipBackedFile(object):
def _getinfo(self):
# type: () -> ZipInfo
if not PY2:
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"))
return self._zip_file.getinfo(self.src_record_path)
def save(self):
# type: () -> None
@ -525,7 +516,7 @@ def _install_wheel(
generated = [] # type: List[str]
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."""
newpath = _fs_to_record_path(destfile, lib_dir)
installed[srcfile] = newpath
@ -546,7 +537,7 @@ def _install_wheel(
return path.endswith("/")
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):
message = (
"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):
# type: (ZipFile, text_type) -> Callable[[RecordPath], File]
# type: (ZipFile, str) -> Callable[[RecordPath], File]
def make_root_scheme_file(record_path):
# type: (RecordPath) -> File
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)
def pyc_source_file_paths():
# type: () -> Iterator[text_type]
# type: () -> Iterator[str]
# We de-duplicate installation paths, since there can be overlap (e.g.
# file in .data maps to same location as file in wheel root).
# Sorting installation paths makes it easier to reproduce and debug
@ -689,16 +680,10 @@ def _install_wheel(
yield full_installed_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.
"""
if PY2:
if sys.flags.optimize:
return path + 'o'
else:
return path + 'c'
else:
return importlib.util.cache_from_source(path)
return importlib.util.cache_from_source(path)
# Compile all of the pyc files for the installed files
if pycompile:

View File

@ -10,7 +10,6 @@ import os
import shutil
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.installed import InstalledDistribution
@ -51,26 +50,16 @@ if MYPY_CHECK_RUNNING:
from pip._internal.req.req_tracker import RequirementTracker
from pip._internal.utils.hashes import Hashes
if PY2:
CopytreeKwargs = TypedDict(
'CopytreeKwargs',
{
'ignore': Callable[[str, List[str]], List[str]],
'symlinks': bool,
},
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,
)
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__)
@ -177,14 +166,13 @@ def _copy_source_tree(source, target):
skipped += [target_basename]
return skipped
kwargs = dict(ignore=ignore, symlinks=True) # type: CopytreeKwargs
if not PY2:
# Python 2 does not support copy_function, so we only ignore
# errors on special file copy in Python 3.
kwargs['copy_function'] = _copy2_ignoring_special_files
shutil.copytree(source, target, **kwargs)
shutil.copytree(
source,
target,
ignore=ignore,
symlinks=True,
copy_function=_copy2_ignoring_special_files,
)
def get_file_url(

View File

@ -2,10 +2,9 @@ from __future__ import absolute_import
import io
import os
import sys
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._internal.exceptions import InstallationError
@ -19,19 +18,13 @@ def _is_list_of_str(obj):
# type: (Any) -> bool
return (
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):
# type: (str) -> str
path = 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
return os.path.join(unpacked_source_directory, 'pyproject.toml')
BuildSystemDetails = namedtuple('BuildSystemDetails', [

View File

@ -8,9 +8,7 @@ import optparse
import os
import re
import shlex
import sys
from pip._vendor.six.moves.urllib import parse as urllib_parse
from urllib import parse as urllib_parse
from pip._internal.cli import cmdoptions
from pip._internal.exceptions import InstallationError, RequirementsFileParseError
@ -410,10 +408,6 @@ def get_line_parser(finder):
defaults.format_control = finder.format_control
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
opts, _ = parser.parse_args(

View File

@ -223,7 +223,7 @@ class InstallRequirement(object):
if self.satisfied_by is not None:
s += ' in {}'.format(display_path(self.satisfied_by.location))
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]
else:
comes_from = self.comes_from.from_path()
@ -334,7 +334,7 @@ class InstallRequirement(object):
return None
s = str(self.req)
if self.comes_from:
if isinstance(self.comes_from, six.string_types):
if isinstance(self.comes_from, str):
comes_from = self.comes_from
else:
comes_from = self.comes_from.from_path()
@ -480,10 +480,6 @@ class InstallRequirement(object):
assert self.source_dir, "No source dir for {}".format(self)
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
@property

View File

@ -6,12 +6,13 @@ import logging
import os
import sys
import sysconfig
from importlib.util import cache_from_source
from pip._vendor import pkg_resources
from pip._internal.exceptions import UninstallationError
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.misc import (
FakeFile,
@ -363,7 +364,7 @@ class UninstallPathSet(object):
# __pycache__ files can show up after 'installed-files.txt' is created,
# 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))
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
# as absolute paths. It also does not recognize UNC paths if they don't
# 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]:
entry = entry.replace('\\', '/')
self.entries.add(entry)

View File

@ -11,15 +11,12 @@ import functools
import locale
import logging
import os
import shutil
import sys
from pip._vendor.six import PY2, text_type
from pip._internal.utils.typing import 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.
F = TypeVar('F')
@ -41,47 +38,13 @@ except ImportError:
__all__ = [
"ipaddress", "uses_pycache", "console_to_str",
"get_path_uid", "stdlib_pkgs", "WINDOWS", "samefile", "get_terminal_size",
"ipaddress", "console_to_str",
"get_path_uid", "stdlib_pkgs", "WINDOWS",
]
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():
# 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
without encoding errors.
"""
if isinstance(data, text_type):
if isinstance(data, str):
return data
# 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',
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
# 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'))
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
# TODO: this can be removed when python 2 support is dropped!
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
# why we ignore the type on this import.
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.misc import format_size
@ -114,18 +113,7 @@ def adjacent_tmp_file(path, **kwargs):
_replace_retry = retry(stop_max_delay=1000, wait_fixed=250)
if PY2:
@_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)
replace = _replace_retry(os.replace)
# 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
from pip._vendor.six import iteritems, iterkeys, itervalues
from pip._internal.exceptions import HashMismatch, HashMissing, InstallationError
from pip._internal.utils.misc import read_chunks
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
if MYPY_CHECK_RUNNING:
from hashlib import _Hash
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 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.
new = {}
for alg, values in iteritems(other._allowed):
for alg, values in other._allowed.items():
if alg not in self._allowed:
continue
new[alg] = [v for v in values if v in self._allowed[alg]]
@ -89,7 +82,7 @@ class Hashes(object):
"""
gots = {}
for hash_name in iterkeys(self._allowed):
for hash_name in self._allowed.keys():
try:
gots[hash_name] = hashlib.new(hash_name)
except (ValueError, TypeError):
@ -98,10 +91,10 @@ class Hashes(object):
)
for chunk in chunks:
for hash in itervalues(gots):
for hash in gots.values():
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]:
return
self._raise(gots)

View File

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

View File

@ -16,7 +16,10 @@ import shutil
import stat
import sys
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.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
# why we ignore the type on this import.
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._internal.exceptions import CommandError
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.virtualenv import (
running_under_virtualenv,
virtualenv_no_global,
)
if PY2:
from io import BytesIO as StringIO
else:
from io import StringIO
if MYPY_CHECK_RUNNING:
from typing import (
Any,
@ -173,7 +167,7 @@ def path_to_display(path):
"""
if path is None:
return None
if isinstance(path, text_type):
if isinstance(path, str):
return path
# Otherwise, path is a bytes object (str in Python 2).
try:
@ -181,17 +175,9 @@ def path_to_display(path):
except UnicodeDecodeError:
# Include the full bytes to make troubleshooting easier, even though
# it may not be very human readable.
if PY2:
# Convert the bytes to a readable str representation using
# repr(), and then convert the str to unicode.
# 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
# Silence the "F821 undefined name 'ascii'" flake8 error since
# ascii() is a built-in.
display_path = ascii(path) # noqa: F821
return display_path
@ -201,9 +187,6 @@ def display_path(path):
"""Gives the display value for a given path, making it relative to cwd
if possible."""
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):
path = '.' + path[len(os.getcwd()):]
return path
@ -854,12 +837,6 @@ class HiddenText(object):
# just the raw, original string.
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):
# type: (str) -> HiddenText

View File

@ -23,8 +23,6 @@ from multiprocessing import Pool as ProcessPool
from multiprocessing.dummy import Pool as ThreadPool
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
@ -100,7 +98,7 @@ def _map_multithread(func, iterable, chunksize=1):
return pool.imap_unordered(func, iterable, chunksize)
if LACK_SEM_OPEN or PY2:
if LACK_SEM_OPEN:
map_multiprocess = map_multithread = _map_fallback
else:
map_multiprocess = _map_multiprocess

View File

@ -2,10 +2,9 @@ from __future__ import absolute_import
import logging
import os
import shlex
import subprocess
from pip._vendor.six.moves import shlex_quote
from pip._internal.cli.spinners import SpinnerInterface, open_spinner
from pip._internal.exceptions import InstallationError
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
# checker doesn't ensure the annotations are correct in all cases.)
return ' '.join(
shlex_quote(str(arg)) if isinstance(arg, HiddenText)
else shlex_quote(arg) for arg in args
shlex.quote(str(arg)) if isinstance(arg, HiddenText)
else shlex.quote(arg) for arg in args
)

View File

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

View File

@ -5,11 +5,11 @@ from __future__ import absolute_import
import logging
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.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.utils.pkg_resources import DictMetadata
@ -21,11 +21,6 @@ if MYPY_CHECK_RUNNING:
from pip._vendor.pkg_resources import Distribution
if PY2:
from zipfile import BadZipfile as BadZipFile
else:
from zipfile import BadZipFile
VERSION_COMPATIBLE = (1, 0)

View File

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

View File

@ -6,10 +6,10 @@ from __future__ import absolute_import
import logging
import os.path
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.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.utils.misc import display_path, hide_url

View File

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

View File

@ -8,12 +8,12 @@ import os
import shutil
import subprocess
import sys
from urllib import parse as urllib_parse
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.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.misc import (
ask_path_exists,
@ -197,7 +197,7 @@ def find_path_to_setup_from_repo_root(location, repo_root):
)
return None
if samefile(repo_root, location):
if os.path.samefile(repo_root, location):
return None
return os.path.relpath(location, repo_root)
@ -289,9 +289,7 @@ class VcsSupport(object):
# Register more schemes with urlparse for various version control
# systems
urllib_parse.uses_netloc.extend(self.schemes)
# Python >= 2.7.4, 3.3 doesn't have uses_fragment
if getattr(urllib_parse, 'uses_fragment', None):
urllib_parse.uses_fragment.extend(self.schemes)
urllib_parse.uses_fragment.extend(self.schemes)
super(VcsSupport, self).__init__()
def __iter__(self):

View File

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

View File

@ -4,7 +4,6 @@ import textwrap
from hashlib import sha256
import pytest
from pip._vendor.six import PY2
from pip._internal.cli.status_codes import ERROR
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)
script.run(
'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)

View File

@ -9,7 +9,6 @@ import textwrap
from os.path import curdir, join, pardir
import pytest
from pip._vendor.six import PY2
from pip._internal.cli.status_codes import ERROR, SUCCESS
from pip._internal.models.index import PyPI, TestPyPI
@ -26,8 +25,6 @@ from tests.lib import (
pyversion,
pyversion_tuple,
requirements_file,
skip_if_not_python2,
skip_if_python2,
windows_workaround_7667,
)
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
@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
@skip_if_python2
def test_upgrade_argparse_shadowed(script):
# If argparse is installed - even if shadowed for imported - we support
# 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(
'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',
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)
@skip_if_python2
@pytest.mark.parametrize("install_args", [
(),
("--trusted-host", "localhost"),

View File

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

View File

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

View File

@ -8,7 +8,7 @@ import shutil
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.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.
# 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):
"""
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))
# pkg_resources.EntryPoint() does not parse unicode correctly on Python 2.
@skip_if_python2
def test_install_from_wheel_gen_unicode_entrypoint(script):
make_wheel(
"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):
package = create_basic_wheel_for_package(
script,

View File

@ -1,10 +1,7 @@
import platform
import textwrap
import pytest
from tests.lib import skip_if_not_python2, skip_if_python2
@pytest.fixture
def warnings_demo(tmpdir):
@ -37,33 +34,11 @@ DEPRECATION_TEXT = "drop support for Python 2.7"
CPYTHON_DEPRECATION_TEXT = "January 1st, 2020"
@skip_if_python2
def test_version_warning_is_not_shown_if_python_version_is_not_2(script):
result = script.pip("debug", allow_stderr_warning=True)
assert 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):
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
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 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.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
generated = shutil.make_archive(
retval,
'gztar',
root_dir=script.temp_path,
base_dir=text_type(os.curdir),
base_dir=os.curdir,
)
shutil.move(generated, retval)
@ -1164,10 +1161,6 @@ def need_mercurial(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.
windows_workaround_7667 = pytest.mark.skipif(
"sys.platform == 'win32' and sys.version_info < (3,)",

View File

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

View File

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

View File

@ -5,7 +5,7 @@ from email import message_from_string
from functools import partial
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 tests.lib.wheel import (
@ -182,7 +182,7 @@ def test_make_wheel_default_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
# 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/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][1] == length, name

View File

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

View File

@ -13,7 +13,7 @@ from zipfile import ZipFile
import csv23
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 tests.lib.path import Path
@ -68,7 +68,7 @@ def message_from_dict(headers):
List values are converted into repeated headers in the result.
"""
message = Message()
for name, value in iteritems(headers):
for name, value in headers.items():
if isinstance(value, list):
for v in value:
message[name] = v
@ -161,7 +161,7 @@ def make_entry_points_file(
entry_points_data["console_scripts"] = console_scripts
lines = []
for section, values in iteritems(entry_points_data):
for section, values in entry_points_data.items():
lines.append("[{}]".format(section))
lines.extend(values)
@ -175,7 +175,7 @@ def make_files(files):
# type: (Dict[str, AnyStr]) -> List[File]
return [
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)
return [
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)
return [
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 uuid
from textwrap import dedent
from urllib import request as urllib_request
import mock
import pretend
import pytest
from mock import Mock, patch
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.index.collector import (
@ -30,7 +30,7 @@ from pip._internal.index.collector import (
from pip._internal.models.index import PyPI
from pip._internal.models.link import Link
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(
@ -406,7 +406,6 @@ def test_parse_links__yanked_reason(anchor_html, expected):
assert actual == expected
@skip_if_python2
def test_parse_links_caches_same_page_by_url():
html = (
'<html><head><meta charset="utf-8"><head>'

View File

@ -1,10 +1,8 @@
import errno
import logging
from threading import Thread
import pytest
from mock import patch
from pip._vendor.six import PY2
from pip._internal.utils.logging import (
BrokenStdoutLoggingError,
@ -17,19 +15,6 @@ from pip._internal.utils.misc import captured_stderr, captured_stdout
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):
"""Test ``pip._internal.utils.logging.IndentingFormatter``."""
@ -146,7 +131,7 @@ class TestColorizedStreamHandler(object):
with captured_stderr() as stderr:
handler = ColorizedStreamHandler(stream=stderr)
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.
handler.emit(record)
@ -154,13 +139,9 @@ class TestColorizedStreamHandler(object):
assert err_text.startswith('my error')
# Check that the logging framework tried to log the exception.
if PY2:
assert 'IOError: [Errno 32] Broken pipe' in err_text
assert 'Logged from file' in err_text
else:
assert 'Logging error' in err_text
assert 'BrokenPipeError' in err_text
assert "Message: 'my error'" in err_text
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):
"""
@ -173,7 +154,7 @@ class TestColorizedStreamHandler(object):
with captured_stdout() as stdout:
handler = ColorizedStreamHandler(stream=stdout)
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):
handler.emit(record)
@ -188,7 +169,7 @@ class TestColorizedStreamHandler(object):
with captured_stdout() as stdout:
handler = ColorizedStreamHandler(stream=stdout)
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):
handler.emit(record)

View File

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

View File

@ -1,8 +1,8 @@
import os
import sys
from urllib import request as urllib_request
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

View File

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

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.pkg_resources import DictMetadata
from tests.lib import skip_if_python2
def test_dict_metadata_works():
@ -45,8 +44,6 @@ def test_dict_metadata_works():
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():
metadata = DictMetadata({
"METADATA": b"\xff"

View File

@ -9,7 +9,6 @@ from pip._vendor.contextlib2 import ExitStack
from pip._internal.exceptions import UnsupportedWheel
from pip._internal.utils import wheel
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
from tests.lib import skip_if_python2
if MYPY_CHECK_RUNNING:
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)
@skip_if_python2
def test_wheel_metadata_fails_on_bad_encoding(tmpdir, zip_dir):
dist_info_dir = tmpdir / "simple-0.1.0.dist-info"
dist_info_dir.mkdir()

View File

@ -2,10 +2,9 @@
Contains functional tests of the Mercurial class.
"""
import configparser
import os
from pip._vendor.six.moves import configparser
from pip._internal.utils.misc import hide_url
from pip._internal.vcs.mercurial import 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.unpacking import unpack_file
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
@ -83,7 +83,7 @@ def test_get_legacy_build_wheel_path__multiple_names(caplog):
[
u"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):

View File

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