[pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci
This commit is contained in:
pre-commit-ci[bot] 2024-04-13 00:00:18 +00:00
parent 72ad6dc953
commit f4cd1ba0d6
813 changed files with 66015 additions and 58839 deletions

View file

@ -1,2 +1,3 @@
"""For modules related to installing packages.
"""
from __future__ import annotations

View file

@ -1,7 +1,11 @@
"""Legacy editable installation process, i.e. `setup.py develop`.
"""
from __future__ import annotations
import logging
from typing import List, Optional, Sequence
from typing import List
from typing import Optional
from typing import Sequence
from pip._internal.build_env import BuildEnvironment
from pip._internal.utils.logging import indent_log
@ -12,10 +16,10 @@ logger = logging.getLogger(__name__)
def install_editable(
install_options: List[str],
install_options: list[str],
global_options: Sequence[str],
prefix: Optional[str],
home: Optional[str],
prefix: str | None,
home: str | None,
use_user_site: bool,
name: str,
setup_py_path: str,
@ -26,7 +30,7 @@ def install_editable(
"""Install a package in editable mode. Most arguments are pass-through
to setuptools.
"""
logger.info("Running setup.py develop for %s", name)
logger.info('Running setup.py develop for %s', name)
args = make_setuptools_develop_args(
setup_py_path,
@ -42,6 +46,6 @@ def install_editable(
with build_env:
call_subprocess(
args,
command_desc="python setup.py develop",
command_desc='python setup.py develop',
cwd=unpacked_source_directory,
)

View file

@ -1,13 +1,17 @@
"""Legacy installation process, i.e. `setup.py install`.
"""
from __future__ import annotations
import logging
import os
from distutils.util import change_root
from typing import List, Optional, Sequence
from typing import List
from typing import Optional
from typing import Sequence
from distutils.util import change_root
from pip._internal.build_env import BuildEnvironment
from pip._internal.exceptions import InstallationError, LegacyInstallFailure
from pip._internal.exceptions import InstallationError
from pip._internal.exceptions import LegacyInstallFailure
from pip._internal.models.scheme import Scheme
from pip._internal.utils.misc import ensure_dir
from pip._internal.utils.setuptools_build import make_setuptools_install_args
@ -18,8 +22,8 @@ logger = logging.getLogger(__name__)
def write_installed_files_from_setuptools_record(
record_lines: List[str],
root: Optional[str],
record_lines: list[str],
root: str | None,
req_description: str,
) -> None:
def prepend_root(path: str) -> str:
@ -30,14 +34,14 @@ def write_installed_files_from_setuptools_record(
for line in record_lines:
directory = os.path.dirname(line)
if directory.endswith(".egg-info"):
if directory.endswith('.egg-info'):
egg_info_dir = prepend_root(directory)
break
else:
message = (
"{} did not indicate that it installed an "
".egg-info directory. Only setup.py projects "
"generating .egg-info directories are supported."
'{} did not indicate that it installed an '
'.egg-info directory. Only setup.py projects '
'generating .egg-info directories are supported.'
).format(req_description)
raise InstallationError(message)
@ -49,17 +53,17 @@ def write_installed_files_from_setuptools_record(
new_lines.append(os.path.relpath(prepend_root(filename), egg_info_dir))
new_lines.sort()
ensure_dir(egg_info_dir)
inst_files_path = os.path.join(egg_info_dir, "installed-files.txt")
with open(inst_files_path, "w") as f:
f.write("\n".join(new_lines) + "\n")
inst_files_path = os.path.join(egg_info_dir, 'installed-files.txt')
with open(inst_files_path, 'w') as f:
f.write('\n'.join(new_lines) + '\n')
def install(
install_options: List[str],
install_options: list[str],
global_options: Sequence[str],
root: Optional[str],
home: Optional[str],
prefix: Optional[str],
root: str | None,
home: str | None,
prefix: str | None,
use_user_site: bool,
pycompile: bool,
scheme: Scheme,
@ -73,9 +77,9 @@ def install(
header_dir = scheme.headers
with TempDirectory(kind="record") as temp_dir:
with TempDirectory(kind='record') as temp_dir:
try:
record_filename = os.path.join(temp_dir.path, "install-record.txt")
record_filename = os.path.join(temp_dir.path, 'install-record.txt')
install_args = make_setuptools_install_args(
setup_py_path,
global_options=global_options,
@ -91,7 +95,7 @@ def install(
)
runner = runner_with_spinner_message(
f"Running setup.py install for {req_name}"
f'Running setup.py install for {req_name}',
)
with build_env:
runner(
@ -100,7 +104,7 @@ def install(
)
if not os.path.exists(record_filename):
logger.debug("Record file %s not found", record_filename)
logger.debug('Record file %s not found', record_filename)
# Signal to the caller that we didn't install the new package
return False

View file

@ -1,5 +1,6 @@
"""Support for installing and building the "wheel" binary package format.
"""
from __future__ import annotations
import collections
import compileall
@ -14,55 +15,57 @@ import sys
import warnings
from base64 import urlsafe_b64encode
from email.message import Message
from itertools import chain, filterfalse, starmap
from typing import (
IO,
TYPE_CHECKING,
Any,
BinaryIO,
Callable,
Dict,
Iterable,
Iterator,
List,
NewType,
Optional,
Sequence,
Set,
Tuple,
Union,
cast,
)
from zipfile import ZipFile, ZipInfo
from pip._vendor.distlib.scripts import ScriptMaker
from pip._vendor.distlib.util import get_export_entry
from pip._vendor.packaging.utils import canonicalize_name
from itertools import chain
from itertools import filterfalse
from itertools import starmap
from typing import Any
from typing import BinaryIO
from typing import Callable
from typing import cast
from typing import Dict
from typing import IO
from typing import Iterable
from typing import Iterator
from typing import List
from typing import NewType
from typing import Optional
from typing import Sequence
from typing import Set
from typing import Tuple
from typing import TYPE_CHECKING
from typing import Union
from zipfile import ZipFile
from zipfile import ZipInfo
from pip._internal.exceptions import InstallationError
from pip._internal.locations import get_major_minor_version
from pip._internal.metadata import (
BaseDistribution,
FilesystemWheel,
get_wheel_distribution,
)
from pip._internal.models.direct_url import DIRECT_URL_METADATA_NAME, DirectUrl
from pip._internal.models.scheme import SCHEME_KEYS, Scheme
from pip._internal.utils.filesystem import adjacent_tmp_file, replace
from pip._internal.utils.misc import captured_stdout, ensure_dir, hash_file, partition
from pip._internal.utils.unpacking import (
current_umask,
is_within_directory,
set_extracted_file_to_default_mode_plus_executable,
zip_item_is_executable,
)
from pip._internal.metadata import BaseDistribution
from pip._internal.metadata import FilesystemWheel
from pip._internal.metadata import get_wheel_distribution
from pip._internal.models.direct_url import DIRECT_URL_METADATA_NAME
from pip._internal.models.direct_url import DirectUrl
from pip._internal.models.scheme import Scheme
from pip._internal.models.scheme import SCHEME_KEYS
from pip._internal.utils.filesystem import adjacent_tmp_file
from pip._internal.utils.filesystem import replace
from pip._internal.utils.misc import captured_stdout
from pip._internal.utils.misc import ensure_dir
from pip._internal.utils.misc import hash_file
from pip._internal.utils.misc import partition
from pip._internal.utils.unpacking import current_umask
from pip._internal.utils.unpacking import is_within_directory
from pip._internal.utils.unpacking import set_extracted_file_to_default_mode_plus_executable
from pip._internal.utils.unpacking import zip_item_is_executable
from pip._internal.utils.wheel import parse_wheel
from pip._vendor.distlib.scripts import ScriptMaker
from pip._vendor.distlib.util import get_export_entry
from pip._vendor.packaging.utils import canonicalize_name
if TYPE_CHECKING:
from typing import Protocol
class File(Protocol):
src_record_path: "RecordPath"
src_record_path: RecordPath
dest_path: str
changed: bool
@ -72,22 +75,22 @@ if TYPE_CHECKING:
logger = logging.getLogger(__name__)
RecordPath = NewType("RecordPath", str)
RecordPath = NewType('RecordPath', str)
InstalledCSVRow = Tuple[RecordPath, str, Union[int, str]]
def rehash(path: str, blocksize: int = 1 << 20) -> Tuple[str, str]:
def rehash(path: str, blocksize: int = 1 << 20) -> tuple[str, str]:
"""Return (encoded_digest, length) for path using hashlib.sha256()"""
h, length = hash_file(path, blocksize)
digest = "sha256=" + urlsafe_b64encode(h.digest()).decode("latin1").rstrip("=")
digest = 'sha256=' + urlsafe_b64encode(h.digest()).decode('latin1').rstrip('=')
return (digest, str(length))
def csv_io_kwargs(mode: str) -> Dict[str, Any]:
def csv_io_kwargs(mode: str) -> dict[str, Any]:
"""Return keyword arguments to properly open a CSV file
in the given mode.
"""
return {"mode": mode, "newline": "", "encoding": "utf-8"}
return {'mode': mode, 'newline': '', 'encoding': 'utf-8'}
def fix_script(path: str) -> bool:
@ -97,35 +100,35 @@ def fix_script(path: str) -> bool:
# XXX RECORD hashes will need to be updated
assert os.path.isfile(path)
with open(path, "rb") as script:
with open(path, 'rb') as script:
firstline = script.readline()
if not firstline.startswith(b"#!python"):
if not firstline.startswith(b'#!python'):
return False
exename = sys.executable.encode(sys.getfilesystemencoding())
firstline = b"#!" + exename + os.linesep.encode("ascii")
firstline = b'#!' + exename + os.linesep.encode('ascii')
rest = script.read()
with open(path, "wb") as script:
with open(path, 'wb') as script:
script.write(firstline)
script.write(rest)
return True
def wheel_root_is_purelib(metadata: Message) -> bool:
return metadata.get("Root-Is-Purelib", "").lower() == "true"
return metadata.get('Root-Is-Purelib', '').lower() == 'true'
def get_entrypoints(dist: BaseDistribution) -> Tuple[Dict[str, str], Dict[str, str]]:
def get_entrypoints(dist: BaseDistribution) -> tuple[dict[str, str], dict[str, str]]:
console_scripts = {}
gui_scripts = {}
for entry_point in dist.iter_entry_points():
if entry_point.group == "console_scripts":
if entry_point.group == 'console_scripts':
console_scripts[entry_point.name] = entry_point.value
elif entry_point.group == "gui_scripts":
elif entry_point.group == 'gui_scripts':
gui_scripts[entry_point.name] = entry_point.value
return console_scripts, gui_scripts
def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> Optional[str]:
def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> str | None:
"""Determine if any scripts are not on PATH and format a warning.
Returns a warning message if one or more scripts are not on PATH,
otherwise None.
@ -134,7 +137,7 @@ def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> Optional[str]:
return None
# Group scripts by the path they were installed in
grouped_by_dir: Dict[str, Set[str]] = collections.defaultdict(set)
grouped_by_dir: dict[str, set[str]] = collections.defaultdict(set)
for destfile in scripts:
parent_dir = os.path.dirname(destfile)
script_name = os.path.basename(destfile)
@ -143,12 +146,12 @@ def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> Optional[str]:
# We don't want to warn for directories that are on PATH.
not_warn_dirs = [
os.path.normcase(i).rstrip(os.sep)
for i in os.environ.get("PATH", "").split(os.pathsep)
for i in os.environ.get('PATH', '').split(os.pathsep)
]
# If an executable sits with sys.executable, we don't warn for it.
# This covers the case of venv invocations without activating the venv.
not_warn_dirs.append(os.path.normcase(os.path.dirname(sys.executable)))
warn_for: Dict[str, Set[str]] = {
warn_for: dict[str, set[str]] = {
parent_dir: scripts
for parent_dir, scripts in grouped_by_dir.items()
if os.path.normcase(parent_dir) not in not_warn_dirs
@ -159,47 +162,47 @@ def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> Optional[str]:
# Format a message
msg_lines = []
for parent_dir, dir_scripts in warn_for.items():
sorted_scripts: List[str] = sorted(dir_scripts)
sorted_scripts: list[str] = sorted(dir_scripts)
if len(sorted_scripts) == 1:
start_text = "script {} is".format(sorted_scripts[0])
start_text = f'script {sorted_scripts[0]} is'
else:
start_text = "scripts {} are".format(
", ".join(sorted_scripts[:-1]) + " and " + sorted_scripts[-1]
start_text = 'scripts {} are'.format(
', '.join(sorted_scripts[:-1]) + ' and ' + sorted_scripts[-1],
)
msg_lines.append(
"The {} installed in '{}' which is not on PATH.".format(
start_text, parent_dir
)
start_text, parent_dir,
),
)
last_line_fmt = (
"Consider adding {} to PATH or, if you prefer "
"to suppress this warning, use --no-warn-script-location."
'Consider adding {} to PATH or, if you prefer '
'to suppress this warning, use --no-warn-script-location.'
)
if len(msg_lines) == 1:
msg_lines.append(last_line_fmt.format("this directory"))
msg_lines.append(last_line_fmt.format('this directory'))
else:
msg_lines.append(last_line_fmt.format("these directories"))
msg_lines.append(last_line_fmt.format('these directories'))
# Add a note if any directory starts with ~
warn_for_tilde = any(
i[0] == "~" for i in os.environ.get("PATH", "").split(os.pathsep) if i
i[0] == '~' for i in os.environ.get('PATH', '').split(os.pathsep) if i
)
if warn_for_tilde:
tilde_warning_msg = (
"NOTE: The current PATH contains path(s) starting with `~`, "
"which may not be expanded by all applications."
'NOTE: The current PATH contains path(s) starting with `~`, '
'which may not be expanded by all applications.'
)
msg_lines.append(tilde_warning_msg)
# Returns the formatted multiline message
return "\n".join(msg_lines)
return '\n'.join(msg_lines)
def _normalized_outrows(
outrows: Iterable[InstalledCSVRow],
) -> List[Tuple[str, str, str]]:
) -> list[tuple[str, str, str]]:
"""Normalize the given rows of a RECORD file.
Items in each row are converted into str. Rows are then sorted to make
@ -227,52 +230,52 @@ def _record_to_fs_path(record_path: RecordPath) -> str:
return record_path
def _fs_to_record_path(path: str, relative_to: Optional[str] = None) -> RecordPath:
def _fs_to_record_path(path: str, relative_to: str | None = None) -> RecordPath:
if relative_to is not None:
# On Windows, do not handle relative paths if they belong to different
# logical disks
if (
os.path.splitdrive(path)[0].lower()
== os.path.splitdrive(relative_to)[0].lower()
os.path.splitdrive(path)[0].lower() ==
os.path.splitdrive(relative_to)[0].lower()
):
path = os.path.relpath(path, relative_to)
path = path.replace(os.path.sep, "/")
return cast("RecordPath", path)
path = path.replace(os.path.sep, '/')
return cast('RecordPath', path)
def get_csv_rows_for_installed(
old_csv_rows: List[List[str]],
installed: Dict[RecordPath, RecordPath],
changed: Set[RecordPath],
generated: List[str],
old_csv_rows: list[list[str]],
installed: dict[RecordPath, RecordPath],
changed: set[RecordPath],
generated: list[str],
lib_dir: str,
) -> List[InstalledCSVRow]:
) -> list[InstalledCSVRow]:
"""
:param installed: A map from archive RECORD path to installation RECORD
path.
"""
installed_rows: List[InstalledCSVRow] = []
installed_rows: list[InstalledCSVRow] = []
for row in old_csv_rows:
if len(row) > 3:
logger.warning("RECORD line has more than three elements: %s", row)
old_record_path = cast("RecordPath", row[0])
logger.warning('RECORD line has more than three elements: %s', row)
old_record_path = cast('RecordPath', row[0])
new_record_path = installed.pop(old_record_path, old_record_path)
if new_record_path in changed:
digest, length = rehash(_record_to_fs_path(new_record_path))
else:
digest = row[1] if len(row) > 1 else ""
length = row[2] if len(row) > 2 else ""
digest = row[1] if len(row) > 1 else ''
length = row[2] if len(row) > 2 else ''
installed_rows.append((new_record_path, digest, length))
for f in generated:
path = _fs_to_record_path(f, lib_dir)
digest, length = rehash(f)
installed_rows.append((path, digest, length))
for installed_record_path in installed.values():
installed_rows.append((installed_record_path, "", ""))
installed_rows.append((installed_record_path, '', ''))
return installed_rows
def get_console_script_specs(console: Dict[str, str]) -> List[str]:
def get_console_script_specs(console: dict[str, str]) -> list[str]:
"""
Given the mapping from entrypoint name to callable, return the relevant
console script specs.
@ -315,47 +318,47 @@ def get_console_script_specs(console: Dict[str, str]) -> List[str]:
# DEFAULT
# - The default behavior is to install pip, pipX, pipX.Y, easy_install
# and easy_install-X.Y.
pip_script = console.pop("pip", None)
pip_script = console.pop('pip', None)
if pip_script:
if "ENSUREPIP_OPTIONS" not in os.environ:
scripts_to_generate.append("pip = " + pip_script)
if 'ENSUREPIP_OPTIONS' not in os.environ:
scripts_to_generate.append('pip = ' + pip_script)
if os.environ.get("ENSUREPIP_OPTIONS", "") != "altinstall":
if os.environ.get('ENSUREPIP_OPTIONS', '') != 'altinstall':
scripts_to_generate.append(
"pip{} = {}".format(sys.version_info[0], pip_script)
f'pip{sys.version_info[0]} = {pip_script}',
)
scripts_to_generate.append(f"pip{get_major_minor_version()} = {pip_script}")
scripts_to_generate.append(f'pip{get_major_minor_version()} = {pip_script}')
# Delete any other versioned pip entry points
pip_ep = [k for k in console if re.match(r"pip(\d(\.\d)?)?$", k)]
pip_ep = [k for k in console if re.match(r'pip(\d(\.\d)?)?$', k)]
for k in pip_ep:
del console[k]
easy_install_script = console.pop("easy_install", None)
easy_install_script = console.pop('easy_install', None)
if easy_install_script:
if "ENSUREPIP_OPTIONS" not in os.environ:
scripts_to_generate.append("easy_install = " + easy_install_script)
if 'ENSUREPIP_OPTIONS' not in os.environ:
scripts_to_generate.append('easy_install = ' + easy_install_script)
scripts_to_generate.append(
"easy_install-{} = {}".format(
get_major_minor_version(), easy_install_script
)
'easy_install-{} = {}'.format(
get_major_minor_version(), easy_install_script,
),
)
# Delete any other versioned easy_install entry points
easy_install_ep = [
k for k in console if re.match(r"easy_install(-\d\.\d)?$", k)
k for k in console if re.match(r'easy_install(-\d\.\d)?$', k)
]
for k in easy_install_ep:
del console[k]
# Generate the console entry points specified in the wheel
scripts_to_generate.extend(starmap("{} = {}".format, console.items()))
scripts_to_generate.extend(starmap('{} = {}'.format, console.items()))
return scripts_to_generate
class ZipBackedFile:
def __init__(
self, src_record_path: RecordPath, dest_path: str, zip_file: ZipFile
self, src_record_path: RecordPath, dest_path: str, zip_file: ZipFile,
) -> None:
self.src_record_path = src_record_path
self.dest_path = dest_path
@ -386,7 +389,7 @@ class ZipBackedFile:
zipinfo = self._getinfo()
with self._zip_file.open(zipinfo) as f:
with open(self.dest_path, "wb") as dest:
with open(self.dest_path, 'wb') as dest:
shutil.copyfileobj(f, dest)
if zip_item_is_executable(zipinfo):
@ -394,7 +397,7 @@ class ZipBackedFile:
class ScriptFile:
def __init__(self, file: "File") -> None:
def __init__(self, file: File) -> None:
self._file = file
self.src_record_path = self._file.src_record_path
self.dest_path = self._file.dest_path
@ -408,10 +411,10 @@ class ScriptFile:
class MissingCallableSuffix(InstallationError):
def __init__(self, entry_point: str) -> None:
super().__init__(
"Invalid script entry point: {} - A callable "
"suffix is required. Cf https://packaging.python.org/"
"specifications/entry-points/#use-for-scripts for more "
"information.".format(entry_point)
'Invalid script entry point: {} - A callable '
'suffix is required. Cf https://packaging.python.org/'
'specifications/entry-points/#use-for-scripts for more '
'information.'.format(entry_point),
)
@ -422,7 +425,7 @@ def _raise_for_invalid_entrypoint(specification: str) -> None:
class PipScriptMaker(ScriptMaker):
def make(self, specification: str, options: Dict[str, Any] = None) -> List[str]:
def make(self, specification: str, options: dict[str, Any] = None) -> list[str]:
_raise_for_invalid_entrypoint(specification)
return super().make(specification, options)
@ -434,7 +437,7 @@ def _install_wheel(
scheme: Scheme,
pycompile: bool = True,
warn_script_location: bool = True,
direct_url: Optional[DirectUrl] = None,
direct_url: DirectUrl | None = None,
requested: bool = False,
) -> None:
"""Install a wheel.
@ -463,12 +466,12 @@ def _install_wheel(
# installed = files copied from the wheel to the destination
# changed = files changed while installing (scripts #! line typically)
# generated = files newly generated during the install (script wrappers)
installed: Dict[RecordPath, RecordPath] = {}
changed: Set[RecordPath] = set()
generated: List[str] = []
installed: dict[RecordPath, RecordPath] = {}
changed: set[RecordPath] = set()
generated: list[str] = []
def record_installed(
srcfile: RecordPath, destfile: str, modified: bool = False
srcfile: RecordPath, destfile: str, modified: bool = False,
) -> None:
"""Map archive RECORD paths to installation RECORD paths."""
newpath = _fs_to_record_path(destfile, lib_dir)
@ -477,22 +480,22 @@ def _install_wheel(
changed.add(_fs_to_record_path(destfile))
def is_dir_path(path: RecordPath) -> bool:
return path.endswith("/")
return path.endswith('/')
def assert_no_path_traversal(dest_dir_path: str, target_path: str) -> None:
if not is_within_directory(dest_dir_path, target_path):
message = (
"The wheel {!r} has a file {!r} trying to install"
" outside the target directory {!r}"
'The wheel {!r} has a file {!r} trying to install'
' outside the target directory {!r}'
)
raise InstallationError(
message.format(wheel_path, target_path, dest_dir_path)
message.format(wheel_path, target_path, dest_dir_path),
)
def root_scheme_file_maker(
zip_file: ZipFile, dest: str
) -> Callable[[RecordPath], "File"]:
def make_root_scheme_file(record_path: RecordPath) -> "File":
zip_file: ZipFile, dest: str,
) -> Callable[[RecordPath], File]:
def make_root_scheme_file(record_path: RecordPath) -> File:
normed_path = os.path.normpath(record_path)
dest_path = os.path.join(dest, normed_path)
assert_no_path_traversal(dest, dest_path)
@ -501,17 +504,17 @@ def _install_wheel(
return make_root_scheme_file
def data_scheme_file_maker(
zip_file: ZipFile, scheme: Scheme
) -> Callable[[RecordPath], "File"]:
zip_file: ZipFile, scheme: Scheme,
) -> Callable[[RecordPath], File]:
scheme_paths = {key: getattr(scheme, key) for key in SCHEME_KEYS}
def make_data_scheme_file(record_path: RecordPath) -> "File":
def make_data_scheme_file(record_path: RecordPath) -> File:
normed_path = os.path.normpath(record_path)
try:
_, scheme_key, dest_subpath = normed_path.split(os.path.sep, 2)
except ValueError:
message = (
"Unexpected file in {}: {!r}. .data directory contents"
'Unexpected file in {}: {!r}. .data directory contents'
" should be named like: '<scheme key>/<path>'."
).format(wheel_path, record_path)
raise InstallationError(message)
@ -519,11 +522,11 @@ def _install_wheel(
try:
scheme_path = scheme_paths[scheme_key]
except KeyError:
valid_scheme_keys = ", ".join(sorted(scheme_paths))
valid_scheme_keys = ', '.join(sorted(scheme_paths))
message = (
"Unknown scheme key used in {}: {} (for file {!r}). .data"
" directory contents should be in subdirectories named"
" with a valid scheme key ({})"
'Unknown scheme key used in {}: {} (for file {!r}). .data'
' directory contents should be in subdirectories named'
' with a valid scheme key ({})'
).format(wheel_path, scheme_key, record_path, valid_scheme_keys)
raise InstallationError(message)
@ -534,7 +537,7 @@ def _install_wheel(
return make_data_scheme_file
def is_data_scheme_path(path: RecordPath) -> bool:
return path.split("/", 1)[0].endswith(".data")
return path.split('/', 1)[0].endswith('.data')
paths = cast(List[RecordPath], wheel_zip.namelist())
file_paths = filterfalse(is_dir_path, paths)
@ -544,11 +547,11 @@ def _install_wheel(
files: Iterator[File] = map(make_root_scheme_file, root_scheme_paths)
def is_script_scheme_path(path: RecordPath) -> bool:
parts = path.split("/", 2)
return len(parts) > 2 and parts[0].endswith(".data") and parts[1] == "scripts"
parts = path.split('/', 2)
return len(parts) > 2 and parts[0].endswith('.data') and parts[1] == 'scripts'
other_scheme_paths, script_scheme_paths = partition(
is_script_scheme_path, data_scheme_paths
is_script_scheme_path, data_scheme_paths,
)
make_data_scheme_file = data_scheme_file_maker(wheel_zip, scheme)
@ -562,16 +565,16 @@ def _install_wheel(
)
console, gui = get_entrypoints(distribution)
def is_entrypoint_wrapper(file: "File") -> bool:
def is_entrypoint_wrapper(file: File) -> bool:
# EP, EP.exe and EP-script.py are scripts generated for
# entry point EP by setuptools
path = file.dest_path
name = os.path.basename(path)
if name.lower().endswith(".exe"):
if name.lower().endswith('.exe'):
matchname = name[:-4]
elif name.lower().endswith("-script.py"):
elif name.lower().endswith('-script.py'):
matchname = name[:-10]
elif name.lower().endswith(".pya"):
elif name.lower().endswith('.pya'):
matchname = name[:-4]
else:
matchname = name
@ -579,7 +582,7 @@ def _install_wheel(
return matchname in console or matchname in gui
script_scheme_files: Iterator[File] = map(
make_data_scheme_file, script_scheme_paths
make_data_scheme_file, script_scheme_paths,
)
script_scheme_files = filterfalse(is_entrypoint_wrapper, script_scheme_files)
script_scheme_files = map(ScriptFile, script_scheme_files)
@ -598,7 +601,7 @@ def _install_wheel(
full_installed_path = os.path.join(lib_dir, installed_path)
if not os.path.isfile(full_installed_path):
continue
if not full_installed_path.endswith(".py"):
if not full_installed_path.endswith('.py'):
continue
yield full_installed_path
@ -610,14 +613,14 @@ def _install_wheel(
if pycompile:
with captured_stdout() as stdout:
with warnings.catch_warnings():
warnings.filterwarnings("ignore")
warnings.filterwarnings('ignore')
for path in pyc_source_file_paths():
success = compileall.compile_file(path, force=True, quiet=True)
if success:
pyc_path = pyc_output_path(path)
assert os.path.exists(pyc_path)
pyc_record_path = cast(
"RecordPath", pyc_path.replace(os.path.sep, "/")
'RecordPath', pyc_path.replace(os.path.sep, '/'),
)
record_installed(pyc_record_path, pyc_path)
logger.debug(stdout.getvalue())
@ -631,7 +634,7 @@ def _install_wheel(
# Ensure we don't generate any variants for scripts because this is almost
# never what somebody wants.
# See https://bitbucket.org/pypa/distlib/issue/35/
maker.variants = {""}
maker.variants = {''}
# This is required because otherwise distlib creates scripts that are not
# executable.
@ -641,12 +644,12 @@ def _install_wheel(
# Generate the console and GUI entry points specified in the wheel
scripts_to_generate = get_console_script_specs(console)
gui_scripts_to_generate = list(starmap("{} = {}".format, gui.items()))
gui_scripts_to_generate = list(starmap('{} = {}'.format, gui.items()))
generated_console_scripts = maker.make_multiple(scripts_to_generate)
generated.extend(generated_console_scripts)
generated.extend(maker.make_multiple(gui_scripts_to_generate, {"gui": True}))
generated.extend(maker.make_multiple(gui_scripts_to_generate, {'gui': True}))
if warn_script_location:
msg = message_about_scripts_not_on_PATH(generated_console_scripts)
@ -665,26 +668,26 @@ def _install_wheel(
dest_info_dir = os.path.join(lib_dir, info_dir)
# Record pip as the installer
installer_path = os.path.join(dest_info_dir, "INSTALLER")
installer_path = os.path.join(dest_info_dir, 'INSTALLER')
with _generate_file(installer_path) as installer_file:
installer_file.write(b"pip\n")
installer_file.write(b'pip\n')
generated.append(installer_path)
# Record the PEP 610 direct URL reference
if direct_url is not None:
direct_url_path = os.path.join(dest_info_dir, DIRECT_URL_METADATA_NAME)
with _generate_file(direct_url_path) as direct_url_file:
direct_url_file.write(direct_url.to_json().encode("utf-8"))
direct_url_file.write(direct_url.to_json().encode('utf-8'))
generated.append(direct_url_path)
# Record the REQUESTED file
if requested:
requested_path = os.path.join(dest_info_dir, "REQUESTED")
with open(requested_path, "wb"):
requested_path = os.path.join(dest_info_dir, 'REQUESTED')
with open(requested_path, 'wb'):
pass
generated.append(requested_path)
record_text = distribution.read_text("RECORD")
record_text = distribution.read_text('RECORD')
record_rows = list(csv.reader(record_text.splitlines()))
rows = get_csv_rows_for_installed(
@ -696,12 +699,12 @@ def _install_wheel(
)
# Record details of all files installed
record_path = os.path.join(dest_info_dir, "RECORD")
record_path = os.path.join(dest_info_dir, 'RECORD')
with _generate_file(record_path, **csv_io_kwargs("w")) as record_file:
with _generate_file(record_path, **csv_io_kwargs('w')) as record_file:
# Explicitly cast to typing.IO[str] as a workaround for the mypy error:
# "writer" has incompatible type "BinaryIO"; expected "_Writer"
writer = csv.writer(cast("IO[str]", record_file))
writer = csv.writer(cast('IO[str]', record_file))
writer.writerows(_normalized_outrows(rows))
@ -710,7 +713,7 @@ def req_error_context(req_description: str) -> Iterator[None]:
try:
yield
except InstallationError as e:
message = "For req: {}. {}".format(req_description, e.args[0])
message = f'For req: {req_description}. {e.args[0]}'
raise InstallationError(message) from e
@ -721,7 +724,7 @@ def install_wheel(
req_description: str,
pycompile: bool = True,
warn_script_location: bool = True,
direct_url: Optional[DirectUrl] = None,
direct_url: DirectUrl | None = None,
requested: bool = False,
) -> None:
with ZipFile(wheel_path, allowZip64=True) as z: