diff --git a/news/c543db45-b1ba-44c9-92b6-6e99e2cf75d8.trivial.rst b/news/c543db45-b1ba-44c9-92b6-6e99e2cf75d8.trivial.rst
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/setup.cfg b/setup.cfg
index 6a3e8c7f5da..d333089c5f8 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -51,11 +51,7 @@ follow_imports = skip
[mypy-pip._vendor.requests.*]
follow_imports = skip
-# TODO: The following options should be removed at some point in the future.
-[mypy-tests.conftest]
-allow_untyped_defs = True
-[mypy-tests.lib.*]
-allow_untyped_defs = True
+# TODO: The following option should be removed at some point in the future.
[mypy-tests.functional.*]
allow_untyped_defs = True
diff --git a/tests/conftest.py b/tests/conftest.py
index 390726d149c..076aeaf1983 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -8,10 +8,19 @@
import sys
import time
from contextlib import ExitStack, contextmanager
-from typing import TYPE_CHECKING, Dict, Iterable, List
+from typing import TYPE_CHECKING, Callable, Dict, Iterable, Iterator, List, Optional
from unittest.mock import patch
+import py.path
import pytest
+
+# Config will be available from the public API in pytest >= 7.0.0:
+# https://github.com/pytest-dev/pytest/commit/88d84a57916b592b070f4201dc84f0286d1f9fef
+from _pytest.config import Config
+
+# Parser will be available from the public API in pytest >= 7.0.0:
+# https://github.com/pytest-dev/pytest/commit/538b5c24999e9ebb4fab43faabc8bcc28737bcdf
+from _pytest.config.argparsing import Parser
from setuptools.wheel import Wheel
from pip._internal.cli.main import main as pip_entry_point
@@ -22,7 +31,7 @@
from tests.lib.path import Path
from tests.lib.server import MockServer as _MockServer
from tests.lib.server import make_mock_server, server_running
-from tests.lib.venv import VirtualEnvironment
+from tests.lib.venv import VirtualEnvironment, VirtualEnvironmentType
from .lib.compat import nullcontext
@@ -30,7 +39,7 @@
from wsgi import WSGIApplication
-def pytest_addoption(parser):
+def pytest_addoption(parser: Parser) -> None:
parser.addoption(
"--keep-tmpdir",
action="store_true",
@@ -58,7 +67,7 @@ def pytest_addoption(parser):
)
-def pytest_collection_modifyitems(config, items):
+def pytest_collection_modifyitems(config: Config, items: List[pytest.Item]) -> None:
for item in items:
if not hasattr(item, "module"): # e.g.: DoctestTextfile
continue
@@ -84,9 +93,10 @@ def pytest_collection_modifyitems(config, items):
if item.get_closest_marker("incompatible_with_sysconfig") and _USE_SYSCONFIG:
item.add_marker(pytest.mark.skip("Incompatible with sysconfig"))
+ # "Item" has no attribute "module"
+ module_file = item.module.__file__ # type: ignore[attr-defined]
module_path = os.path.relpath(
- item.module.__file__,
- os.path.commonprefix([__file__, item.module.__file__]),
+ module_file, os.path.commonprefix([__file__, module_file])
)
module_root_dir = module_path.split(os.pathsep)[0]
@@ -103,7 +113,7 @@ def pytest_collection_modifyitems(config, items):
@pytest.fixture(scope="session", autouse=True)
-def resolver_variant(request):
+def resolver_variant(request: pytest.FixtureRequest) -> Iterator[str]:
"""Set environment variable to make pip default to the correct resolver."""
resolver = request.config.getoption("--resolver")
@@ -125,7 +135,9 @@ def resolver_variant(request):
@pytest.fixture(scope="session")
-def tmpdir_factory(request, tmpdir_factory):
+def tmpdir_factory(
+ request: pytest.FixtureRequest, tmpdir_factory: pytest.TempdirFactory
+) -> Iterator[pytest.TempdirFactory]:
"""Modified `tmpdir_factory` session fixture
that will automatically cleanup after itself.
"""
@@ -138,7 +150,7 @@ def tmpdir_factory(request, tmpdir_factory):
@pytest.fixture
-def tmpdir(request, tmpdir):
+def tmpdir(request: pytest.FixtureRequest, tmpdir: py.path.local) -> Iterator[Path]:
"""
Return a temporary directory path object which is unique to each test
function invocation, created as a sub directory of the base temporary
@@ -158,7 +170,7 @@ def tmpdir(request, tmpdir):
@pytest.fixture(autouse=True)
-def isolate(tmpdir, monkeypatch):
+def isolate(tmpdir: Path, monkeypatch: pytest.MonkeyPatch) -> None:
"""
Isolate our tests so that things like global configuration files and the
like do not affect our test results.
@@ -257,7 +269,7 @@ def isolate(tmpdir, monkeypatch):
@pytest.fixture(autouse=True)
-def scoped_global_tempdir_manager(request):
+def scoped_global_tempdir_manager(request: pytest.FixtureRequest) -> Iterator[None]:
"""Make unit tests with globally-managed tempdirs easier
Each test function gets its own individual scope for globally-managed
@@ -273,12 +285,14 @@ def scoped_global_tempdir_manager(request):
@pytest.fixture(scope="session")
-def pip_src(tmpdir_factory):
- def not_code_files_and_folders(path, names):
+def pip_src(tmpdir_factory: pytest.TempdirFactory) -> Path:
+ def not_code_files_and_folders(path: str, names: List[str]) -> Iterable[str]:
# In the root directory...
if path == SRC_DIR:
# ignore all folders except "src"
- folders = {name for name in names if os.path.isdir(path / name)}
+ folders = {
+ name for name in names if os.path.isdir(os.path.join(path, name))
+ }
to_ignore = folders - {"src"}
# and ignore ".git" if present (which may be a file if in a linked
# worktree).
@@ -302,7 +316,9 @@ def not_code_files_and_folders(path, names):
return pip_src
-def _common_wheel_editable_install(tmpdir_factory, common_wheels, package):
+def _common_wheel_editable_install(
+ tmpdir_factory: pytest.TempdirFactory, common_wheels: Path, package: str
+) -> Path:
wheel_candidates = list(common_wheels.glob(f"{package}-*.whl"))
assert len(wheel_candidates) == 1, wheel_candidates
install_dir = Path(str(tmpdir_factory.mktemp(package))) / "install"
@@ -313,21 +329,27 @@ def _common_wheel_editable_install(tmpdir_factory, common_wheels, package):
@pytest.fixture(scope="session")
-def setuptools_install(tmpdir_factory, common_wheels):
+def setuptools_install(
+ tmpdir_factory: pytest.TempdirFactory, common_wheels: Path
+) -> Path:
return _common_wheel_editable_install(tmpdir_factory, common_wheels, "setuptools")
@pytest.fixture(scope="session")
-def wheel_install(tmpdir_factory, common_wheels):
+def wheel_install(tmpdir_factory: pytest.TempdirFactory, common_wheels: Path) -> Path:
return _common_wheel_editable_install(tmpdir_factory, common_wheels, "wheel")
@pytest.fixture(scope="session")
-def coverage_install(tmpdir_factory, common_wheels):
+def coverage_install(
+ tmpdir_factory: pytest.TempdirFactory, common_wheels: Path
+) -> Path:
return _common_wheel_editable_install(tmpdir_factory, common_wheels, "coverage")
-def install_egg_link(venv, project_name, egg_info_dir):
+def install_egg_link(
+ venv: VirtualEnvironment, project_name: str, egg_info_dir: Path
+) -> None:
with open(venv.site / "easy-install.pth", "a") as fp:
fp.write(str(egg_info_dir.resolve()) + "\n")
with open(venv.site / (project_name + ".egg-link"), "w") as fp:
@@ -336,9 +358,14 @@ def install_egg_link(venv, project_name, egg_info_dir):
@pytest.fixture(scope="session")
def virtualenv_template(
- request, tmpdir_factory, pip_src, setuptools_install, coverage_install
-):
-
+ request: pytest.FixtureRequest,
+ tmpdir_factory: pytest.TempdirFactory,
+ pip_src: Path,
+ setuptools_install: Path,
+ coverage_install: Path,
+) -> Iterator[VirtualEnvironment]:
+
+ venv_type: VirtualEnvironmentType
if request.config.getoption("--use-venv"):
venv_type = "venv"
else:
@@ -388,15 +415,19 @@ def virtualenv_template(
@pytest.fixture(scope="session")
-def virtualenv_factory(virtualenv_template):
- def factory(tmpdir):
+def virtualenv_factory(
+ virtualenv_template: VirtualEnvironment,
+) -> Callable[[Path], VirtualEnvironment]:
+ def factory(tmpdir: Path) -> VirtualEnvironment:
return VirtualEnvironment(tmpdir, virtualenv_template)
return factory
@pytest.fixture
-def virtualenv(virtualenv_factory, tmpdir):
+def virtualenv(
+ virtualenv_factory: Callable[[Path], VirtualEnvironment], tmpdir: Path
+) -> Iterator[VirtualEnvironment]:
"""
Return a virtual environment which is unique to each test function
invocation created inside of a sub directory of the test function's
@@ -407,13 +438,17 @@ def virtualenv(virtualenv_factory, tmpdir):
@pytest.fixture
-def with_wheel(virtualenv, wheel_install):
+def with_wheel(virtualenv: VirtualEnvironment, wheel_install: Path) -> None:
install_egg_link(virtualenv, "wheel", wheel_install)
@pytest.fixture(scope="session")
-def script_factory(virtualenv_factory, deprecated_python):
- def factory(tmpdir, virtualenv=None):
+def script_factory(
+ virtualenv_factory: Callable[[Path], VirtualEnvironment], deprecated_python: bool
+) -> Callable[[Path, Optional[VirtualEnvironment]], PipTestEnvironment]:
+ def factory(
+ tmpdir: Path, virtualenv: Optional[VirtualEnvironment] = None
+ ) -> PipTestEnvironment:
if virtualenv is None:
virtualenv = virtualenv_factory(tmpdir.joinpath("venv"))
return PipTestEnvironment(
@@ -437,7 +472,11 @@ def factory(tmpdir, virtualenv=None):
@pytest.fixture
-def script(tmpdir, virtualenv, script_factory):
+def script(
+ tmpdir: Path,
+ virtualenv: VirtualEnvironment,
+ script_factory: Callable[[Path, Optional[VirtualEnvironment]], PipTestEnvironment],
+) -> PipTestEnvironment:
"""
Return a PipTestEnvironment which is unique to each test function and
will execute all commands inside of the unique virtual environment for this
@@ -448,29 +487,29 @@ def script(tmpdir, virtualenv, script_factory):
@pytest.fixture(scope="session")
-def common_wheels():
+def common_wheels() -> Path:
"""Provide a directory with latest setuptools and wheel wheels"""
return DATA_DIR.joinpath("common_wheels")
@pytest.fixture(scope="session")
-def shared_data(tmpdir_factory):
+def shared_data(tmpdir_factory: pytest.TempdirFactory) -> TestData:
return TestData.copy(Path(str(tmpdir_factory.mktemp("data"))))
@pytest.fixture
-def data(tmpdir):
+def data(tmpdir: Path) -> TestData:
return TestData.copy(tmpdir.joinpath("data"))
class InMemoryPipResult:
- def __init__(self, returncode, stdout):
+ def __init__(self, returncode: int, stdout: str) -> None:
self.returncode = returncode
self.stdout = stdout
class InMemoryPip:
- def pip(self, *args):
+ def pip(self, *args: str) -> InMemoryPipResult:
orig_stdout = sys.stdout
stdout = io.StringIO()
sys.stdout = stdout
@@ -484,18 +523,18 @@ def pip(self, *args):
@pytest.fixture
-def in_memory_pip():
+def in_memory_pip() -> InMemoryPip:
return InMemoryPip()
@pytest.fixture(scope="session")
-def deprecated_python():
+def deprecated_python() -> bool:
"""Used to indicate whether pip deprecated this Python version"""
return sys.version_info[:2] in []
@pytest.fixture(scope="session")
-def cert_factory(tmpdir_factory):
+def cert_factory(tmpdir_factory: pytest.TempdirFactory) -> Callable[[], str]:
def factory() -> str:
"""Returns path to cert/key file."""
output_path = Path(str(tmpdir_factory.mktemp("certs"))) / "cert.pem"
@@ -517,11 +556,11 @@ def __init__(self, server: _MockServer) -> None:
self.context = ExitStack()
@property
- def port(self):
+ def port(self) -> int:
return self._server.port
@property
- def host(self):
+ def host(self) -> str:
return self._server.host
def set_responses(self, responses: Iterable["WSGIApplication"]) -> None:
@@ -534,7 +573,7 @@ def start(self) -> None:
self.context.enter_context(self._set_running())
@contextmanager
- def _set_running(self):
+ def _set_running(self) -> Iterator[None]:
self._running = True
try:
yield
@@ -554,7 +593,7 @@ def get_requests(self) -> List[Dict[str, str]]:
@pytest.fixture
-def mock_server():
+def mock_server() -> Iterator[MockServer]:
server = make_mock_server()
test_server = MockServer(server)
with test_server.context:
@@ -562,7 +601,7 @@ def mock_server():
@pytest.fixture
-def utc():
+def utc() -> Iterator[None]:
# time.tzset() is not implemented on some platforms, e.g. Windows.
tzset = getattr(time, "tzset", lambda: None)
with patch.dict(os.environ, {"TZ": "UTC"}):
diff --git a/tests/lib/__init__.py b/tests/lib/__init__.py
index 3916272bc66..dde1f3d6939 100644
--- a/tests/lib/__init__.py
+++ b/tests/lib/__init__.py
@@ -11,12 +11,12 @@
from hashlib import sha256
from io import BytesIO
from textwrap import dedent
-from typing import List, Optional
+from typing import Any, Callable, Dict, Iterator, List, Optional, Tuple, Union, cast
from zipfile import ZipFile
import pytest
from pip._vendor.packaging.utils import canonicalize_name
-from scripttest import FoundDir, TestFileEnvironment
+from scripttest import FoundDir, FoundFile, ProcResult, TestFileEnvironment
from pip._internal.index.collector import LinkCollector
from pip._internal.index.package_finder import PackageFinder
@@ -27,6 +27,7 @@
from pip._internal.network.session import PipSession
from pip._internal.utils.deprecation import DEPRECATION_MSG_PREFIX
from tests.lib.path import Path, curdir
+from tests.lib.venv import VirtualEnvironment
from tests.lib.wheel import make_wheel
DATA_DIR = Path(__file__).parent.parent.joinpath("data").resolve()
@@ -36,12 +37,15 @@
CURRENT_PY_VERSION_INFO = sys.version_info[:3]
+_Test = Callable[..., None]
+_FilesState = Dict[str, Union[FoundDir, FoundFile]]
-def assert_paths_equal(actual, expected):
+
+def assert_paths_equal(actual: str, expected: str) -> None:
assert os.path.normpath(actual) == os.path.normpath(expected)
-def path_to_url(path):
+def path_to_url(path: str) -> str:
"""
Convert a path to URI. The path will be made absolute and
will not have quoted path parts.
@@ -58,7 +62,7 @@ def path_to_url(path):
return "file://" + url
-def _test_path_to_file_url(path):
+def _test_path_to_file_url(path: Path) -> str:
"""
Convert a test Path to a "file://" URL.
@@ -68,7 +72,7 @@ def _test_path_to_file_url(path):
return "file://" + path.resolve().replace("\\", "/")
-def create_file(path, contents=None):
+def create_file(path: str, contents: Optional[str] = None) -> None:
"""Create a file on the path, with the given contents"""
from pip._internal.utils.misc import ensure_dir
@@ -83,7 +87,7 @@ def create_file(path, contents=None):
def make_test_search_scope(
find_links: Optional[List[str]] = None,
index_urls: Optional[List[str]] = None,
-):
+) -> SearchScope:
if find_links is None:
find_links = []
if index_urls is None:
@@ -152,17 +156,17 @@ class TestData:
__test__ = False
- def __init__(self, root, source=None):
+ def __init__(self, root: str, source: Optional[Path] = None) -> None:
self.source = source or DATA_DIR
self.root = Path(root).resolve()
@classmethod
- def copy(cls, root):
+ def copy(cls, root: str) -> "TestData":
obj = cls(root)
obj.reset()
return obj
- def reset(self):
+ def reset(self) -> None:
# Check explicitly for the target directory to avoid overly-broad
# try/except.
if self.root.exists():
@@ -170,50 +174,50 @@ def reset(self):
shutil.copytree(self.source, self.root, symlinks=True)
@property
- def packages(self):
+ def packages(self) -> Path:
return self.root.joinpath("packages")
@property
- def packages2(self):
+ def packages2(self) -> Path:
return self.root.joinpath("packages2")
@property
- def packages3(self):
+ def packages3(self) -> Path:
return self.root.joinpath("packages3")
@property
- def src(self):
+ def src(self) -> Path:
return self.root.joinpath("src")
@property
- def indexes(self):
+ def indexes(self) -> Path:
return self.root.joinpath("indexes")
@property
- def reqfiles(self):
+ def reqfiles(self) -> Path:
return self.root.joinpath("reqfiles")
@property
- def completion_paths(self):
+ def completion_paths(self) -> Path:
return self.root.joinpath("completion_paths")
@property
- def find_links(self):
+ def find_links(self) -> str:
return path_to_url(self.packages)
@property
- def find_links2(self):
+ def find_links2(self) -> str:
return path_to_url(self.packages2)
@property
- def find_links3(self):
+ def find_links3(self) -> str:
return path_to_url(self.packages3)
@property
- def backends(self):
+ def backends(self) -> str:
return path_to_url(self.root.joinpath("backends"))
- def index_url(self, index="simple"):
+ def index_url(self, index: str = "simple") -> str:
return path_to_url(self.root.joinpath("indexes", index))
@@ -226,7 +230,7 @@ class TestFailure(AssertionError):
class TestPipResult:
- def __init__(self, impl, verbose=False):
+ def __init__(self, impl: ProcResult, verbose: bool = False) -> None:
self._impl = impl
if verbose:
@@ -236,7 +240,7 @@ def __init__(self, impl, verbose=False):
print(self.stderr)
print("=======================")
- def __getattr__(self, attr):
+ def __getattr__(self, attr: str) -> Any:
return getattr(self._impl, attr)
if sys.platform == "win32":
@@ -255,19 +259,19 @@ def __str__(self):
else:
# Python doesn't automatically forward __str__ through __getattr__
- def __str__(self):
+ def __str__(self) -> str:
return str(self._impl)
def assert_installed(
self,
- pkg_name,
- editable=True,
- with_files=None,
- without_files=None,
- without_egg_link=False,
- use_user_site=False,
- sub_dir=False,
- ):
+ pkg_name: str,
+ editable: bool = True,
+ with_files: Optional[List[Path]] = None,
+ without_files: Optional[List[Path]] = None,
+ without_egg_link: bool = False,
+ use_user_site: bool = False,
+ sub_dir: bool = False,
+ ) -> None:
with_files = with_files or []
without_files = without_files or []
e = self.test_env
@@ -354,20 +358,20 @@ def assert_installed(
f"Package directory {pkg_dir!r} has unexpected content {f}"
)
- def did_create(self, path, message=None):
+ def did_create(self, path: Path, message: Optional[str] = None) -> None:
assert str(path) in self.files_created, _one_or_both(message, self)
- def did_not_create(self, path, message=None):
+ def did_not_create(self, path: Path, message: Optional[str] = None) -> None:
assert str(path) not in self.files_created, _one_or_both(message, self)
- def did_update(self, path, message=None):
+ def did_update(self, path: Path, message: Optional[str] = None) -> None:
assert str(path) in self.files_updated, _one_or_both(message, self)
- def did_not_update(self, path, message=None):
+ def did_not_update(self, path: Path, message: Optional[str] = None) -> None:
assert str(path) not in self.files_updated, _one_or_both(message, self)
-def _one_or_both(a, b):
+def _one_or_both(a: Optional[str], b: Any) -> str:
"""Returns f"{a}\n{b}" if a is truthy, else returns str(b)."""
if not a:
return str(b)
@@ -375,7 +379,7 @@ def _one_or_both(a, b):
return f"{a}\n{b}"
-def make_check_stderr_message(stderr, line, reason):
+def make_check_stderr_message(stderr: str, line: str, reason: str) -> str:
"""
Create an exception message to use inside check_stderr().
"""
@@ -389,10 +393,10 @@ def make_check_stderr_message(stderr, line, reason):
def _check_stderr(
- stderr,
- allow_stderr_warning,
- allow_stderr_error,
-):
+ stderr: str,
+ allow_stderr_warning: bool,
+ allow_stderr_error: bool,
+) -> None:
"""
Check the given stderr for logged warnings and errors.
@@ -457,7 +461,14 @@ class PipTestEnvironment(TestFileEnvironment):
exe = sys.platform == "win32" and ".exe" or ""
verbose = False
- def __init__(self, base_path, *args, virtualenv, pip_expect_warning=None, **kwargs):
+ def __init__(
+ self,
+ base_path: str,
+ *args: Any,
+ virtualenv: VirtualEnvironment,
+ pip_expect_warning: bool = False,
+ **kwargs: Any,
+ ) -> None:
# Make our base_path a test.lib.path.Path object
base_path = Path(base_path)
@@ -467,6 +478,9 @@ def __init__(self, base_path, *args, virtualenv, pip_expect_warning=None, **kwar
self.site_packages_path = virtualenv.site
self.bin_path = virtualenv.bin
+ assert site.USER_BASE is not None
+ assert site.USER_SITE is not None
+
self.user_base_path = self.venv_path.joinpath("user")
self.user_site_path = self.venv_path.joinpath(
"user",
@@ -524,7 +538,7 @@ def __init__(self, base_path, *args, virtualenv, pip_expect_warning=None, **kwar
setattr(self, name, relative_path)
# Make sure temp_path is a Path object
- self.temp_path = Path(self.temp_path)
+ self.temp_path: Path = Path(self.temp_path)
# Ensure the tmp dir exists, things break horribly if it doesn't
self.temp_path.mkdir()
@@ -533,14 +547,14 @@ def __init__(self, base_path, *args, virtualenv, pip_expect_warning=None, **kwar
self.user_site_path.mkdir(parents=True)
self.user_site_path.joinpath("easy-install.pth").touch()
- def _ignore_file(self, fn):
+ def _ignore_file(self, fn: str) -> bool:
if fn.endswith("__pycache__") or fn.endswith(".pyc"):
result = True
else:
result = super()._ignore_file(fn)
return result
- def _find_traverse(self, path, result):
+ def _find_traverse(self, path: str, result: Dict[str, FoundDir]) -> None:
# Ignore symlinked directories to avoid duplicates in `run()`
# results because of venv `lib64 -> lib/` symlink on Linux.
full = os.path.join(self.base_path, path)
@@ -552,13 +566,13 @@ def _find_traverse(self, path, result):
def run(
self,
- *args,
- cwd=None,
- allow_stderr_error=None,
- allow_stderr_warning=None,
- allow_error=None,
- **kw,
- ):
+ *args: str,
+ cwd: Optional[str] = None,
+ allow_stderr_error: Optional[bool] = None,
+ allow_stderr_warning: Optional[bool] = None,
+ allow_error: bool = False,
+ **kw: Any,
+ ) -> TestPipResult:
"""
:param allow_stderr_error: whether a logged error is allowed in
stderr. Passing True for this argument implies
@@ -638,7 +652,7 @@ def run(
return TestPipResult(result, verbose=self.verbose)
- def pip(self, *args, use_module=True, **kwargs):
+ def pip(self, *args: str, use_module: bool = True, **kwargs: Any) -> TestPipResult:
__tracebackhide__ = True
if self.pip_expect_warning:
kwargs["allow_stderr_warning"] = True
@@ -649,7 +663,7 @@ def pip(self, *args, use_module=True, **kwargs):
exe = "pip"
return self.run(exe, *args, **kwargs)
- def pip_install_local(self, *args, **kwargs):
+ def pip_install_local(self, *args: str, **kwargs: Any) -> TestPipResult:
return self.pip(
"install",
"--no-index",
@@ -659,11 +673,11 @@ def pip_install_local(self, *args, **kwargs):
**kwargs,
)
- def easy_install(self, *args, **kwargs):
+ def easy_install(self, *args: str, **kwargs: Any) -> TestPipResult:
args = ("-m", "easy_install") + args
return self.run("python", *args, **kwargs)
- def assert_installed(self, **kwargs):
+ def assert_installed(self, **kwargs: str) -> None:
ret = self.pip("list", "--format=json")
installed = set(
(canonicalize_name(val["name"]), val["version"])
@@ -672,7 +686,7 @@ def assert_installed(self, **kwargs):
expected = set((canonicalize_name(k), v) for k, v in kwargs.items())
assert expected <= installed, "{!r} not all in {!r}".format(expected, installed)
- def assert_not_installed(self, *args):
+ def assert_not_installed(self, *args: str) -> None:
ret = self.pip("list", "--format=json")
installed = set(
canonicalize_name(val["name"]) for val in json.loads(ret.stdout)
@@ -688,7 +702,9 @@ def assert_not_installed(self, *args):
# FIXME ScriptTest does something similar, but only within a single
# ProcResult; this generalizes it so states can be compared across
# multiple commands. Maybe should be rolled into ScriptTest?
-def diff_states(start, end, ignore=None):
+def diff_states(
+ start: _FilesState, end: _FilesState, ignore: Optional[List[str]] = None
+) -> Dict[str, _FilesState]:
"""
Differences two "filesystem states" as represented by dictionaries
of FoundFile and FoundDir objects.
@@ -714,7 +730,7 @@ def diff_states(start, end, ignore=None):
"""
ignore = ignore or []
- def prefix_match(path, prefix):
+ def prefix_match(path: str, prefix: str) -> bool:
if path == prefix:
return True
prefix = prefix.rstrip(os.path.sep) + os.path.sep
@@ -733,7 +749,11 @@ def prefix_match(path, prefix):
return dict(deleted=deleted, created=created, updated=updated)
-def assert_all_changes(start_state, end_state, expected_changes):
+def assert_all_changes(
+ start_state: Union[_FilesState, TestPipResult],
+ end_state: Union[_FilesState, TestPipResult],
+ expected_changes: List[str],
+) -> Dict[str, _FilesState]:
"""
Fails if anything changed that isn't listed in the
expected_changes.
@@ -754,6 +774,8 @@ def assert_all_changes(start_state, end_state, expected_changes):
start_files = start_state.files_before
if isinstance(end_state, TestPipResult):
end_files = end_state.files_after
+ start_files = cast(_FilesState, start_files)
+ end_files = cast(_FilesState, end_files)
diff = diff_states(start_files, end_files, ignore=expected_changes)
if list(diff.values()) != [{}, {}, {}]:
@@ -766,7 +788,9 @@ def assert_all_changes(start_state, end_state, expected_changes):
return diff
-def _create_main_file(dir_path, name=None, output=None):
+def _create_main_file(
+ dir_path: Path, name: Optional[str] = None, output: Optional[str] = None
+) -> None:
"""
Create a module with a main() function that prints the given output.
"""
@@ -785,12 +809,12 @@ def main():
def _git_commit(
- env_or_script,
- repo_dir,
- message=None,
- allow_empty=False,
- stage_modified=False,
-):
+ env_or_script: PipTestEnvironment,
+ repo_dir: str,
+ message: Optional[str] = None,
+ allow_empty: bool = False,
+ stage_modified: bool = False,
+) -> None:
"""
Run git-commit.
@@ -822,7 +846,9 @@ def _git_commit(
env_or_script.run(*new_args, cwd=repo_dir)
-def _vcs_add(script, version_pkg_path, vcs="git"):
+def _vcs_add(
+ script: PipTestEnvironment, version_pkg_path: str, vcs: str = "git"
+) -> str:
if vcs == "git":
script.run("git", "init", cwd=version_pkg_path)
script.run("git", "add", ".", cwd=version_pkg_path)
@@ -845,7 +871,7 @@ def _vcs_add(script, version_pkg_path, vcs="git"):
script.run(
"svn", "checkout", repo_url, "pip-test-package", cwd=script.scratch_path
)
- checkout_path = script.scratch_path / "pip-test-package"
+ checkout_path: str = script.scratch_path / "pip-test-package"
# svn internally stores windows drives as uppercase; we'll match that.
checkout_path = checkout_path.replace("c:", "C:")
@@ -872,7 +898,9 @@ def _vcs_add(script, version_pkg_path, vcs="git"):
return version_pkg_path
-def _create_test_package_with_subdirectory(script, subdirectory):
+def _create_test_package_with_subdirectory(
+ script: PipTestEnvironment, subdirectory: str
+) -> Path:
script.scratch_path.joinpath("version_pkg").mkdir()
version_pkg_path = script.scratch_path / "version_pkg"
_create_main_file(version_pkg_path, name="version_pkg", output="0.1")
@@ -919,7 +947,9 @@ def _create_test_package_with_subdirectory(script, subdirectory):
return version_pkg_path
-def _create_test_package_with_srcdir(script, name="version_pkg", vcs="git"):
+def _create_test_package_with_srcdir(
+ script: PipTestEnvironment, name: str = "version_pkg", vcs: str = "git"
+) -> str:
script.scratch_path.joinpath(name).mkdir()
version_pkg_path = script.scratch_path / name
subdir_path = version_pkg_path.joinpath("subdir")
@@ -947,7 +977,9 @@ def _create_test_package_with_srcdir(script, name="version_pkg", vcs="git"):
return _vcs_add(script, version_pkg_path, vcs)
-def _create_test_package(script, name="version_pkg", vcs="git"):
+def _create_test_package(
+ script: PipTestEnvironment, name: str = "version_pkg", vcs: str = "git"
+) -> str:
script.scratch_path.joinpath(name).mkdir()
version_pkg_path = script.scratch_path / name
_create_main_file(version_pkg_path, name=name, output="0.1")
@@ -970,7 +1002,7 @@ def _create_test_package(script, name="version_pkg", vcs="git"):
return _vcs_add(script, version_pkg_path, vcs)
-def _create_svn_repo(script, version_pkg_path):
+def _create_svn_repo(script: PipTestEnvironment, version_pkg_path: str) -> str:
repo_url = path_to_url(script.scratch_path / "pip-test-package-repo" / "trunk")
script.run("svnadmin", "create", "pip-test-package-repo", cwd=script.scratch_path)
script.run(
@@ -985,7 +1017,9 @@ def _create_svn_repo(script, version_pkg_path):
return repo_url
-def _change_test_package_version(script, version_pkg_path):
+def _change_test_package_version(
+ script: PipTestEnvironment, version_pkg_path: Path
+) -> None:
_create_main_file(
version_pkg_path, name="version_pkg", output="some different version"
)
@@ -994,7 +1028,7 @@ def _change_test_package_version(script, version_pkg_path):
@contextmanager
-def requirements_file(contents, tmpdir):
+def requirements_file(contents: str, tmpdir: Path) -> Iterator[Path]:
"""Return a Path to a requirements file of given contents.
As long as the context manager is open, the requirements file will exist.
@@ -1008,7 +1042,9 @@ def requirements_file(contents, tmpdir):
path.unlink()
-def create_test_package_with_setup(script, **setup_kwargs):
+def create_test_package_with_setup(
+ script: PipTestEnvironment, **setup_kwargs: Any
+) -> Path:
assert "name" in setup_kwargs, setup_kwargs
pkg_path = script.scratch_path / setup_kwargs["name"]
pkg_path.mkdir()
@@ -1029,10 +1065,10 @@ def urlsafe_b64encode_nopad(data: bytes) -> str:
def create_really_basic_wheel(name: str, version: str) -> bytes:
- def digest(contents):
+ def digest(contents: bytes) -> str:
return "sha256={}".format(urlsafe_b64encode_nopad(sha256(contents).digest()))
- def add_file(path, text):
+ def add_file(path: str, text: str) -> None:
contents = text.encode("utf-8")
z.writestr(path, contents)
records.append((path, digest(contents), str(len(contents))))
@@ -1061,14 +1097,14 @@ def add_file(path, text):
def create_basic_wheel_for_package(
- script,
- name,
- version,
- depends=None,
- extras=None,
- requires_python=None,
- extra_files=None,
-):
+ script: PipTestEnvironment,
+ name: str,
+ version: str,
+ depends: Optional[List[str]] = None,
+ extras: Dict[str, str] = None,
+ requires_python: Optional[str] = None,
+ extra_files: Optional[Dict[str, str]] = None,
+) -> Path:
if depends is None:
depends = []
if extras is None:
@@ -1098,7 +1134,7 @@ def hello():
for package in packages
]
- metadata_updates = {
+ metadata_updates: Dict[str, Any] = {
"Provides-Extra": list(extras),
"Requires-Dist": requires_dist,
}
@@ -1120,7 +1156,12 @@ def hello():
return archive_path
-def create_basic_sdist_for_package(script, name, version, extra_files=None):
+def create_basic_sdist_for_package(
+ script: PipTestEnvironment,
+ name: str,
+ version: str,
+ extra_files: Optional[Dict[str, str]] = None,
+) -> Path:
files = {
"setup.py": """
from setuptools import find_packages, setup
@@ -1161,8 +1202,8 @@ def create_basic_sdist_for_package(script, name, version, extra_files=None):
return retval
-def need_executable(name, check_cmd):
- def wrapper(fn):
+def need_executable(name: str, check_cmd: Tuple[str, ...]) -> Callable[[_Test], _Test]:
+ def wrapper(fn: _Test) -> _Test:
try:
subprocess.check_output(check_cmd)
except (OSError, subprocess.CalledProcessError):
@@ -1172,7 +1213,7 @@ def wrapper(fn):
return wrapper
-def is_bzr_installed():
+def is_bzr_installed() -> bool:
try:
subprocess.check_output(("bzr", "version", "--short"))
except OSError:
@@ -1180,7 +1221,7 @@ def is_bzr_installed():
return True
-def is_svn_installed():
+def is_svn_installed() -> bool:
try:
subprocess.check_output(("svn", "--version"))
except OSError:
@@ -1188,11 +1229,11 @@ def is_svn_installed():
return True
-def need_bzr(fn):
+def need_bzr(fn: _Test) -> _Test:
return pytest.mark.bzr(need_executable("Bazaar", ("bzr", "version", "--short"))(fn))
-def need_svn(fn):
+def need_svn(fn: _Test) -> _Test:
return pytest.mark.svn(
need_executable("Subversion", ("svn", "--version"))(
need_executable("Subversion Admin", ("svnadmin", "--version"))(fn)
@@ -1200,5 +1241,5 @@ def need_svn(fn):
)
-def need_mercurial(fn):
+def need_mercurial(fn: _Test) -> _Test:
return pytest.mark.mercurial(need_executable("Mercurial", ("hg", "version"))(fn))
diff --git a/tests/lib/configuration_helpers.py b/tests/lib/configuration_helpers.py
index e315ceaa9ac..67f75e8e7a0 100644
--- a/tests/lib/configuration_helpers.py
+++ b/tests/lib/configuration_helpers.py
@@ -6,34 +6,42 @@
import os
import tempfile
import textwrap
+from typing import Any, Dict, Iterator
import pip._internal.configuration
from pip._internal.utils.misc import ensure_dir
# This is so that tests don't need to import pip._internal.configuration.
+Kind = pip._internal.configuration.Kind
kinds = pip._internal.configuration.kinds
class ConfigurationMixin:
- def setup(self):
+ def setup(self) -> None:
self.configuration = pip._internal.configuration.Configuration(
isolated=False,
)
- def patch_configuration(self, variant, di):
+ def patch_configuration(self, variant: Kind, di: Dict[str, Any]) -> None:
old = self.configuration._load_config_files
@functools.wraps(old)
- def overridden():
+ def overridden() -> None:
# Manual Overload
self.configuration._config[variant].update(di)
- self.configuration._parsers[variant].append((None, None))
- return old()
+ # Configuration._parsers has type:
+ # Dict[Kind, List[Tuple[str, RawConfigParser]]].
+ # As a testing convenience, pass a special value.
+ self.configuration._parsers[variant].append(
+ (None, None), # type: ignore[arg-type]
+ )
+ old()
- self.configuration._load_config_files = overridden
+ # https://github.com/python/mypy/issues/2427
+ self.configuration._load_config_files = overridden # type: ignore[assignment]
@contextlib.contextmanager
- def tmpfile(self, contents):
+ def tmpfile(self, contents: str) -> Iterator[str]:
# Create a temporary file
fd, path = tempfile.mkstemp(prefix="pip_", suffix="_config.ini", text=True)
os.close(fd)
diff --git a/tests/lib/git_submodule_helpers.py b/tests/lib/git_submodule_helpers.py
index 220a926b57a..80afd9474a0 100644
--- a/tests/lib/git_submodule_helpers.py
+++ b/tests/lib/git_submodule_helpers.py
@@ -1,9 +1,11 @@
import textwrap
+from typing import Tuple
-from tests.lib import _create_main_file, _git_commit
+from tests.lib import PipTestEnvironment, _create_main_file, _git_commit
+from tests.lib.path import Path
-def _create_test_package_submodule(env):
+def _create_test_package_submodule(env: PipTestEnvironment) -> Path:
env.scratch_path.joinpath("version_pkg_submodule").mkdir()
submodule_path = env.scratch_path / "version_pkg_submodule"
env.run("touch", "testfile", cwd=submodule_path)
@@ -14,14 +16,18 @@ def _create_test_package_submodule(env):
return submodule_path
-def _change_test_package_submodule(env, submodule_path):
+def _change_test_package_submodule(
+ env: PipTestEnvironment, submodule_path: Path
+) -> None:
submodule_path.joinpath("testfile").write_text("this is a changed file")
submodule_path.joinpath("testfile2").write_text("this is an added file")
env.run("git", "add", ".", cwd=submodule_path)
_git_commit(env, submodule_path, message="submodule change")
-def _pull_in_submodule_changes_to_module(env, module_path, rel_path):
+def _pull_in_submodule_changes_to_module(
+ env: PipTestEnvironment, module_path: Path, rel_path: Path
+) -> None:
"""
Args:
rel_path: the location of the submodule relative to the superproject.
@@ -32,7 +38,9 @@ def _pull_in_submodule_changes_to_module(env, module_path, rel_path):
_git_commit(env, module_path, message="submodule change", stage_modified=True)
-def _create_test_package_with_submodule(env, rel_path):
+def _create_test_package_with_submodule(
+ env: PipTestEnvironment, rel_path: Path
+) -> Tuple[Path, Path]:
"""
Args:
rel_path: the location of the submodule relative to the superproject.
diff --git a/tests/lib/local_repos.py b/tests/lib/local_repos.py
index 81a114fd023..8d11a3fb12e 100644
--- a/tests/lib/local_repos.py
+++ b/tests/lib/local_repos.py
@@ -8,7 +8,7 @@
from tests.lib.path import Path
-def _create_svn_initools_repo(initools_dir):
+def _create_svn_initools_repo(initools_dir: str) -> None:
"""
Create the SVN INITools repo.
"""
@@ -60,5 +60,5 @@ def local_checkout(
return "{}+{}".format(vcs_name, path_to_url(repo_url_path))
-def local_repo(remote_repo, temp_path):
+def local_repo(remote_repo: str, temp_path: Path) -> str:
return local_checkout(remote_repo, temp_path).split("+", 1)[1]
diff --git a/tests/lib/requests_mocks.py b/tests/lib/requests_mocks.py
index 1a77d271049..a70a9b2b048 100644
--- a/tests/lib/requests_mocks.py
+++ b/tests/lib/requests_mocks.py
@@ -2,41 +2,47 @@
"""
from io import BytesIO
+from typing import Any, Callable, Dict, Iterator, List, Optional
+
+_Hook = Callable[["MockResponse"], None]
class FakeStream:
- def __init__(self, contents):
+ def __init__(self, contents: bytes) -> None:
self._io = BytesIO(contents)
- def read(self, size, decode_content=None):
+ def read(self, size: int, decode_content: Optional[bool] = None) -> bytes:
return self._io.read(size)
- def stream(self, size, decode_content=None):
+ def stream(
+ self, size: int, decode_content: Optional[bool] = None
+ ) -> Iterator[bytes]:
yield self._io.read(size)
- def release_conn(self):
+ def release_conn(self) -> None:
pass
class MockResponse:
- def __init__(self, contents):
+ request: "MockRequest"
+ connection: "MockConnection"
+ url: str
+
+ def __init__(self, contents: bytes) -> None:
self.raw = FakeStream(contents)
self.content = contents
- self.request = None
- self.reason = None
+ self.reason = "OK"
self.status_code = 200
- self.connection = None
- self.url = None
- self.headers = {"Content-Length": len(contents)}
- self.history = []
+ self.headers = {"Content-Length": str(len(contents))}
+ self.history: List[MockResponse] = []
self.from_cache = False
class MockConnection:
- def _send(self, req, **kwargs):
+ def _send(self, req: "MockRequest", **kwargs: Any) -> MockResponse:
raise NotImplementedError("_send must be overridden for tests")
- def send(self, req, **kwargs):
+ def send(self, req: "MockRequest", **kwargs: Any) -> MockResponse:
resp = self._send(req, **kwargs)
for cb in req.hooks.get("response", []):
cb(resp)
@@ -44,10 +50,10 @@ def send(self, req, **kwargs):
class MockRequest:
- def __init__(self, url):
+ def __init__(self, url: str) -> None:
self.url = url
- self.headers = {}
- self.hooks = {}
+ self.headers: Dict[str, str] = {}
+ self.hooks: Dict[str, List[_Hook]] = {}
- def register_hook(self, event_name, callback):
+ def register_hook(self, event_name: str, callback: _Hook) -> None:
self.hooks.setdefault(event_name, []).append(callback)
diff --git a/tests/lib/server.py b/tests/lib/server.py
index 24a09a6d659..c1e046a22b7 100644
--- a/tests/lib/server.py
+++ b/tests/lib/server.py
@@ -31,10 +31,11 @@ class MockServer(BaseWSGIServer):
else:
@contextmanager
- def blocked_signals():
+ def blocked_signals() -> Iterator[None]:
"""Block all signals for e.g. starting a worker thread."""
# valid_signals() was added in Python 3.8 (and not using it results
# in a warning on pthread_sigmask() call)
+ mask: Iterable[int]
try:
mask = signal.valid_signals()
except AttributeError:
@@ -48,7 +49,7 @@ def blocked_signals():
class _RequestHandler(WSGIRequestHandler):
- def make_environ(self):
+ def make_environ(self) -> Dict[str, Any]:
environ = super().make_environ()
# From pallets/werkzeug#1469, will probably be in release after
@@ -176,7 +177,7 @@ def html5_page(text: str) -> str:
def index_page(spec: Dict[str, str]) -> "WSGIApplication":
- def link(name, value):
+ def link(name: str, value: str) -> str:
return '{}'.format(value, name)
links = "".join(link(*kv) for kv in spec.items())
@@ -184,7 +185,7 @@ def link(name, value):
def package_page(spec: Dict[str, str]) -> "WSGIApplication":
- def link(name, value):
+ def link(name: str, value: str) -> str:
return '{}'.format(value, name)
links = "".join(link(*kv) for kv in spec.items())
diff --git a/tests/lib/test_lib.py b/tests/lib/test_lib.py
index 0e26389c1d1..118393d03f4 100644
--- a/tests/lib/test_lib.py
+++ b/tests/lib/test_lib.py
@@ -4,14 +4,17 @@
import sys
from contextlib import contextmanager
from os.path import isdir, join
+from typing import Any, Dict, Iterator, Type
import pytest
-from tests.lib import SRC_DIR
+from tests.lib import SRC_DIR, PipTestEnvironment
@contextmanager
-def assert_error_startswith(exc_type, expected_start):
+def assert_error_startswith(
+ exc_type: Type[Exception], expected_start: str
+) -> Iterator[None]:
"""
Assert that an exception is raised starting with a certain message.
"""
@@ -21,7 +24,7 @@ def assert_error_startswith(exc_type, expected_start):
assert str(err.value).startswith(expected_start), f"full message: {err.value}"
-def test_tmp_dir_exists_in_env(script):
+def test_tmp_dir_exists_in_env(script: PipTestEnvironment) -> None:
"""
Test that $TMPDIR == env.temp_path and path exists and env.assert_no_temp()
passes (in fast env)
@@ -33,7 +36,7 @@ def test_tmp_dir_exists_in_env(script):
assert isdir(script.temp_path)
-def test_correct_pip_version(script):
+def test_correct_pip_version(script: PipTestEnvironment) -> None:
"""
Check we are running proper version of pip in run_pip.
"""
@@ -43,11 +46,13 @@ def test_correct_pip_version(script):
# compare the directory tree of the invoked pip with that of this source
# distribution
- pip_folder_outputed = re.match(
+ match = re.match(
r"pip \d+(\.[\d]+)+(\.?(b|rc|dev|pre|post)\d+)? from (.*) "
r"\(python \d+(\.[\d]+)+\)$",
result.stdout,
- ).group(4)
+ )
+ assert match is not None
+ pip_folder_outputed = match.group(4)
pip_folder = join(SRC_DIR, "src", "pip")
diffs = filecmp.dircmp(pip_folder, pip_folder_outputed)
@@ -67,7 +72,7 @@ def test_correct_pip_version(script):
)
-def test_as_import(script):
+def test_as_import(script: PipTestEnvironment) -> None:
"""test that pip.__init__.py does not shadow
the command submodule with a dictionary
"""
@@ -77,7 +82,9 @@ def test_as_import(script):
class TestPipTestEnvironment:
- def run_stderr_with_prefix(self, script, prefix, **kwargs):
+ def run_stderr_with_prefix(
+ self, script: PipTestEnvironment, prefix: str, **kwargs: Any
+ ) -> None:
"""
Call run() that prints stderr with the given prefix.
"""
@@ -86,7 +93,9 @@ def run_stderr_with_prefix(self, script, prefix, **kwargs):
args = [sys.executable, "-c", command]
script.run(*args, **kwargs)
- def run_with_log_command(self, script, sub_string, **kwargs):
+ def run_with_log_command(
+ self, script: PipTestEnvironment, sub_string: str, **kwargs: Any
+ ) -> None:
"""
Call run() on a command that logs a "%"-style format string using
the given substring as the string's replacement field.
@@ -106,14 +115,14 @@ def run_with_log_command(self, script, sub_string, **kwargs):
"FOO",
),
)
- def test_run__allowed_stderr(self, script, prefix):
+ def test_run__allowed_stderr(self, script: PipTestEnvironment, prefix: str) -> None:
"""
Test calling run() with allowed stderr.
"""
# Check that no error happens.
self.run_stderr_with_prefix(script, prefix)
- def test_run__allow_stderr_warning(self, script):
+ def test_run__allow_stderr_warning(self, script: PipTestEnvironment) -> None:
"""
Test passing allow_stderr_warning=True.
"""
@@ -141,7 +150,9 @@ def test_run__allow_stderr_warning(self, script):
"ERROR",
),
)
- def test_run__allow_stderr_error(self, script, prefix):
+ def test_run__allow_stderr_error(
+ self, script: PipTestEnvironment, prefix: str
+ ) -> None:
"""
Test passing allow_stderr_error=True.
"""
@@ -156,14 +167,16 @@ def test_run__allow_stderr_error(self, script, prefix):
("ERROR", "stderr has an unexpected error"),
),
)
- def test_run__unexpected_stderr(self, script, prefix, expected_start):
+ def test_run__unexpected_stderr(
+ self, script: PipTestEnvironment, prefix: str, expected_start: str
+ ) -> None:
"""
Test calling run() with unexpected stderr output.
"""
with assert_error_startswith(RuntimeError, expected_start):
self.run_stderr_with_prefix(script, prefix)
- def test_run__logging_error(self, script):
+ def test_run__logging_error(self, script: PipTestEnvironment) -> None:
"""
Test calling run() with an unexpected logging error.
"""
@@ -183,9 +196,8 @@ def test_run__logging_error(self, script):
)
def test_run__allow_stderr_error_false_error_with_expect_error(
- self,
- script,
- ):
+ self, script: PipTestEnvironment
+ ) -> None:
"""
Test passing allow_stderr_error=False with expect_error=True.
"""
@@ -194,9 +206,8 @@ def test_run__allow_stderr_error_false_error_with_expect_error(
script.run("python", allow_stderr_error=False, expect_error=True)
def test_run__allow_stderr_warning_false_error_with_expect_stderr(
- self,
- script,
- ):
+ self, script: PipTestEnvironment
+ ) -> None:
"""
Test passing allow_stderr_warning=False with expect_stderr=True.
"""
@@ -217,23 +228,29 @@ def test_run__allow_stderr_warning_false_error_with_expect_stderr(
"allow_stderr_error",
),
)
- def test_run__allow_stderr_warning_false_error(self, script, arg_name):
+ def test_run__allow_stderr_warning_false_error(
+ self, script: PipTestEnvironment, arg_name: str
+ ) -> None:
"""
Test passing allow_stderr_warning=False when it is not allowed.
"""
- kwargs = {"allow_stderr_warning": False, arg_name: True}
+ kwargs: Dict[str, Any] = {"allow_stderr_warning": False, arg_name: True}
expected_start = (
"cannot pass allow_stderr_warning=False with allow_stderr_error=True"
)
with assert_error_startswith(RuntimeError, expected_start):
script.run("python", **kwargs)
- def test_run__expect_error_fails_when_zero_returncode(self, script):
+ def test_run__expect_error_fails_when_zero_returncode(
+ self, script: PipTestEnvironment
+ ) -> None:
expected_start = "Script passed unexpectedly"
with assert_error_startswith(AssertionError, expected_start):
script.run("python", expect_error=True)
- def test_run__no_expect_error_fails_when_nonzero_returncode(self, script):
+ def test_run__no_expect_error_fails_when_nonzero_returncode(
+ self, script: PipTestEnvironment
+ ) -> None:
expected_start = "Script returned code: 1"
with assert_error_startswith(AssertionError, expected_start):
script.run("python", "-c", "import sys; sys.exit(1)")
diff --git a/tests/lib/test_wheel.py b/tests/lib/test_wheel.py
index 6173c8c8e1d..09c2ee3e610 100644
--- a/tests/lib/test_wheel.py
+++ b/tests/lib/test_wheel.py
@@ -6,7 +6,9 @@
from functools import partial
from zipfile import ZipFile
+from tests.lib.path import Path
from tests.lib.wheel import (
+ File,
_default,
make_metadata_file,
make_wheel,
@@ -15,12 +17,12 @@
)
-def test_message_from_dict_one_value():
+def test_message_from_dict_one_value() -> None:
message = message_from_dict({"a": "1"})
assert set(message.get_all("a")) == {"1"}
-def test_message_from_dict_multiple_values():
+def test_message_from_dict_multiple_values() -> None:
message = message_from_dict({"a": ["1", "2"]})
assert set(message.get_all("a")) == {"1", "2"}
@@ -39,7 +41,7 @@ def message_from_bytes(contents: bytes) -> Message:
)
-def default_metadata_checks(f):
+def default_metadata_checks(f: File) -> Message:
assert f.name == "simple-0.1.0.dist-info/METADATA"
message = message_from_bytes(f.contents)
assert message.get_all("Metadata-Version") == ["2.1"]
@@ -48,32 +50,37 @@ def default_metadata_checks(f):
return message
-def test_make_metadata_file_defaults():
+def test_make_metadata_file_defaults() -> None:
f = default_make_metadata()
+ assert f is not None
default_metadata_checks(f)
-def test_make_metadata_file_custom_value():
+def test_make_metadata_file_custom_value() -> None:
f = default_make_metadata(updates={"a": "1"})
+ assert f is not None
message = default_metadata_checks(f)
assert message.get_all("a") == ["1"]
-def test_make_metadata_file_custom_value_list():
+def test_make_metadata_file_custom_value_list() -> None:
f = default_make_metadata(updates={"a": ["1", "2"]})
+ assert f is not None
message = default_metadata_checks(f)
assert set(message.get_all("a")) == {"1", "2"}
-def test_make_metadata_file_custom_value_overrides():
+def test_make_metadata_file_custom_value_overrides() -> None:
f = default_make_metadata(updates={"Metadata-Version": "2.2"})
+ assert f is not None
message = message_from_bytes(f.contents)
assert message.get_all("Metadata-Version") == ["2.2"]
-def test_make_metadata_file_custom_contents():
+def test_make_metadata_file_custom_contents() -> None:
value = b"hello"
f = default_make_metadata(value=value)
+ assert f is not None
assert f.contents == value
@@ -88,7 +95,7 @@ def test_make_metadata_file_custom_contents():
)
-def default_wheel_metadata_checks(f):
+def default_wheel_metadata_checks(f: File) -> Message:
assert f.name == "simple-0.1.0.dist-info/WHEEL"
message = message_from_bytes(f.contents)
assert message.get_all("Wheel-Version") == ["1.0"]
@@ -98,43 +105,47 @@ def default_wheel_metadata_checks(f):
return message
-def test_make_wheel_metadata_file_defaults():
+def test_make_wheel_metadata_file_defaults() -> None:
f = default_make_wheel_metadata()
+ assert f is not None
default_wheel_metadata_checks(f)
-def test_make_wheel_metadata_file_custom_value():
+def test_make_wheel_metadata_file_custom_value() -> None:
f = default_make_wheel_metadata(updates={"a": "1"})
+ assert f is not None
message = default_wheel_metadata_checks(f)
assert message.get_all("a") == ["1"]
-def test_make_wheel_metadata_file_custom_value_list():
+def test_make_wheel_metadata_file_custom_value_list() -> None:
f = default_make_wheel_metadata(updates={"a": ["1", "2"]})
+ assert f is not None
message = default_wheel_metadata_checks(f)
assert set(message.get_all("a")) == {"1", "2"}
-def test_make_wheel_metadata_file_custom_value_override():
+def test_make_wheel_metadata_file_custom_value_override() -> None:
f = default_make_wheel_metadata(updates={"Wheel-Version": "1.1"})
+ assert f is not None
message = message_from_bytes(f.contents)
assert message.get_all("Wheel-Version") == ["1.1"]
-def test_make_wheel_metadata_file_custom_contents():
+def test_make_wheel_metadata_file_custom_contents() -> None:
value = b"hello"
f = default_make_wheel_metadata(value=value)
-
+ assert f is not None
assert f.name == "simple-0.1.0.dist-info/WHEEL"
assert f.contents == value
-def test_make_wheel_metadata_file_no_contents():
+def test_make_wheel_metadata_file_no_contents() -> None:
f = default_make_wheel_metadata(value=None)
assert f is None
-def test_make_wheel_basics(tmpdir):
+def test_make_wheel_basics(tmpdir: Path) -> None:
make_wheel(name="simple", version="0.1.0").save_to_dir(tmpdir)
expected_wheel_path = tmpdir / "simple-0.1.0-py2.py3-none-any.whl"
@@ -149,7 +160,7 @@ def test_make_wheel_basics(tmpdir):
}
-def test_make_wheel_default_record():
+def test_make_wheel_default_record() -> None:
with make_wheel(
name="simple",
version="0.1.0",
@@ -191,7 +202,7 @@ def test_make_wheel_default_record():
assert records[name][1] == length, name
-def test_make_wheel_extra_files():
+def test_make_wheel_extra_files() -> None:
with make_wheel(
name="simple",
version="0.1.0",
@@ -214,7 +225,7 @@ def test_make_wheel_extra_files():
assert z.read("simple-0.1.0.data/info.txt") == b"c"
-def test_make_wheel_no_files():
+def test_make_wheel_no_files() -> None:
with make_wheel(
name="simple",
version="0.1.0",
@@ -225,7 +236,7 @@ def test_make_wheel_no_files():
assert not z.namelist()
-def test_make_wheel_custom_files():
+def test_make_wheel_custom_files() -> None:
with make_wheel(
name="simple",
version="0.1.0",
diff --git a/tests/lib/venv.py b/tests/lib/venv.py
index 8f5465ed8f0..a43aead9605 100644
--- a/tests/lib/venv.py
+++ b/tests/lib/venv.py
@@ -14,6 +14,10 @@
# Literal was introduced in Python 3.8.
from typing import Literal
+ VirtualEnvironmentType = Literal["virtualenv", "venv"]
+else:
+ VirtualEnvironmentType = str
+
class VirtualEnvironment:
"""
@@ -25,11 +29,11 @@ def __init__(
self,
location: str,
template: Optional["VirtualEnvironment"] = None,
- venv_type: 'Literal[None, "virtualenv", "venv"]' = None,
+ venv_type: Optional[VirtualEnvironmentType] = None,
):
self.location = Path(location)
assert template is None or venv_type is None
- self._venv_type: Literal["virtualenv", "venv"]
+ self._venv_type: VirtualEnvironmentType
if template is not None:
self._venv_type = template._venv_type
elif venv_type is not None:
diff --git a/tests/unit/test_configuration.py b/tests/unit/test_configuration.py
index 6eb1f78ae56..788d32b9b76 100644
--- a/tests/unit/test_configuration.py
+++ b/tests/unit/test_configuration.py
@@ -198,7 +198,8 @@ def test_site_modification(self) -> None:
# Mock out the method
mymock = MagicMock(spec=self.configuration._mark_as_modified)
- self.configuration._mark_as_modified = mymock
+ # https://github.com/python/mypy/issues/2427
+ self.configuration._mark_as_modified = mymock # type: ignore[assignment]
self.configuration.set_value("test.hello", "10")
@@ -213,7 +214,8 @@ def test_user_modification(self) -> None:
# Mock out the method
mymock = MagicMock(spec=self.configuration._mark_as_modified)
- self.configuration._mark_as_modified = mymock
+ # https://github.com/python/mypy/issues/2427
+ self.configuration._mark_as_modified = mymock # type: ignore[assignment]
self.configuration.set_value("test.hello", "10")
@@ -231,7 +233,8 @@ def test_global_modification(self) -> None:
# Mock out the method
mymock = MagicMock(spec=self.configuration._mark_as_modified)
- self.configuration._mark_as_modified = mymock
+ # https://github.com/python/mypy/issues/2427
+ self.configuration._mark_as_modified = mymock # type: ignore[assignment]
self.configuration.set_value("test.hello", "10")