diff options
author | Jon Dufresne <jon.dufresne@gmail.com> | 2021-08-25 07:02:26 -0700 |
---|---|---|
committer | Jon Dufresne <jon.dufresne@gmail.com> | 2021-08-27 09:25:22 -0700 |
commit | 34a3838b733275e2cd221d3264a6fdf9f7160827 (patch) | |
tree | 65eaca359d18d8ff51cbdd09106c895121386317 | |
parent | ed9c0d96ecdea27ff0cef04dd68cc7697fba6201 (diff) | |
download | pip-34a3838b733275e2cd221d3264a6fdf9f7160827.tar.gz |
Complete typing of some tests/lib/* files
-rw-r--r-- | news/06d03f6d-b858-4973-af59-2a8bbad0f6dc.trivial.rst | 0 | ||||
-rw-r--r-- | src/pip/_internal/cli/base_command.py | 2 | ||||
-rw-r--r-- | tests/lib/direct_url.py | 4 | ||||
-rw-r--r-- | tests/lib/filesystem.py | 9 | ||||
-rw-r--r-- | tests/lib/index.py | 6 | ||||
-rw-r--r-- | tests/lib/options_helpers.py | 11 | ||||
-rw-r--r-- | tests/lib/path.py | 72 | ||||
-rw-r--r-- | tests/lib/venv.py | 47 |
8 files changed, 89 insertions, 62 deletions
diff --git a/news/06d03f6d-b858-4973-af59-2a8bbad0f6dc.trivial.rst b/news/06d03f6d-b858-4973-af59-2a8bbad0f6dc.trivial.rst new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/news/06d03f6d-b858-4973-af59-2a8bbad0f6dc.trivial.rst diff --git a/src/pip/_internal/cli/base_command.py b/src/pip/_internal/cli/base_command.py index eea38306a..200b8e47e 100644 --- a/src/pip/_internal/cli/base_command.py +++ b/src/pip/_internal/cli/base_command.py @@ -88,7 +88,7 @@ class Command(CommandContextMixIn): def run(self, options: Values, args: List[Any]) -> int: 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 return self.parser.parse_args(args) diff --git a/tests/lib/direct_url.py b/tests/lib/direct_url.py index 497e10c6b..7f1dee8bd 100644 --- a/tests/lib/direct_url.py +++ b/tests/lib/direct_url.py @@ -1,9 +1,11 @@ import re +from typing import Optional 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( pkg + r"-[\d\.]+\.dist-info." + DIRECT_URL_METADATA_NAME + r"$" ) diff --git a/tests/lib/filesystem.py b/tests/lib/filesystem.py index 05e2db62c..84a1c81bd 100644 --- a/tests/lib/filesystem.py +++ b/tests/lib/filesystem.py @@ -6,11 +6,12 @@ import subprocess import sys from functools import partial from itertools import chain +from typing import Iterator, List, Set 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 # chdir before creating it and use a relative path name. cwd = os.getcwd() @@ -22,7 +23,7 @@ def make_socket_file(path): os.chdir(cwd) -def make_unreadable_file(path): +def make_unreadable_file(path: str) -> None: Path(path).touch() os.chmod(path, 0o000) if sys.platform == "win32": @@ -34,8 +35,8 @@ def make_unreadable_file(path): subprocess.check_call(args) -def get_filelist(base): - def join(dirpath, dirnames, filenames): +def get_filelist(base: str) -> Set[str]: + def join(dirpath: str, dirnames: List[str], filenames: List[str]) -> Iterator[str]: relative_dirpath = os.path.relpath(dirpath, base) join_dirpath = partial(os.path.join, relative_dirpath) return chain( diff --git a/tests/lib/index.py b/tests/lib/index.py index dff0ac103..17282bc56 100644 --- a/tests/lib/index.py +++ b/tests/lib/index.py @@ -1,8 +1,12 @@ +from typing import Optional + from pip._internal.models.candidate import InstallationCandidate 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" if hex_digest is not None: assert len(hex_digest) == 64 diff --git a/tests/lib/options_helpers.py b/tests/lib/options_helpers.py index 8aa105b96..31f650035 100644 --- a/tests/lib/options_helpers.py +++ b/tests/lib/options_helpers.py @@ -1,13 +1,18 @@ """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.base_command import Command from pip._internal.commands import CommandInfo, commands_dict 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( cmdoptions.index_group, self.parser, @@ -17,12 +22,12 @@ class FakeCommand(Command): class AddFakeCommandMixin: - def setup(self): + def setup(self) -> None: commands_dict["fake"] = CommandInfo( "tests.lib.options_helpers", "FakeCommand", "fake summary", ) - def teardown(self): + def teardown(self) -> None: commands_dict.pop("fake") diff --git a/tests/lib/path.py b/tests/lib/path.py index 8ea042071..ea8c819ec 100644 --- a/tests/lib/path.py +++ b/tests/lib/path.py @@ -1,12 +1,7 @@ -# flake8: noqa # Author: Aziz Köksal import glob import os - -try: - from os import supports_fd -except ImportError: - supports_fd = set() +from typing import Iterable, Iterator, Union class Path(str): @@ -20,12 +15,12 @@ class Path(str): # Separator in the PATH environment variable. pathsep = os.pathsep - def __new__(cls, *paths): + def __new__(cls, *paths: str) -> "Path": if len(paths): return super().__new__(cls, os.path.join(*paths)) return super().__new__(cls) - def __div__(self, path): + def __div__(self, path: str) -> "Path": """ Joins this path with another path. @@ -36,7 +31,7 @@ class Path(str): __truediv__ = __div__ - def __rdiv__(self, path): + def __rdiv__(self, path: str) -> "Path": """ Joins this path with another path. @@ -46,7 +41,7 @@ class Path(str): __rtruediv__ = __rdiv__ - def __idiv__(self, path): + def __idiv__(self, path: str) -> "Path": """ Like __div__ but also assigns to the variable. @@ -56,52 +51,52 @@ class Path(str): __itruediv__ = __idiv__ - def __add__(self, path): + def __add__(self, path: str) -> "Path": """ >>> Path('/home/a') + 'bc.d' '/home/abc.d' """ return Path(str(self) + path) - def __radd__(self, path): + def __radd__(self, path: str) -> "Path": """ >>> '/home/a' + Path('bc.d') '/home/abc.d' """ return Path(path + str(self)) - def __repr__(self): + def __repr__(self) -> str: return "Path({inner})".format(inner=str.__repr__(self)) @property - def name(self): + def name(self) -> str: """ '/home/a/bc.d' -> 'bc.d' """ return os.path.basename(self) @property - def stem(self): + def stem(self) -> str: """ '/home/a/bc.d' -> 'bc' """ return Path(os.path.splitext(self)[0]).name @property - def suffix(self): + def suffix(self) -> str: """ '/home/a/bc.d' -> '.d' """ return Path(os.path.splitext(self)[1]) - def resolve(self): + def resolve(self) -> "Path": """ Resolves symbolic links. """ return Path(os.path.realpath(self)) @property - def parent(self): + def parent(self) -> "Path": """ Returns the parent directory of this path. @@ -111,13 +106,18 @@ class Path(str): """ return Path(os.path.dirname(self)) - def exists(self): + def exists(self) -> bool: """ Returns True if the path exists. """ 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. @@ -131,32 +131,32 @@ class Path(str): if not exist_ok or not os.path.isdir(self): raise - def unlink(self): + def unlink(self) -> None: """ Removes a file. """ - return os.remove(self) + os.remove(self) - def rmdir(self): + def rmdir(self) -> None: """ 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. """ - 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))) - def joinpath(self, *parts): + def joinpath(self, *parts: str) -> "Path": return Path(self, *parts) # 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.") def read_bytes(self) -> bytes: @@ -167,23 +167,23 @@ class Path(str): with open(self, "wb") as f: f.write(content) - def read_text(self): + def read_text(self) -> str: with open(self, "r") as fp: return fp.read() - def write_text(self, content): + def write_text(self, content: str) -> None: with open(self, "w") as fp: fp.write(content) - def touch(self): + def touch(self) -> None: with open(self, "a") as fp: - path = fp.fileno() if os.utime in supports_fd else self - os.utime(path, None) # times is not optional on Python 2.7 + path: Union[int, str] = fp.fileno() if os.utime in os.supports_fd else self + os.utime(path) - def symlink_to(self, target): + def symlink_to(self, target: str) -> None: os.symlink(target, self) - def stat(self): + def stat(self) -> os.stat_result: return os.stat(self) diff --git a/tests/lib/venv.py b/tests/lib/venv.py index e297d6462..8f5465ed8 100644 --- a/tests/lib/venv.py +++ b/tests/lib/venv.py @@ -4,11 +4,16 @@ import subprocess import sys import textwrap import venv as _venv +from typing import TYPE_CHECKING, Optional import virtualenv as _virtualenv from .path import Path +if TYPE_CHECKING: + # Literal was introduced in Python 3.8. + from typing import Literal + class VirtualEnvironment: """ @@ -16,18 +21,28 @@ class VirtualEnvironment: virtualenv but in the future it could use pyvenv. """ - def __init__(self, location, template=None, venv_type=None): - assert template is None or venv_type is None - assert venv_type in (None, "virtualenv", "venv") + def __init__( + self, + location: str, + template: Optional["VirtualEnvironment"] = None, + venv_type: 'Literal[None, "virtualenv", "venv"]' = None, + ): 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._template = template - self._sitecustomize = None + self._sitecustomize: Optional[str] = None self._update_paths() self._create() - def _update_paths(self): + def _update_paths(self) -> None: home, lib, inc, bin = _virtualenv.path_locations(self.location) self.bin = Path(bin) self.site = Path(lib) / "site-packages" @@ -38,10 +53,10 @@ class VirtualEnvironment: else: self.lib = Path(lib) - def __repr__(self): + def __repr__(self) -> str: return f"<VirtualEnvironment {self.location}>" - def _create(self, clear=False): + def _create(self, clear: bool = False) -> None: if clear: shutil.rmtree(self.location) if self._template: @@ -77,7 +92,7 @@ class VirtualEnvironment: self.sitecustomize = self._sitecustomize 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. site_py = self.lib / "site.py" with open(site_py) as fp: @@ -111,7 +126,7 @@ class VirtualEnvironment: # Make sure bytecode is up-to-date too. assert compileall.compile_file(str(site_py), quiet=1, force=True) - def _customize_site(self): + def _customize_site(self) -> None: contents = "" if self._venv_type == "venv": # Enable user site (before system). @@ -149,29 +164,29 @@ class VirtualEnvironment: # Make sure bytecode is up-to-date too. assert compileall.compile_file(str(sitecustomize), quiet=1, force=True) - def clear(self): + def clear(self) -> None: self._create(clear=True) - def move(self, location): + def move(self, location: str) -> None: shutil.move(self.location, location) self.location = Path(location) self._update_paths() @property - def sitecustomize(self): + def sitecustomize(self) -> Optional[str]: return self._sitecustomize @sitecustomize.setter - def sitecustomize(self, value): + def sitecustomize(self, value: str) -> None: self._sitecustomize = value self._customize_site() @property - def user_site_packages(self): + def user_site_packages(self) -> bool: return self._user_site_packages @user_site_packages.setter - def user_site_packages(self, value): + def user_site_packages(self, value: bool) -> None: self._user_site_packages = value if self._venv_type == "virtualenv": marker = self.lib / "no-global-site-packages.txt" |