mirror of
https://github.com/pypa/pip
synced 2023-12-13 21:30:23 +01:00
Complete typing of some tests/lib/* files
This commit is contained in:
parent
ed9c0d96ec
commit
34a3838b73
|
@ -88,7 +88,7 @@ class Command(CommandContextMixIn):
|
||||||
def run(self, options: Values, args: List[Any]) -> int:
|
def run(self, options: Values, args: List[Any]) -> int:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def parse_args(self, args: List[str]) -> Tuple[Any, Any]:
|
def parse_args(self, args: List[str]) -> Tuple[Values, List[str]]:
|
||||||
# factored out for testability
|
# factored out for testability
|
||||||
return self.parser.parse_args(args)
|
return self.parser.parse_args(args)
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import re
|
import re
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from pip._internal.models.direct_url import DIRECT_URL_METADATA_NAME, DirectUrl
|
from pip._internal.models.direct_url import DIRECT_URL_METADATA_NAME, DirectUrl
|
||||||
|
from tests.lib import TestPipResult
|
||||||
|
|
||||||
|
|
||||||
def get_created_direct_url(result, pkg):
|
def get_created_direct_url(result: TestPipResult, pkg: str) -> Optional[DirectUrl]:
|
||||||
direct_url_metadata_re = re.compile(
|
direct_url_metadata_re = re.compile(
|
||||||
pkg + r"-[\d\.]+\.dist-info." + DIRECT_URL_METADATA_NAME + r"$"
|
pkg + r"-[\d\.]+\.dist-info." + DIRECT_URL_METADATA_NAME + r"$"
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,11 +6,12 @@ import subprocess
|
||||||
import sys
|
import sys
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
from typing import Iterator, List, Set
|
||||||
|
|
||||||
from .path import Path
|
from .path import Path
|
||||||
|
|
||||||
|
|
||||||
def make_socket_file(path):
|
def make_socket_file(path: str) -> None:
|
||||||
# Socket paths are limited to 108 characters (sometimes less) so we
|
# Socket paths are limited to 108 characters (sometimes less) so we
|
||||||
# chdir before creating it and use a relative path name.
|
# chdir before creating it and use a relative path name.
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
|
@ -22,7 +23,7 @@ def make_socket_file(path):
|
||||||
os.chdir(cwd)
|
os.chdir(cwd)
|
||||||
|
|
||||||
|
|
||||||
def make_unreadable_file(path):
|
def make_unreadable_file(path: str) -> None:
|
||||||
Path(path).touch()
|
Path(path).touch()
|
||||||
os.chmod(path, 0o000)
|
os.chmod(path, 0o000)
|
||||||
if sys.platform == "win32":
|
if sys.platform == "win32":
|
||||||
|
@ -34,8 +35,8 @@ def make_unreadable_file(path):
|
||||||
subprocess.check_call(args)
|
subprocess.check_call(args)
|
||||||
|
|
||||||
|
|
||||||
def get_filelist(base):
|
def get_filelist(base: str) -> Set[str]:
|
||||||
def join(dirpath, dirnames, filenames):
|
def join(dirpath: str, dirnames: List[str], filenames: List[str]) -> Iterator[str]:
|
||||||
relative_dirpath = os.path.relpath(dirpath, base)
|
relative_dirpath = os.path.relpath(dirpath, base)
|
||||||
join_dirpath = partial(os.path.join, relative_dirpath)
|
join_dirpath = partial(os.path.join, relative_dirpath)
|
||||||
return chain(
|
return chain(
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from pip._internal.models.candidate import InstallationCandidate
|
from pip._internal.models.candidate import InstallationCandidate
|
||||||
from pip._internal.models.link import Link
|
from pip._internal.models.link import Link
|
||||||
|
|
||||||
|
|
||||||
def make_mock_candidate(version, yanked_reason=None, hex_digest=None):
|
def make_mock_candidate(
|
||||||
|
version: str, yanked_reason: Optional[str] = None, hex_digest: Optional[str] = None
|
||||||
|
) -> InstallationCandidate:
|
||||||
url = f"https://example.com/pkg-{version}.tar.gz"
|
url = f"https://example.com/pkg-{version}.tar.gz"
|
||||||
if hex_digest is not None:
|
if hex_digest is not None:
|
||||||
assert len(hex_digest) == 64
|
assert len(hex_digest) == 64
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
"""Provides helper classes for testing option handling in pip
|
"""Provides helper classes for testing option handling in pip
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from optparse import Values
|
||||||
|
from typing import List, Tuple
|
||||||
|
|
||||||
from pip._internal.cli import cmdoptions
|
from pip._internal.cli import cmdoptions
|
||||||
from pip._internal.cli.base_command import Command
|
from pip._internal.cli.base_command import Command
|
||||||
from pip._internal.commands import CommandInfo, commands_dict
|
from pip._internal.commands import CommandInfo, commands_dict
|
||||||
|
|
||||||
|
|
||||||
class FakeCommand(Command):
|
class FakeCommand(Command):
|
||||||
def main(self, args):
|
def main( # type: ignore[override]
|
||||||
|
self, args: List[str]
|
||||||
|
) -> Tuple[Values, List[str]]:
|
||||||
index_opts = cmdoptions.make_option_group(
|
index_opts = cmdoptions.make_option_group(
|
||||||
cmdoptions.index_group,
|
cmdoptions.index_group,
|
||||||
self.parser,
|
self.parser,
|
||||||
|
@ -17,12 +22,12 @@ class FakeCommand(Command):
|
||||||
|
|
||||||
|
|
||||||
class AddFakeCommandMixin:
|
class AddFakeCommandMixin:
|
||||||
def setup(self):
|
def setup(self) -> None:
|
||||||
commands_dict["fake"] = CommandInfo(
|
commands_dict["fake"] = CommandInfo(
|
||||||
"tests.lib.options_helpers",
|
"tests.lib.options_helpers",
|
||||||
"FakeCommand",
|
"FakeCommand",
|
||||||
"fake summary",
|
"fake summary",
|
||||||
)
|
)
|
||||||
|
|
||||||
def teardown(self):
|
def teardown(self) -> None:
|
||||||
commands_dict.pop("fake")
|
commands_dict.pop("fake")
|
||||||
|
|
|
@ -1,12 +1,7 @@
|
||||||
# flake8: noqa
|
|
||||||
# Author: Aziz Köksal
|
# Author: Aziz Köksal
|
||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
|
from typing import Iterable, Iterator, Union
|
||||||
try:
|
|
||||||
from os import supports_fd
|
|
||||||
except ImportError:
|
|
||||||
supports_fd = set()
|
|
||||||
|
|
||||||
|
|
||||||
class Path(str):
|
class Path(str):
|
||||||
|
@ -20,12 +15,12 @@ class Path(str):
|
||||||
# Separator in the PATH environment variable.
|
# Separator in the PATH environment variable.
|
||||||
pathsep = os.pathsep
|
pathsep = os.pathsep
|
||||||
|
|
||||||
def __new__(cls, *paths):
|
def __new__(cls, *paths: str) -> "Path":
|
||||||
if len(paths):
|
if len(paths):
|
||||||
return super().__new__(cls, os.path.join(*paths))
|
return super().__new__(cls, os.path.join(*paths))
|
||||||
return super().__new__(cls)
|
return super().__new__(cls)
|
||||||
|
|
||||||
def __div__(self, path):
|
def __div__(self, path: str) -> "Path":
|
||||||
"""
|
"""
|
||||||
Joins this path with another path.
|
Joins this path with another path.
|
||||||
|
|
||||||
|
@ -36,7 +31,7 @@ class Path(str):
|
||||||
|
|
||||||
__truediv__ = __div__
|
__truediv__ = __div__
|
||||||
|
|
||||||
def __rdiv__(self, path):
|
def __rdiv__(self, path: str) -> "Path":
|
||||||
"""
|
"""
|
||||||
Joins this path with another path.
|
Joins this path with another path.
|
||||||
|
|
||||||
|
@ -46,7 +41,7 @@ class Path(str):
|
||||||
|
|
||||||
__rtruediv__ = __rdiv__
|
__rtruediv__ = __rdiv__
|
||||||
|
|
||||||
def __idiv__(self, path):
|
def __idiv__(self, path: str) -> "Path":
|
||||||
"""
|
"""
|
||||||
Like __div__ but also assigns to the variable.
|
Like __div__ but also assigns to the variable.
|
||||||
|
|
||||||
|
@ -56,52 +51,52 @@ class Path(str):
|
||||||
|
|
||||||
__itruediv__ = __idiv__
|
__itruediv__ = __idiv__
|
||||||
|
|
||||||
def __add__(self, path):
|
def __add__(self, path: str) -> "Path":
|
||||||
"""
|
"""
|
||||||
>>> Path('/home/a') + 'bc.d'
|
>>> Path('/home/a') + 'bc.d'
|
||||||
'/home/abc.d'
|
'/home/abc.d'
|
||||||
"""
|
"""
|
||||||
return Path(str(self) + path)
|
return Path(str(self) + path)
|
||||||
|
|
||||||
def __radd__(self, path):
|
def __radd__(self, path: str) -> "Path":
|
||||||
"""
|
"""
|
||||||
>>> '/home/a' + Path('bc.d')
|
>>> '/home/a' + Path('bc.d')
|
||||||
'/home/abc.d'
|
'/home/abc.d'
|
||||||
"""
|
"""
|
||||||
return Path(path + str(self))
|
return Path(path + str(self))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
return "Path({inner})".format(inner=str.__repr__(self))
|
return "Path({inner})".format(inner=str.__repr__(self))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self) -> str:
|
||||||
"""
|
"""
|
||||||
'/home/a/bc.d' -> 'bc.d'
|
'/home/a/bc.d' -> 'bc.d'
|
||||||
"""
|
"""
|
||||||
return os.path.basename(self)
|
return os.path.basename(self)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def stem(self):
|
def stem(self) -> str:
|
||||||
"""
|
"""
|
||||||
'/home/a/bc.d' -> 'bc'
|
'/home/a/bc.d' -> 'bc'
|
||||||
"""
|
"""
|
||||||
return Path(os.path.splitext(self)[0]).name
|
return Path(os.path.splitext(self)[0]).name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def suffix(self):
|
def suffix(self) -> str:
|
||||||
"""
|
"""
|
||||||
'/home/a/bc.d' -> '.d'
|
'/home/a/bc.d' -> '.d'
|
||||||
"""
|
"""
|
||||||
return Path(os.path.splitext(self)[1])
|
return Path(os.path.splitext(self)[1])
|
||||||
|
|
||||||
def resolve(self):
|
def resolve(self) -> "Path":
|
||||||
"""
|
"""
|
||||||
Resolves symbolic links.
|
Resolves symbolic links.
|
||||||
"""
|
"""
|
||||||
return Path(os.path.realpath(self))
|
return Path(os.path.realpath(self))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def parent(self):
|
def parent(self) -> "Path":
|
||||||
"""
|
"""
|
||||||
Returns the parent directory of this path.
|
Returns the parent directory of this path.
|
||||||
|
|
||||||
|
@ -111,13 +106,18 @@ class Path(str):
|
||||||
"""
|
"""
|
||||||
return Path(os.path.dirname(self))
|
return Path(os.path.dirname(self))
|
||||||
|
|
||||||
def exists(self):
|
def exists(self) -> bool:
|
||||||
"""
|
"""
|
||||||
Returns True if the path exists.
|
Returns True if the path exists.
|
||||||
"""
|
"""
|
||||||
return os.path.exists(self)
|
return os.path.exists(self)
|
||||||
|
|
||||||
def mkdir(self, mode=0x1FF, exist_ok=False, parents=False): # 0o777
|
def mkdir(
|
||||||
|
self,
|
||||||
|
mode: int = 0o777,
|
||||||
|
exist_ok: bool = False,
|
||||||
|
parents: bool = False,
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Creates a directory, if it doesn't exist already.
|
Creates a directory, if it doesn't exist already.
|
||||||
|
|
||||||
|
@ -131,32 +131,32 @@ class Path(str):
|
||||||
if not exist_ok or not os.path.isdir(self):
|
if not exist_ok or not os.path.isdir(self):
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def unlink(self):
|
def unlink(self) -> None:
|
||||||
"""
|
"""
|
||||||
Removes a file.
|
Removes a file.
|
||||||
"""
|
"""
|
||||||
return os.remove(self)
|
os.remove(self)
|
||||||
|
|
||||||
def rmdir(self):
|
def rmdir(self) -> None:
|
||||||
"""
|
"""
|
||||||
Removes a directory.
|
Removes a directory.
|
||||||
"""
|
"""
|
||||||
return os.rmdir(self)
|
os.rmdir(self)
|
||||||
|
|
||||||
def rename(self, to):
|
def rename(self, to: str) -> None:
|
||||||
"""
|
"""
|
||||||
Renames a file or directory. May throw an OSError.
|
Renames a file or directory. May throw an OSError.
|
||||||
"""
|
"""
|
||||||
return os.rename(self, to)
|
os.rename(self, to)
|
||||||
|
|
||||||
def glob(self, pattern):
|
def glob(self, pattern: str) -> Iterator["Path"]:
|
||||||
return (Path(i) for i in glob.iglob(self.joinpath(pattern)))
|
return (Path(i) for i in glob.iglob(self.joinpath(pattern)))
|
||||||
|
|
||||||
def joinpath(self, *parts):
|
def joinpath(self, *parts: str) -> "Path":
|
||||||
return Path(self, *parts)
|
return Path(self, *parts)
|
||||||
|
|
||||||
# TODO: Remove after removing inheritance from str.
|
# TODO: Remove after removing inheritance from str.
|
||||||
def join(self, *parts):
|
def join(self, parts: Iterable[str]) -> str:
|
||||||
raise RuntimeError("Path.join is invalid, use joinpath instead.")
|
raise RuntimeError("Path.join is invalid, use joinpath instead.")
|
||||||
|
|
||||||
def read_bytes(self) -> bytes:
|
def read_bytes(self) -> bytes:
|
||||||
|
@ -167,23 +167,23 @@ class Path(str):
|
||||||
with open(self, "wb") as f:
|
with open(self, "wb") as f:
|
||||||
f.write(content)
|
f.write(content)
|
||||||
|
|
||||||
def read_text(self):
|
def read_text(self) -> str:
|
||||||
with open(self, "r") as fp:
|
with open(self, "r") as fp:
|
||||||
return fp.read()
|
return fp.read()
|
||||||
|
|
||||||
def write_text(self, content):
|
def write_text(self, content: str) -> None:
|
||||||
with open(self, "w") as fp:
|
with open(self, "w") as fp:
|
||||||
fp.write(content)
|
fp.write(content)
|
||||||
|
|
||||||
def touch(self):
|
def touch(self) -> None:
|
||||||
with open(self, "a") as fp:
|
with open(self, "a") as fp:
|
||||||
path = fp.fileno() if os.utime in supports_fd else self
|
path: Union[int, str] = fp.fileno() if os.utime in os.supports_fd else self
|
||||||
os.utime(path, None) # times is not optional on Python 2.7
|
os.utime(path)
|
||||||
|
|
||||||
def symlink_to(self, target):
|
def symlink_to(self, target: str) -> None:
|
||||||
os.symlink(target, self)
|
os.symlink(target, self)
|
||||||
|
|
||||||
def stat(self):
|
def stat(self) -> os.stat_result:
|
||||||
return os.stat(self)
|
return os.stat(self)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,16 @@ import subprocess
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
import venv as _venv
|
import venv as _venv
|
||||||
|
from typing import TYPE_CHECKING, Optional
|
||||||
|
|
||||||
import virtualenv as _virtualenv
|
import virtualenv as _virtualenv
|
||||||
|
|
||||||
from .path import Path
|
from .path import Path
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
# Literal was introduced in Python 3.8.
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
|
|
||||||
class VirtualEnvironment:
|
class VirtualEnvironment:
|
||||||
"""
|
"""
|
||||||
|
@ -16,18 +21,28 @@ class VirtualEnvironment:
|
||||||
virtualenv but in the future it could use pyvenv.
|
virtualenv but in the future it could use pyvenv.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, location, template=None, venv_type=None):
|
def __init__(
|
||||||
assert template is None or venv_type is None
|
self,
|
||||||
assert venv_type in (None, "virtualenv", "venv")
|
location: str,
|
||||||
|
template: Optional["VirtualEnvironment"] = None,
|
||||||
|
venv_type: 'Literal[None, "virtualenv", "venv"]' = None,
|
||||||
|
):
|
||||||
self.location = Path(location)
|
self.location = Path(location)
|
||||||
self._venv_type = venv_type or template._venv_type or "virtualenv"
|
assert template is None or venv_type is None
|
||||||
|
self._venv_type: Literal["virtualenv", "venv"]
|
||||||
|
if template is not None:
|
||||||
|
self._venv_type = template._venv_type
|
||||||
|
elif venv_type is not None:
|
||||||
|
self._venv_type = venv_type
|
||||||
|
else:
|
||||||
|
self._venv_type = "virtualenv"
|
||||||
self._user_site_packages = False
|
self._user_site_packages = False
|
||||||
self._template = template
|
self._template = template
|
||||||
self._sitecustomize = None
|
self._sitecustomize: Optional[str] = None
|
||||||
self._update_paths()
|
self._update_paths()
|
||||||
self._create()
|
self._create()
|
||||||
|
|
||||||
def _update_paths(self):
|
def _update_paths(self) -> None:
|
||||||
home, lib, inc, bin = _virtualenv.path_locations(self.location)
|
home, lib, inc, bin = _virtualenv.path_locations(self.location)
|
||||||
self.bin = Path(bin)
|
self.bin = Path(bin)
|
||||||
self.site = Path(lib) / "site-packages"
|
self.site = Path(lib) / "site-packages"
|
||||||
|
@ -38,10 +53,10 @@ class VirtualEnvironment:
|
||||||
else:
|
else:
|
||||||
self.lib = Path(lib)
|
self.lib = Path(lib)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
return f"<VirtualEnvironment {self.location}>"
|
return f"<VirtualEnvironment {self.location}>"
|
||||||
|
|
||||||
def _create(self, clear=False):
|
def _create(self, clear: bool = False) -> None:
|
||||||
if clear:
|
if clear:
|
||||||
shutil.rmtree(self.location)
|
shutil.rmtree(self.location)
|
||||||
if self._template:
|
if self._template:
|
||||||
|
@ -77,7 +92,7 @@ class VirtualEnvironment:
|
||||||
self.sitecustomize = self._sitecustomize
|
self.sitecustomize = self._sitecustomize
|
||||||
self.user_site_packages = self._user_site_packages
|
self.user_site_packages = self._user_site_packages
|
||||||
|
|
||||||
def _fix_virtualenv_site_module(self):
|
def _fix_virtualenv_site_module(self) -> None:
|
||||||
# Patch `site.py` so user site work as expected.
|
# Patch `site.py` so user site work as expected.
|
||||||
site_py = self.lib / "site.py"
|
site_py = self.lib / "site.py"
|
||||||
with open(site_py) as fp:
|
with open(site_py) as fp:
|
||||||
|
@ -111,7 +126,7 @@ class VirtualEnvironment:
|
||||||
# Make sure bytecode is up-to-date too.
|
# Make sure bytecode is up-to-date too.
|
||||||
assert compileall.compile_file(str(site_py), quiet=1, force=True)
|
assert compileall.compile_file(str(site_py), quiet=1, force=True)
|
||||||
|
|
||||||
def _customize_site(self):
|
def _customize_site(self) -> None:
|
||||||
contents = ""
|
contents = ""
|
||||||
if self._venv_type == "venv":
|
if self._venv_type == "venv":
|
||||||
# Enable user site (before system).
|
# Enable user site (before system).
|
||||||
|
@ -149,29 +164,29 @@ class VirtualEnvironment:
|
||||||
# Make sure bytecode is up-to-date too.
|
# Make sure bytecode is up-to-date too.
|
||||||
assert compileall.compile_file(str(sitecustomize), quiet=1, force=True)
|
assert compileall.compile_file(str(sitecustomize), quiet=1, force=True)
|
||||||
|
|
||||||
def clear(self):
|
def clear(self) -> None:
|
||||||
self._create(clear=True)
|
self._create(clear=True)
|
||||||
|
|
||||||
def move(self, location):
|
def move(self, location: str) -> None:
|
||||||
shutil.move(self.location, location)
|
shutil.move(self.location, location)
|
||||||
self.location = Path(location)
|
self.location = Path(location)
|
||||||
self._update_paths()
|
self._update_paths()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def sitecustomize(self):
|
def sitecustomize(self) -> Optional[str]:
|
||||||
return self._sitecustomize
|
return self._sitecustomize
|
||||||
|
|
||||||
@sitecustomize.setter
|
@sitecustomize.setter
|
||||||
def sitecustomize(self, value):
|
def sitecustomize(self, value: str) -> None:
|
||||||
self._sitecustomize = value
|
self._sitecustomize = value
|
||||||
self._customize_site()
|
self._customize_site()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def user_site_packages(self):
|
def user_site_packages(self) -> bool:
|
||||||
return self._user_site_packages
|
return self._user_site_packages
|
||||||
|
|
||||||
@user_site_packages.setter
|
@user_site_packages.setter
|
||||||
def user_site_packages(self, value):
|
def user_site_packages(self, value: bool) -> None:
|
||||||
self._user_site_packages = value
|
self._user_site_packages = value
|
||||||
if self._venv_type == "virtualenv":
|
if self._venv_type == "virtualenv":
|
||||||
marker = self.lib / "no-global-site-packages.txt"
|
marker = self.lib / "no-global-site-packages.txt"
|
||||||
|
|
Loading…
Reference in a new issue