tests: fully type the test suite (#2794)

* tests: fully type the test suite

* chore: require more typing

Signed-off-by: Henry Schreiner <henryfs@princeton.edu>

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

for more information, see https://pre-commit.ci

---------

Signed-off-by: Henry Schreiner <henryfs@princeton.edu>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Henry Schreiner
2026-04-01 15:23:02 +01:00
committed by GitHub
co-authored by pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
parent 643b30c796
commit 097806b6b1
58 changed files with 627 additions and 339 deletions
+1 -1
View File
@@ -52,7 +52,7 @@ class Unbuffered:
self.stream.writelines(data)
self.stream.flush()
def __getattr__(self, attr: str) -> Any:
def __getattr__(self, attr: str) -> Any: # noqa: ANN401
return getattr(self.stream, attr)
+1 -1
View File
@@ -131,7 +131,7 @@ class ParsedEnvironment:
def __repr__(self) -> str:
return f"{self.__class__.__name__}({[repr(a) for a in self.assignments]!r})"
def options_summary(self) -> Any:
def options_summary(self) -> list[EnvironmentAssignment]:
return self.assignments
+3 -3
View File
@@ -987,8 +987,8 @@ class Options:
def option_summary(
self,
option_name: str,
option_value: Any,
default_value: Any,
option_value: Any, # noqa: ANN401
default_value: Any, # noqa: ANN401
overrides: Mapping[str, Any] | None = None,
skip_unset: bool = False,
) -> str | None:
@@ -1040,7 +1040,7 @@ class Options:
return value
@staticmethod
def option_summary_value(option_value: Any) -> str:
def option_summary_value(option_value: Any) -> str: # noqa: ANN401
if hasattr(option_value, "options_summary"):
option_value = option_value.options_summary()
+3 -3
View File
@@ -2,7 +2,7 @@ import dataclasses
import itertools
from enum import StrEnum
from fnmatch import fnmatch
from typing import Any, Self
from typing import Self
import bracex
from packaging.specifiers import SpecifierSet
@@ -113,7 +113,7 @@ class BuildSelector:
return should_build and not should_skip
def options_summary(self) -> Any:
def options_summary(self) -> dict[str, str | list[str]]:
return {
"build_config": self.build_config,
"skip_config": self.skip_config,
@@ -134,5 +134,5 @@ class TestSelector:
should_skip = selector_matches(self.skip_config, build_id)
return not should_skip
def options_summary(self) -> Any:
def options_summary(self) -> dict[str, str]:
return {"skip_config": self.skip_config}
+2 -2
View File
@@ -2,7 +2,7 @@ import shlex
from collections.abc import Mapping, Sequence
from dataclasses import dataclass, field
from pathlib import Path, PurePath
from typing import Any, Literal, Self, TypeVar
from typing import Literal, Self, TypeVar
from packaging.utils import parse_wheel_filename
@@ -102,7 +102,7 @@ class DependencyConstraints:
return None
def options_summary(self) -> Any:
def options_summary(self) -> str | dict[str, str]:
if self == DependencyConstraints.pinned():
return "pinned"
elif self.packages:
+1 -1
View File
@@ -8,7 +8,7 @@ import rich.console
import rich.text
def define_env(env: Any) -> None:
def define_env(env: Any) -> None: # noqa: ANN401
"Hook function for mkdocs-macros"
@env.macro # type: ignore[untyped-decorator]
+3 -5
View File
@@ -129,14 +129,9 @@ files = [
]
warn_unused_configs = true
strict = true
disallow_untyped_defs = false
enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
warn_unreachable = false
[[tool.mypy.overrides]]
module = "cibuildwheel.*"
disallow_untyped_defs = true
[[tool.mypy.overrides]]
module = [
"setuptools._distutils", # needed even if only directly import setuptools._distutils.util
@@ -196,6 +191,7 @@ extend-select = [
"B", # flake8-bugbear
"I", # isort
"ARG", # flake8-unused-arguments
"ANN", # flake8-annotations
"C4", # flake8-comprehensions
"EM", # flake8-errmsg
"ICN", # flake8-import-conventions
@@ -236,6 +232,8 @@ ignore = [
]
flake8-unused-arguments.ignore-variadic-names = true
flake8-tidy-imports.ban-relative-imports = "all"
flake8-annotations.allow-star-arg-any = true
flake8-annotations.mypy-init-return = true
[tool.ruff.lint.flake8-tidy-imports.banned-api]
"typing.Mapping".msg = "Use collections.abc.Mapping instead."
+1 -1
View File
@@ -46,7 +46,7 @@ def pytest_addoption(parser: pytest.Parser) -> None:
)
def pytest_configure(config):
def pytest_configure(config: pytest.Config) -> None:
flag_enable = config.getoption("--enable")
flag_platform = config.getoption("--platform")
+12 -5
View File
@@ -1,4 +1,5 @@
import textwrap
from pathlib import Path
import packaging.utils
import pytest
@@ -21,7 +22,7 @@ basic_project = test_projects.new_c_project(
@pytest.mark.serial
def test_dummy_serial():
def test_dummy_serial() -> None:
"""A no-op test to ensure that at least one serial test is always found.
Without this no-op test, CI fails on CircleCI because no serial tests are
@@ -29,7 +30,9 @@ def test_dummy_serial():
"""
def test(tmp_path, build_frontend_env, capfd):
def test(
tmp_path: Path, build_frontend_env: dict[str, str], capfd: pytest.CaptureFixture[str]
) -> None:
project_dir = tmp_path / "project"
basic_project.generate(project_dir)
@@ -52,7 +55,7 @@ def test(tmp_path, build_frontend_env, capfd):
@pytest.mark.skip(reason="to keep test output clean")
def test_sample_build(tmp_path, capfd):
def test_sample_build(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
project_dir = tmp_path / "project"
basic_project.generate(project_dir)
@@ -70,7 +73,9 @@ def test_sample_build(tmp_path, capfd):
@pytest.mark.parametrize(
"enable_setting", ["", "cpython-prerelease", "pypy", "cpython-freethreading"]
)
def test_build_identifiers(tmp_path, enable_setting, monkeypatch):
def test_build_identifiers(
tmp_path: Path, enable_setting: str, monkeypatch: pytest.MonkeyPatch
) -> None:
project_dir = tmp_path / "project"
basic_project.generate(project_dir)
@@ -93,7 +98,9 @@ def test_build_identifiers(tmp_path, enable_setting, monkeypatch):
(None, {"CIBW_ALLOW_EMPTY": "1"}),
],
)
def test_allow_empty(tmp_path, add_args, env_allow_empty):
def test_allow_empty(
tmp_path: Path, add_args: list[str] | None, env_allow_empty: dict[str, str]
) -> None:
project_dir = tmp_path / "project"
basic_project.generate(project_dir)
+5 -2
View File
@@ -1,4 +1,7 @@
import textwrap
from pathlib import Path
import pytest
from . import test_projects, utils
@@ -31,7 +34,7 @@ limited_api_project = test_projects.new_c_project(
limited_api_project.files["pyproject.toml"] = pyproject_toml
def test_abi3(tmp_path):
def test_abi3(tmp_path: Path) -> None:
project_dir = tmp_path / "project"
limited_api_project.generate(project_dir)
@@ -178,7 +181,7 @@ ctypes_project.files["test/add_test.py"] = textwrap.dedent(
ctypes_project.files["pyproject.toml"] = pyproject_toml
def test_abi_none(tmp_path, capfd):
def test_abi_none(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
project_dir = tmp_path / "project"
ctypes_project.generate(project_dir)
+43 -23
View File
@@ -2,6 +2,8 @@ import os
import platform
import re
import sys
import typing
from collections.abc import Callable
from dataclasses import dataclass
from pathlib import Path
from shutil import rmtree, which
@@ -52,8 +54,10 @@ if "ANDROID_HOME" not in os.environ:
# Many CI services don't support running the Android emulator: see platforms.md.
supports_emulator = (not ci) or ("GITHUB_ACTIONS" in os.environ and platform.system() == "Linux")
T = typing.TypeVar("T", bound=Callable[..., typing.Any])
def needs_emulator(test):
def needs_emulator(test: T) -> T:
# All copies of the testbed app run on the same emulator with the same
# application ID, so these tests must be run serially.
test = pytest.mark.serial(test)
@@ -85,7 +89,7 @@ cp313_env = {
}
def test_android_home(tmp_path, capfd):
def test_android_home(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
new_c_project().generate(tmp_path)
env = os.environ.copy()
del env["ANDROID_HOME"]
@@ -100,7 +104,7 @@ def test_android_home(tmp_path, capfd):
# a build, which is marked as serial so it will run before the parallel tests, but isn't
# marked as needs_emulator so it will run on all CI platforms.
@pytest.mark.serial
def test_expected_wheels(tmp_path, spam_env):
def test_expected_wheels(tmp_path: Path, spam_env: dict[str, str]) -> None:
# Since this test covers all Python versions, check the cross venv.
test_module = "_cross_venv_test_android"
project = new_c_project(setup_py_add=f"import {test_module}")
@@ -119,7 +123,7 @@ def test_expected_wheels(tmp_path, spam_env):
@needs_emulator
def test_frontend_good(tmp_path, build_frontend_env):
def test_frontend_good(tmp_path: Path, build_frontend_env: dict[str, str]) -> None:
new_c_project().generate(tmp_path)
wheels = cibuildwheel_run(
tmp_path,
@@ -129,7 +133,7 @@ def test_frontend_good(tmp_path, build_frontend_env):
@pytest.mark.parametrize("frontend", ["pip"])
def test_frontend_bad(frontend, tmp_path, capfd):
def test_frontend_bad(frontend: str, tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
new_c_project().generate(tmp_path)
with pytest.raises(CalledProcessError):
cibuildwheel_run(
@@ -140,7 +144,7 @@ def test_frontend_bad(frontend, tmp_path, capfd):
@needs_emulator
def test_archs(tmp_path, capfd):
def test_archs(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
new_c_project().generate(tmp_path)
# Build all architectures while checking the handling of the `before` commands.
@@ -189,7 +193,7 @@ def test_archs(tmp_path, capfd):
pytest.fail(f"Unexpected line: {line!r}")
def test_build_requires(tmp_path, capfd):
def test_build_requires(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
# Build-time requirements should be installed for the build platform, not for Android. Prove
# this by installing some non-pure-Python requirements and using them in setup.py.
#
@@ -226,13 +230,13 @@ def test_build_requires(tmp_path, capfd):
@pytest.fixture
def spam_env(tmp_path):
def spam_env(tmp_path: Path) -> dict[str, str]:
project = new_c_project()
project.files["test_spam.py"] = dedent(
"""\
import spam
def test_spam():
def test_spam() -> None:
assert spam.filter("ham")
assert not spam.filter("spam")
print("Spam test passed")
@@ -240,7 +244,7 @@ def spam_env(tmp_path):
)
project.files["test_empty.py"] = dedent(
"""\
def test_empty():
def test_empty() -> None:
pass
"""
)
@@ -265,7 +269,13 @@ def spam_env(tmp_path):
("pytest test_spam.py", "=== 1 passed in "),
],
)
def test_test_command_good(command, expected_output, tmp_path, spam_env, capfd):
def test_test_command_good(
command: str,
expected_output: str,
tmp_path: Path,
spam_env: dict[str, str],
capfd: pytest.CaptureFixture[str],
) -> None:
cibuildwheel_run(tmp_path, add_env={**spam_env, "CIBW_TEST_COMMAND": command})
stdout, stderr = capfd.readouterr()
assert expected_output in stdout
@@ -300,7 +310,13 @@ BAD_PLACEHOLDER_ERROR = (
("pytest test_ham.py", "not found: test_ham.py"),
],
)
def test_test_command_bad(command, expected_output, tmp_path, spam_env, capfd):
def test_test_command_bad(
command: str,
expected_output: str,
tmp_path: Path,
spam_env: dict[str, str],
capfd: pytest.CaptureFixture[str],
) -> None:
with pytest.raises(CalledProcessError):
cibuildwheel_run(tmp_path, add_env={**spam_env, "CIBW_TEST_COMMAND": command})
assert expected_output in capfd.readouterr().err
@@ -314,7 +330,9 @@ def test_test_command_bad(command, expected_output, tmp_path, spam_env, capfd):
("-E", 1),
],
)
def test_test_command_python_options(options, expected, tmp_path, capfd):
def test_test_command_python_options(
options: str, expected: int, tmp_path: Path, capfd: pytest.CaptureFixture[str]
) -> None:
project = new_c_project()
project.generate(tmp_path)
@@ -330,7 +348,9 @@ def test_test_command_python_options(options, expected, tmp_path, capfd):
@needs_emulator
def test_package_subdir(tmp_path, spam_env, capfd):
def test_package_subdir(
tmp_path: Path, spam_env: dict[str, str], capfd: pytest.CaptureFixture[str]
) -> None:
spam_paths = list(tmp_path.iterdir())
package_dir = tmp_path / "package"
package_dir.mkdir()
@@ -345,7 +365,7 @@ def test_package_subdir(tmp_path, spam_env, capfd):
@needs_emulator
def test_no_test_sources(tmp_path, capfd):
def test_no_test_sources(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
new_c_project().generate(tmp_path)
with pytest.raises(CalledProcessError):
cibuildwheel_run(
@@ -359,17 +379,17 @@ def test_no_test_sources(tmp_path, capfd):
@needs_emulator
def test_environment_markers(tmp_path):
def test_environment_markers(tmp_path: Path) -> None:
project = new_c_project()
test_filename = "test_environment_markers.py"
project.files[test_filename] = dedent(
"""\
import pytest
def test_android():
def test_android() -> None:
import certifi
def test_not_android():
def test_not_android() -> None:
try:
import platformdirs
except ImportError:
@@ -392,7 +412,7 @@ def test_environment_markers(tmp_path):
@needs_emulator
def test_verbosity(tmp_path, capfd):
def test_verbosity(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
new_c_project().generate(tmp_path)
test_env = {
**cp313_env,
@@ -418,7 +438,7 @@ def test_verbosity(tmp_path, capfd):
@needs_emulator
def test_api_level(tmp_path, capfd):
def test_api_level(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
project = new_c_project()
project.files["pyproject.toml"] = dedent(
"""\
@@ -450,7 +470,7 @@ def test_api_level(tmp_path, capfd):
@needs_emulator
def test_libcxx(tmp_path, capfd):
def test_libcxx(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
project_dir = tmp_path / "project"
output_dir = tmp_path / "output"
@@ -499,7 +519,7 @@ def test_libcxx(tmp_path, capfd):
@needs_emulator
def test_setuptools_rust(tmp_path, capfd):
def test_setuptools_rust(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
"""
Test Android cross-compilation using the setuptools-rust toolchain.
"""
@@ -584,7 +604,7 @@ def test_setuptools_rust(tmp_path, capfd):
@needs_emulator
def test_maturin(tmp_path, capfd):
def test_maturin(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
"""
Test Android cross-compilation using the maturin backend.
"""
+4 -3
View File
@@ -1,5 +1,6 @@
import subprocess
import textwrap
from pathlib import Path
import pytest
@@ -29,7 +30,7 @@ project_with_before_build_asserts = test_projects.new_c_project(
)
def test(tmp_path):
def test(tmp_path: Path) -> None:
project_dir = tmp_path / "project"
project_with_before_build_asserts.generate(project_dir)
@@ -61,7 +62,7 @@ def test(tmp_path):
assert set(actual_wheels) == set(expected_wheels)
def test_failing_command(tmp_path):
def test_failing_command(tmp_path: Path) -> None:
project_dir = tmp_path / "project"
test_projects.new_c_project().generate(project_dir)
@@ -75,7 +76,7 @@ def test_failing_command(tmp_path):
)
def test_cwd(tmp_path):
def test_cwd(tmp_path: Path) -> None:
project_dir = tmp_path / "project"
test_projects.new_c_project().generate(project_dir)
+4 -3
View File
@@ -1,5 +1,6 @@
import subprocess
import textwrap
from pathlib import Path
import pytest
@@ -36,7 +37,7 @@ project_with_before_build_asserts = test_projects.new_c_project(
)
def test(tmp_path):
def test(tmp_path: Path) -> None:
project_dir = tmp_path / "project"
project_with_before_build_asserts.generate(project_dir)
@@ -65,7 +66,7 @@ def test(tmp_path):
assert set(actual_wheels) == set(expected_wheels)
def test_failing_command(tmp_path):
def test_failing_command(tmp_path: Path) -> None:
project_dir = tmp_path / "project"
test_projects.new_c_project().generate(project_dir)
@@ -79,7 +80,7 @@ def test_failing_command(tmp_path):
)
def test_cwd(tmp_path):
def test_cwd(tmp_path: Path) -> None:
project_dir = tmp_path / "project"
test_projects.new_c_project().generate(project_dir)
+5 -3
View File
@@ -1,3 +1,5 @@
from pathlib import Path
from . import test_projects, utils
before_test_project = test_projects.new_c_project()
@@ -11,7 +13,7 @@ PROJECT_DIR = Path(__file__).parent.parent.resolve()
class TestBeforeTest(TestCase):
def test_version(self):
def test_version(self) -> None:
# assert that the Python version as written to pythonversion_bt.txt in the CIBW_BEFORE_TEST step
# is the same one as is currently running.
# because of use symlinks in MacOS run this test is also need
@@ -20,7 +22,7 @@ class TestBeforeTest(TestCase):
print('sys.version', sys.version)
assert stored_version == sys.version
def test_prefix(self):
def test_prefix(self) -> None:
# check that the prefix also was written
stored_prefix = PROJECT_DIR.joinpath('pythonprefix_bt.txt').read_text()
print('stored_prefix', stored_prefix)
@@ -32,7 +34,7 @@ class TestBeforeTest(TestCase):
"""
def test(tmp_path, build_frontend_env):
def test(tmp_path: Path, build_frontend_env: dict[str, str]) -> None:
project_dir = tmp_path / "project"
before_test_project.generate(project_dir)
test_project_dir = project_dir / "dependency"
+4 -1
View File
@@ -1,4 +1,5 @@
import subprocess
from pathlib import Path
import pytest
@@ -12,7 +13,9 @@ from . import test_projects, utils
"build",
],
)
def test_build_frontend_args(tmp_path, capfd, frontend_name):
def test_build_frontend_args(
tmp_path: Path, capfd: pytest.CaptureFixture[str], frontend_name: str
) -> None:
project = test_projects.new_c_project()
project_dir = tmp_path / "project"
project.generate(project_dir)
+2 -1
View File
@@ -1,4 +1,5 @@
import textwrap
from pathlib import Path
from . import test_projects, utils
@@ -15,7 +16,7 @@ project_with_skip_asserts = test_projects.new_c_project(
)
def test(tmp_path):
def test(tmp_path: Path) -> None:
project_dir = tmp_path / "project"
project_with_skip_asserts.generate(project_dir)
+6 -2
View File
@@ -1,3 +1,5 @@
from pathlib import Path
import pytest
from . import test_projects, utils
@@ -5,7 +7,9 @@ from . import test_projects, utils
basic_project = test_projects.new_c_project()
def test_podman(tmp_path, capfd, request):
def test_podman(
tmp_path: Path, capfd: pytest.CaptureFixture[str], request: pytest.FixtureRequest
) -> None:
if utils.get_platform() != "linux":
pytest.skip("the test is only relevant to the linux build")
@@ -35,7 +39,7 @@ def test_podman(tmp_path, capfd, request):
assert "test log statement from before-all" in captured.out
def test_create_args(tmp_path, capfd):
def test_create_args(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
if utils.get_platform() != "linux":
pytest.skip("the test is only relevant to the linux build")
+2 -1
View File
@@ -1,5 +1,6 @@
import platform
import textwrap
from pathlib import Path
import pytest
@@ -22,7 +23,7 @@ dockcross_only_project = test_projects.new_c_project(
@pytest.mark.usefixtures("docker_cleanup")
def test(tmp_path):
def test(tmp_path: Path) -> None:
if utils.get_platform() != "linux":
pytest.skip("the test is only relevant to the linux build")
if platform.machine() not in ["x86_64", "i686"]:
+5 -3
View File
@@ -1,3 +1,5 @@
from pathlib import Path
import jinja2
from . import utils
@@ -52,7 +54,7 @@ cpp_test_project.files["setup.py"] = jinja2.Template(setup_py_template)
cpp_test_project.files["spam.cpp"] = jinja2.Template(spam_cpp_template)
def test_cpp11(tmp_path):
def test_cpp11(tmp_path: Path) -> None:
# This test checks that the C++11 standard is supported
project_dir = tmp_path / "project"
cpp11_project = cpp_test_project.copy()
@@ -68,7 +70,7 @@ def test_cpp11(tmp_path):
assert set(actual_wheels) == set(expected_wheels)
def test_cpp14(tmp_path):
def test_cpp14(tmp_path: Path) -> None:
# This test checks that the C++14 standard is supported
project_dir = tmp_path / "project"
cpp14_project = cpp_test_project.copy()
@@ -84,7 +86,7 @@ def test_cpp14(tmp_path):
assert set(actual_wheels) == set(expected_wheels)
def test_cpp17(tmp_path):
def test_cpp17(tmp_path: Path) -> None:
# This test checks that the C++17 standard is supported
project_dir = tmp_path / "project"
cpp17_project = cpp_test_project.copy()
+3 -2
View File
@@ -1,6 +1,7 @@
import subprocess
import textwrap
from contextlib import nullcontext as does_not_raise
from pathlib import Path
import pytest
@@ -30,7 +31,7 @@ shutil.copy(wheel, dest)
"""
def test(tmp_path, capfd):
def test(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
# this test checks that a generated wheel name shall be unique in a given cibuildwheel run
project_dir = tmp_path / "project"
basic_project.generate(project_dir)
@@ -68,7 +69,7 @@ def test(tmp_path, capfd):
],
ids=["no-placeholder", "package-placeholder", "project-placeholder"],
)
def test_repair_wheel_command_structure(tmp_path, repair_command):
def test_repair_wheel_command_structure(tmp_path: Path, repair_command: str) -> None:
project_dir = tmp_path / "project"
project = test_projects.new_c_project()
project.files["repair.py"] = textwrap.dedent("""
+9 -3
View File
@@ -36,7 +36,9 @@ for name, expected_version in expected_versions.items():
"""
def test_check_versions_script(tmp_path, build_frontend_env_nouv, capfd):
def test_check_versions_script(
tmp_path: Path, build_frontend_env_nouv: dict[str, str], capfd: pytest.CaptureFixture[str]
) -> None:
if utils.get_platform() == "linux":
pytest.skip("we don't test dependency versions on linux, refer to other tests")
@@ -76,7 +78,9 @@ def get_versions_from_constraint_file(constraint_file: Path) -> dict[str, str]:
@pytest.mark.parametrize("python_version", ["3.8", "3.12"])
def test_pinned_versions(tmp_path, python_version, build_frontend_env_nouv):
def test_pinned_versions(
tmp_path: Path, python_version: str, build_frontend_env_nouv: dict[str, str]
) -> None:
if utils.get_platform() == "linux":
pytest.skip("linux doesn't pin individual tool versions, it pins manylinux images instead")
if python_version != "3.12" and utils.get_platform() == "pyodide":
@@ -127,7 +131,9 @@ def test_pinned_versions(tmp_path, python_version, build_frontend_env_nouv):
@pytest.mark.parametrize("method", ["inline", "file"])
def test_dependency_constraints(method, tmp_path, build_frontend_env_nouv):
def test_dependency_constraints(
method: str, tmp_path: Path, build_frontend_env_nouv: dict[str, str]
) -> None:
if utils.get_platform() == "linux":
pytest.skip("linux doesn't pin individual tool versions, it pins manylinux images instead")
+4 -3
View File
@@ -1,5 +1,6 @@
import itertools
import subprocess
from pathlib import Path
import pytest
@@ -10,13 +11,13 @@ project_with_a_test = test_projects.new_c_project()
project_with_a_test.files["test/spam_test.py"] = r"""
import spam
def test_spam():
def test_spam() -> None:
assert spam.filter("spam") == 0
assert spam.filter("ham") != 0
"""
def test(tmp_path, request):
def test(tmp_path: Path, request: pytest.FixtureRequest) -> None:
archs = request.config.getoption("--run-emulation")
if archs is None:
pytest.skip("needs --run-emulation option to run")
@@ -45,7 +46,7 @@ def test(tmp_path, request):
assert set(actual_wheels) == set(expected_wheels)
def test_setting_arch_on_other_platforms(tmp_path, capfd):
def test_setting_arch_on_other_platforms(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
if utils.get_platform() == "linux":
pytest.skip("this test checks the behaviour on platforms other than linux")
+4 -3
View File
@@ -2,6 +2,7 @@ import os
import subprocess
import sys
import textwrap
from pathlib import Path
import pytest
@@ -33,7 +34,7 @@ project_with_environment_asserts = test_projects.new_c_project(
)
def test(tmp_path):
def test(tmp_path: Path) -> None:
python_echo = f"'{sys.executable}' -c \"import sys; print(*sys.argv[1:])\""
project_dir = tmp_path / "project"
project_with_environment_asserts.generate(project_dir)
@@ -55,7 +56,7 @@ def test(tmp_path):
assert set(actual_wheels) == set(expected_wheels)
def test_overridden_path(tmp_path, capfd):
def test_overridden_path(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
project_dir = tmp_path / "project"
output_dir = tmp_path / "output"
@@ -108,7 +109,7 @@ def test_overridden_path(tmp_path, capfd):
),
],
)
def test_overridden_pip_constraint(tmp_path, build_frontend):
def test_overridden_pip_constraint(tmp_path: Path, build_frontend: str) -> None:
"""
Verify that users can use PIP_CONSTRAINT to specify a specific version of
a build-system.requires dependency, by asserting the version of pytz in the
+6 -4
View File
@@ -6,6 +6,8 @@ from collections.abc import Mapping
from pathlib import Path
from tempfile import TemporaryDirectory
import pytest
from test.test_projects.base import TestProject
from . import test_projects, utils
@@ -59,7 +61,7 @@ def cibuildwheel_from_sdist_run(
# tests
def test_simple(tmp_path):
def test_simple(tmp_path: Path) -> None:
basic_project = test_projects.new_c_project()
# make an sdist of the project
@@ -87,7 +89,7 @@ def test_simple(tmp_path):
assert set(actual_wheels) == set(expected_wheels)
def test_external_config_file_argument(tmp_path, capfd):
def test_external_config_file_argument(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
basic_project = test_projects.new_c_project()
# make an sdist of the project
@@ -118,7 +120,7 @@ def test_external_config_file_argument(tmp_path, capfd):
assert "test log statement from before-all" in captured.out
def test_config_in_pyproject_toml(tmp_path, capfd):
def test_config_in_pyproject_toml(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
# make a project with a pyproject.toml
project = test_projects.new_c_project()
project.files["pyproject.toml"] = textwrap.dedent(
@@ -145,7 +147,7 @@ def test_config_in_pyproject_toml(tmp_path, capfd):
assert "test log statement from before-build 8419" in captured.out
def test_internal_config_file_argument(tmp_path, capfd):
def test_internal_config_file_argument(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
# make a project with a config file inside
project = test_projects.new_c_project(
setup_cfg_add="include_package_data = True",
+23 -13
View File
@@ -3,6 +3,7 @@ import platform
import shutil
import subprocess
import textwrap
from pathlib import Path
import pytest
@@ -22,7 +23,7 @@ import platform
from unittest import TestCase
class TestPlatform(TestCase):
def test_platform(self):
def test_platform(self) -> None:
self.assertEqual(platform.machine(), "{platform.machine()}")
"""
@@ -59,7 +60,12 @@ def skip_if_ios_testing_not_supported() -> None:
{"CIBW_PLATFORM": "ios", "CIBW_BUILD_FRONTEND": "build"},
],
)
def test_ios_platforms(tmp_path, build_config, monkeypatch, capfd):
def test_ios_platforms(
tmp_path: Path,
build_config: dict[str, str],
monkeypatch: pytest.MonkeyPatch,
capfd: pytest.CaptureFixture[str],
) -> None:
skip_if_ios_testing_not_supported()
# Create a temporary "bin" directory, symlink a tool that we know eixsts
@@ -67,7 +73,9 @@ def test_ios_platforms(tmp_path, build_config, monkeypatch, capfd):
# and add the temp bin directory to the PATH.
tools_dir = tmp_path / "bin"
tools_dir.mkdir()
tools_dir.joinpath("does-exist").symlink_to(shutil.which("true"))
true_app = shutil.which("true")
assert true_app is not None
tools_dir.joinpath("does-exist").symlink_to(true_app)
monkeypatch.setenv("PATH", str(tools_dir), prepend=os.pathsep)
@@ -110,7 +118,7 @@ def test_ios_platforms(tmp_path, build_config, monkeypatch, capfd):
@pytest.mark.serial
def test_no_test_sources(tmp_path, capfd):
def test_no_test_sources(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
"""Build will provide a helpful error if pytest is run and test-sources is not defined."""
skip_if_ios_testing_not_supported()
@@ -138,7 +146,7 @@ def test_no_test_sources(tmp_path, capfd):
)
def test_ios_testing_with_placeholder(tmp_path, capfd):
def test_ios_testing_with_placeholder(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
"""
Tests with the {project} placeholder are not supported on iOS, because the test command
is run in the simulator.
@@ -168,7 +176,7 @@ def test_ios_testing_with_placeholder(tmp_path, capfd):
@pytest.mark.serial
@pytest.mark.flaky(reruns=2)
def test_ios_test_command_short_circuit(tmp_path, capfd):
def test_ios_test_command_short_circuit(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
skip_if_ios_testing_not_supported()
project_dir = tmp_path / "project"
@@ -196,7 +204,7 @@ def test_ios_test_command_short_circuit(tmp_path, capfd):
assert "Zen of Python" not in captured.out + captured.err
def test_missing_xbuild_tool(tmp_path, capfd):
def test_missing_xbuild_tool(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
"""Build will fail if xbuild-tools references a non-existent tool."""
skip_if_ios_testing_not_supported()
@@ -220,7 +228,7 @@ def test_missing_xbuild_tool(tmp_path, capfd):
assert "Could not find a 'does-not-exist' executable on the path." in captured.err
def test_no_xbuild_tool_definition(tmp_path, capfd):
def test_no_xbuild_tool_definition(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
"""Build will succeed with a warning if there is no xbuild-tools definition."""
skip_if_ios_testing_not_supported()
@@ -254,7 +262,7 @@ def test_no_xbuild_tool_definition(tmp_path, capfd):
assert "Your project configuration does not define any cross-build tools." in captured.err
def test_empty_xbuild_tool_definition(tmp_path, capfd):
def test_empty_xbuild_tool_definition(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
"""Build will succeed with no warning if there is an empty xbuild-tools definition."""
skip_if_ios_testing_not_supported()
@@ -286,7 +294,9 @@ def test_empty_xbuild_tool_definition(tmp_path, capfd):
@pytest.mark.serial
def test_ios_test_command_without_python_dash_m(tmp_path, capfd):
def test_ios_test_command_without_python_dash_m(
tmp_path: Path, capfd: pytest.CaptureFixture[str]
) -> None:
"""pytest should be able to run without python -m, but it should warn."""
skip_if_ios_testing_not_supported()
@@ -296,7 +306,7 @@ def test_ios_test_command_without_python_dash_m(tmp_path, capfd):
project.files["tests/__init__.py"] = ""
project.files["tests/test_spam.py"] = textwrap.dedent("""
import spam
def test_spam():
def test_spam() -> None:
assert spam.filter("spam") == 0
assert spam.filter("ham") != 0
""")
@@ -324,7 +334,7 @@ def test_ios_test_command_without_python_dash_m(tmp_path, capfd):
assert "iOS tests configured with a test command which doesn't start with 'python -m'" in err
def test_ios_test_command_invalid(tmp_path, capfd):
def test_ios_test_command_invalid(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
"""Test command should raise an error if it's clearly invalid."""
skip_if_ios_testing_not_supported()
@@ -347,7 +357,7 @@ def test_ios_test_command_invalid(tmp_path, capfd):
assert "iOS tests configured with a test command which doesn't start with 'python -m'" in err
def test_repair_step(tmp_path):
def test_repair_step(tmp_path: Path) -> None:
"""Build will succeed & the custom repair step is called."""
skip_if_ios_testing_not_supported()
+2 -1
View File
@@ -1,12 +1,13 @@
import platform
import subprocess
from pathlib import Path
import pytest
from . import test_projects, utils
def test_python_exist(tmp_path, capfd):
def test_python_exist(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
if utils.get_platform() != "linux":
pytest.skip("the test is only relevant to the linux build")
machine = platform.machine()
+23 -7
View File
@@ -1,4 +1,5 @@
import platform
from pathlib import Path
import pytest
@@ -19,7 +20,7 @@ ALL_MACOS_WHEELS = {
DEPLOYMENT_TARGET_TOO_LOW_WARNING = "Bumping MACOSX_DEPLOYMENT_TARGET"
def test_cross_compiled_build(tmp_path):
def test_cross_compiled_build(tmp_path: Path) -> None:
if utils.get_platform() != "macos":
pytest.skip("this test is only relevant to macos")
if utils.get_xcode_version() < (12, 2):
@@ -51,7 +52,12 @@ def test_cross_compiled_build(tmp_path):
},
],
)
def test_cross_compiled_test(tmp_path, capfd, build_universal2, test_config):
def test_cross_compiled_test(
tmp_path: Path,
capfd: pytest.CaptureFixture[str],
build_universal2: bool,
test_config: dict[str, str],
) -> None:
if utils.get_platform() != "macos":
pytest.skip("this test is only relevant to macos")
if utils.get_xcode_version() < (12, 2):
@@ -110,7 +116,9 @@ def test_cross_compiled_test(tmp_path, capfd, build_universal2, test_config):
assert set(actual_wheels) == set(expected_wheels)
def test_deployment_target_warning_is_firing(tmp_path, capfd):
def test_deployment_target_warning_is_firing(
tmp_path: Path, capfd: pytest.CaptureFixture[str]
) -> None:
# force the warning to check that we can detect it if it happens
if utils.get_platform() != "macos":
pytest.skip("this test is only relevant to macos")
@@ -133,7 +141,9 @@ def test_deployment_target_warning_is_firing(tmp_path, capfd):
@pytest.mark.parametrize("skip_arm64_test", [False, True])
def test_universal2_testing_on_x86_64(tmp_path, capfd, skip_arm64_test):
def test_universal2_testing_on_x86_64(
tmp_path: Path, capfd: pytest.CaptureFixture[str], skip_arm64_test: bool
) -> None:
if utils.get_platform() != "macos":
pytest.skip("this test is only relevant to macos")
if utils.get_xcode_version() < (12, 2):
@@ -172,7 +182,9 @@ def test_universal2_testing_on_x86_64(tmp_path, capfd, skip_arm64_test):
assert set(actual_wheels) == set(expected_wheels)
def test_universal2_testing_on_arm64(build_frontend_env, tmp_path, capfd):
def test_universal2_testing_on_arm64(
build_frontend_env: dict[str, str], tmp_path: Path, capfd: pytest.CaptureFixture[str]
) -> None:
# cibuildwheel should test the universal2 wheel on both x86_64 and arm64, when run on arm64
if utils.get_platform() != "macos":
pytest.skip("this test is only relevant to macos")
@@ -203,7 +215,9 @@ def test_universal2_testing_on_arm64(build_frontend_env, tmp_path, capfd):
assert set(actual_wheels) == set(expected_wheels)
def test_cp38_arm64_testing(tmp_path, capfd, request):
def test_cp38_arm64_testing(
tmp_path: Path, capfd: pytest.CaptureFixture[str], request: pytest.FixtureRequest
) -> None:
if utils.get_platform() != "macos":
pytest.skip("this test is only relevant to macos")
if utils.get_xcode_version() < (12, 2):
@@ -238,7 +252,9 @@ def test_cp38_arm64_testing(tmp_path, capfd, request):
assert set(actual_wheels) == set(expected_wheels)
def test_cp38_arm64_testing_universal2_installer(tmp_path, capfd, request):
def test_cp38_arm64_testing_universal2_installer(
tmp_path: Path, capfd: pytest.CaptureFixture[str], request: pytest.FixtureRequest
) -> None:
if not request.config.getoption("--run-cp38-universal2"):
pytest.skip("needs --run-cp38-universal2 option to run")
+2 -1
View File
@@ -1,5 +1,6 @@
import platform
import textwrap
from pathlib import Path
import pytest
@@ -61,7 +62,7 @@ project_with_manylinux_symbols = test_projects.new_c_project(
],
)
@pytest.mark.usefixtures("docker_cleanup")
def test(manylinux_image, tmp_path):
def test(manylinux_image: str, tmp_path: Path) -> None:
if utils.get_platform() != "linux":
pytest.skip("the container image test is only relevant to the linux build")
+3 -1
View File
@@ -1,3 +1,5 @@
from pathlib import Path
import packaging.utils
from . import test_projects, utils
@@ -5,7 +7,7 @@ from . import test_projects, utils
meson_project = test_projects.new_meson_project()
def test_meson_python_basic(tmp_path, build_frontend_env):
def test_meson_python_basic(tmp_path: Path, build_frontend_env: dict[str, str]) -> None:
"""Test that cibuildwheel can build a project with meson-python backend."""
project_dir = tmp_path / "project"
+2 -1
View File
@@ -1,4 +1,5 @@
import textwrap
from pathlib import Path
import pytest
@@ -27,7 +28,7 @@ project_with_manylinux_symbols = test_projects.new_c_project(
["musllinux_1_2"],
)
@pytest.mark.usefixtures("docker_cleanup")
def test(musllinux_image, tmp_path):
def test(musllinux_image: str, tmp_path: Path) -> None:
if utils.get_platform() != "linux":
pytest.skip("the container image test is only relevant to the linux build")
+2 -1
View File
@@ -1,4 +1,5 @@
import textwrap
from pathlib import Path
from . import test_projects, utils
@@ -29,7 +30,7 @@ build-backend = "setuptools.build_meta"
"""
def test_pep518(tmp_path, build_frontend_env):
def test_pep518(tmp_path: Path, build_frontend_env: dict[str, str]) -> None:
project_dir = tmp_path / "project"
basic_project.generate(project_dir)
+2 -1
View File
@@ -1,4 +1,5 @@
import subprocess
from pathlib import Path
import pytest
@@ -23,7 +24,7 @@ def a_function():
"""
def test(tmp_path, capfd):
def test(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
# this test checks that if a pure wheel is generated, the build should
# fail.
project_dir = tmp_path / "project"
+7 -6
View File
@@ -3,6 +3,7 @@ import os
import subprocess
import sys
import textwrap
from pathlib import Path
import pytest
@@ -48,7 +49,7 @@ if __name__ == "__main__":
@pytest.mark.parametrize("use_pyproject_toml", [True, False])
def test_pyodide_build(tmp_path, use_pyproject_toml):
def test_pyodide_build(tmp_path: Path, use_pyproject_toml: bool) -> None:
if sys.platform == "win32":
pytest.skip("pyodide-build doesn't work correctly on Windows")
@@ -88,7 +89,7 @@ def test_pyodide_build(tmp_path, use_pyproject_toml):
assert set(actual_wheels) == set(expected_wheels)
def test_pyodide_version_incompatible(tmp_path, capfd):
def test_pyodide_version_incompatible(tmp_path: Path, capfd: pytest.CaptureFixture[str]) -> None:
if sys.platform == "win32":
pytest.skip("pyodide-build doesn't work correctly on Windows")
@@ -110,19 +111,19 @@ def test_pyodide_version_incompatible(tmp_path, capfd):
@pytest.mark.parametrize("expect_failure", [True, False])
def test_pyodide_build_and_test(tmp_path, expect_failure):
def test_pyodide_build_and_test(tmp_path: Path, expect_failure: bool) -> None:
if sys.platform == "win32":
pytest.skip("pyodide-build doesn't work correctly on Windows")
if expect_failure:
basic_project.files["test/spam_test.py"] = textwrap.dedent(r"""
def test_filter():
def test_filter() -> None:
assert 0 == 1
""")
else:
basic_project.files["test/spam_test.py"] = textwrap.dedent(r"""
import spam
def test_filter():
def test_filter() -> None:
assert spam.filter("spam") == 0
""")
basic_project.generate(tmp_path)
@@ -149,7 +150,7 @@ def test_pyodide_build_and_test(tmp_path, expect_failure):
assert set(actual_wheels) == set(expected_wheels)
def test_pyodide_repair_wheel(tmp_path):
def test_pyodide_repair_wheel(tmp_path: Path) -> None:
if sys.platform == "win32":
pytest.skip("pyodide-build doesn't work correctly on Windows")
+2 -1
View File
@@ -1,4 +1,5 @@
import textwrap
from pathlib import Path
import pytest
@@ -32,7 +33,7 @@ project_with_ssl_tests = test_projects.new_c_project(
@pytest.mark.flaky(reruns=2)
def test(tmp_path):
def test(tmp_path: Path) -> None:
# this test checks that SSL is working in the build environment using
# some checks in setup.py.
project_dir = tmp_path / "project"
+2 -1
View File
@@ -1,6 +1,7 @@
from pathlib import Path
import jinja2
import pytest
from . import utils
from .test_projects import TestProject
@@ -31,7 +32,7 @@ print('before_build.py executed!')
"""
def test(capfd, tmp_path):
def test(capfd: pytest.CaptureFixture[str], tmp_path: Path) -> None:
project_dir = tmp_path / "project"
subdir_package_project.generate(project_dir)
+10 -10
View File
@@ -43,11 +43,11 @@ def path_contains(parent, child):
class TestSpam(TestCase):
def test_filter(self):
def test_filter(self) -> None:
self.assertEqual(0, spam.filter("spam"))
self.assertNotEqual(0, spam.filter("ham"))
def test_virtualenv(self):
def test_virtualenv(self) -> None:
# sys.prefix is different from sys.base_prefix when running a virtualenv
# See https://docs.python.org/3/library/venv.html, which virtualenv seems
# to honor in recent releases
@@ -58,7 +58,7 @@ class TestSpam(TestCase):
self.assertTrue(path_contains(sys.prefix, spam.__file__))
self.assertIn("VIRTUAL_ENV", os.environ)
def test_uname(self):
def test_uname(self) -> None:
if platform.system() == "Windows":
return
# if we're running in 32-bit Python, check that the machine is i686.
@@ -69,7 +69,7 @@ class TestSpam(TestCase):
'''
def test(tmp_path):
def test(tmp_path: Path) -> None:
project_dir = tmp_path / "project"
project_with_a_test.generate(project_dir)
@@ -90,7 +90,7 @@ def test(tmp_path):
assert set(actual_wheels) == set(expected_wheels)
def test_extras_require(tmp_path):
def test_extras_require(tmp_path: Path) -> None:
project_dir = tmp_path / "project"
project_with_a_test.generate(project_dir)
@@ -112,7 +112,7 @@ def test_extras_require(tmp_path):
assert set(actual_wheels) == set(expected_wheels)
def test_dependency_groups(tmp_path):
def test_dependency_groups(tmp_path: Path) -> None:
group_project = project_with_a_test.copy()
group_project.files["pyproject.toml"] = inspect.cleandoc("""
[build-system]
@@ -149,12 +149,12 @@ project_with_a_failing_test.files["test/spam_test.py"] = r"""
from unittest import TestCase
class TestSpam(TestCase):
def test_something(self):
def test_something(self) -> None:
self.fail('this test is supposed to fail')
"""
def test_failing_test(tmp_path):
def test_failing_test(tmp_path: Path) -> None:
"""Ensure a failing test causes cibuildwheel to error out and exit"""
project_dir = tmp_path / "project"
output_dir = tmp_path / "output"
@@ -215,7 +215,7 @@ def test_bare_pytest_invocation(
)
def test_test_sources(tmp_path):
def test_test_sources(tmp_path: Path) -> None:
project_dir = tmp_path / "project"
project_with_a_test.generate(project_dir)
@@ -235,7 +235,7 @@ def test_test_sources(tmp_path):
assert set(actual_wheels) == set(expected_wheels)
def test_test_environment(tmp_path):
def test_test_environment(tmp_path: Path) -> None:
project_dir = tmp_path / "project"
test_projects.new_c_project().generate(project_dir)
+12 -2
View File
@@ -1,4 +1,5 @@
import subprocess
from pathlib import Path
import pytest
@@ -9,7 +10,12 @@ SO_FILE_WARNING = "NOTE: Shared object (.so) files found in this project."
@pytest.mark.parametrize("project_contains_so_files", [False, True])
def test_failed_build_with_so_files(tmp_path, capfd, build_frontend_env, project_contains_so_files):
def test_failed_build_with_so_files(
tmp_path: Path,
capfd: pytest.CaptureFixture[str],
build_frontend_env: dict[str, str],
project_contains_so_files: bool,
) -> None:
project = TestProject()
project.files["setup.py"] = "raise Exception('this build will fail')\n"
if project_contains_so_files:
@@ -35,7 +41,11 @@ def test_failed_build_with_so_files(tmp_path, capfd, build_frontend_env, project
@pytest.mark.parametrize("project_contains_so_files", [False, True])
def test_failed_repair_with_so_files(tmp_path, capfd, project_contains_so_files):
def test_failed_repair_with_so_files(
tmp_path: Path,
capfd: pytest.CaptureFixture[str],
project_contains_so_files: bool,
) -> None:
if utils.get_platform() != "linux":
pytest.skip("this test is only relevant to the linux build")
+3 -1
View File
@@ -1,3 +1,5 @@
from pathlib import Path
import pytest
from . import test_projects, utils
@@ -5,7 +7,7 @@ from . import test_projects, utils
basic_project = test_projects.new_c_project()
def test_wheel_tag_is_correct_when_using_macosx_deployment_target(tmp_path):
def test_wheel_tag_is_correct_when_using_macosx_deployment_target(tmp_path: Path) -> None:
if utils.get_platform() != "macos":
pytest.skip("This test is only relevant to MACOSX_DEPLOYMENT_TARGET")
+3 -1
View File
@@ -38,7 +38,9 @@ def skip_if_no_msvc(arm64: bool = False) -> None:
@pytest.mark.parametrize("use_pyproject_toml", [True, False])
def test_wheel_tag_is_correct_when_using_windows_cross_compile(tmp_path, use_pyproject_toml):
def test_wheel_tag_is_correct_when_using_windows_cross_compile(
tmp_path: Path, use_pyproject_toml: bool
) -> None:
if utils.get_platform() != "windows":
pytest.skip("This test is only relevant to Windows")
+2 -2
View File
@@ -11,7 +11,7 @@ import sys
from collections.abc import Generator, Mapping, Sequence
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import Any, Final
from typing import Final
import pytest
@@ -458,7 +458,7 @@ def get_xcode_version() -> tuple[int, int]:
return (int(version_parts[0]), int(version_parts[1]))
def skip_if_pyodide(reason: str) -> Any:
def skip_if_pyodide(reason: str) -> pytest.MarkDecorator:
return pytest.mark.skipif(get_platform() == "pyodide", reason=reason)
+13 -8
View File
@@ -6,6 +6,7 @@ import pytest
import cibuildwheel.architecture
from cibuildwheel.architecture import Architecture, arch_synonym
from cibuildwheel.typing import PlatformName
@pytest.fixture(
@@ -20,7 +21,9 @@ from cibuildwheel.architecture import Architecture, arch_synonym
pytest.param(("windows", "win32", "ARM64", "arm"), id="windows-arm"),
]
)
def platform_machine(request, monkeypatch):
def platform_machine(
request: pytest.FixtureRequest, monkeypatch: pytest.MonkeyPatch
) -> tuple[str, str]:
platform_name, platform_value, machine_value, machine_name = request.param
monkeypatch.setattr(sys, "platform", platform_value)
monkeypatch.setattr(platform_module, "machine", lambda: machine_value)
@@ -28,7 +31,7 @@ def platform_machine(request, monkeypatch):
return platform_name, machine_name
def test_arch_auto(platform_machine):
def test_arch_auto(platform_machine: tuple[str, str]) -> None:
_, machine_name = platform_machine
arch_set = Architecture.auto_archs("linux")
@@ -52,7 +55,7 @@ def test_arch_auto(platform_machine):
assert arch_set == expected[machine_name]
def test_arch_auto64(platform_machine):
def test_arch_auto64(platform_machine: tuple[str, str]) -> None:
_, machine_name = platform_machine
arch_set = Architecture.parse_config("auto64", "linux")
@@ -68,7 +71,7 @@ def test_arch_auto64(platform_machine):
assert arch_set == expected[machine_name]
def test_arch_auto32(platform_machine):
def test_arch_auto32(platform_machine: tuple[str, str]) -> None:
_, machine_name = platform_machine
arch_set = Architecture.parse_config("auto32", "linux")
@@ -83,7 +86,7 @@ def test_arch_auto32(platform_machine):
assert arch_set == expected[machine_name]
def test_arch_auto_no_aarch32(monkeypatch):
def test_arch_auto_no_aarch32(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(sys, "platform", "linux")
monkeypatch.setattr(platform_module, "machine", lambda: "aarch64")
monkeypatch.setattr(shutil, "which", lambda *args, **kwargs: None)
@@ -103,14 +106,14 @@ def test_arch_auto_no_aarch32(monkeypatch):
assert arch_set == set()
def test_arch_native_on_ios(monkeypatch):
def test_arch_native_on_ios(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(sys, "platform", "darwin")
monkeypatch.setattr(platform_module, "machine", lambda: "arm64")
arch_set = Architecture.parse_config("native", platform="ios")
assert arch_set == {Architecture.arm64_iphonesimulator}
def test_arch_auto_on_ios(monkeypatch):
def test_arch_auto_on_ios(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(sys, "platform", "darwin")
monkeypatch.setattr(platform_module, "machine", lambda: "arm64")
arch_set = Architecture.parse_config("auto", platform="ios")
@@ -130,5 +133,7 @@ def test_arch_auto_on_ios(monkeypatch):
("x86", "windows", "macos", None),
],
)
def test_arch_synonym(arch, from_platform, to_platform, expected):
def test_arch_synonym(
arch: str, from_platform: PlatformName, to_platform: PlatformName, expected: str | None
) -> None:
assert arch_synonym(arch, from_platform, to_platform) == expected
+2 -2
View File
@@ -6,7 +6,7 @@ from cibuildwheel.extra import Printable, dump_python_configurations
from cibuildwheel.util import resources
def test_compare_configs():
def test_compare_configs() -> None:
txt = resources.BUILD_PLATFORMS.read_text()
with resources.BUILD_PLATFORMS.open("rb") as f2:
@@ -18,7 +18,7 @@ def test_compare_configs():
assert new_txt == txt
def test_dump_with_Version():
def test_dump_with_Version() -> None:
# MyPy doesn't understand deeply nested dicts correctly
example: dict[str, dict[str, list[dict[str, Printable]]]] = {
"windows": {
+15 -15
View File
@@ -4,7 +4,7 @@ import cibuildwheel.selector
from cibuildwheel.selector import BuildSelector, EnableGroup
def test_build():
def test_build() -> None:
build_selector = BuildSelector(
build_config="cp3*-* *-manylinux*", skip_config="", enable=frozenset([EnableGroup.PyPy])
)
@@ -41,7 +41,7 @@ def test_build():
assert not build_selector("pp311-win_amd64")
def test_build_filter_pre():
def test_build_filter_pre() -> None:
build_selector = BuildSelector(
build_config="cp3*-* *-manylinux*",
skip_config="",
@@ -55,7 +55,7 @@ def test_build_filter_pre():
assert not build_selector("cp313t-manylinux_x86_64")
def test_build_filter_pypy():
def test_build_filter_pypy() -> None:
build_selector = BuildSelector(
build_config="*",
skip_config="",
@@ -67,7 +67,7 @@ def test_build_filter_pypy():
assert not build_selector("pp39-manylinux_x86_64")
def test_build_filter_pypy_eol():
def test_build_filter_pypy_eol() -> None:
build_selector = BuildSelector(
build_config="*",
skip_config="",
@@ -79,7 +79,7 @@ def test_build_filter_pypy_eol():
assert build_selector("pp39-manylinux_x86_64")
def test_build_filter_pypy_all():
def test_build_filter_pypy_all() -> None:
build_selector = BuildSelector(
build_config="*",
skip_config="",
@@ -91,7 +91,7 @@ def test_build_filter_pypy_all():
assert build_selector("pp39-manylinux_x86_64")
def test_build_filter_pyodide_prerelease():
def test_build_filter_pyodide_prerelease() -> None:
build_selector = BuildSelector(
build_config="*",
skip_config="",
@@ -101,7 +101,7 @@ def test_build_filter_pyodide_prerelease():
assert build_selector("cp313-pyodide_wasm32")
def test_build_filter_pyodide():
def test_build_filter_pyodide() -> None:
build_selector = BuildSelector(
build_config="*",
skip_config="",
@@ -111,7 +111,7 @@ def test_build_filter_pyodide():
assert build_selector("cp313-pyodide_wasm32")
def test_skip():
def test_skip() -> None:
build_selector = BuildSelector(
build_config="*",
skip_config="pp310-* cp3?-manylinux_i686 cp36-win* *-win32",
@@ -136,7 +136,7 @@ def test_skip():
assert build_selector("cp37-win_amd64")
def test_build_and_skip():
def test_build_and_skip() -> None:
build_selector = BuildSelector(
build_config="cp36-* cp37-macosx* *-manylinux*",
skip_config="pp37-* cp37-manylinux_i686",
@@ -160,7 +160,7 @@ def test_build_and_skip():
assert not build_selector("cp37-win_amd64")
def test_build_braces():
def test_build_braces() -> None:
build_selector = BuildSelector(build_config="cp{36,37}*", skip_config="")
assert build_selector("cp36-manylinux_x86_64")
@@ -169,7 +169,7 @@ def test_build_braces():
assert not build_selector("cp39-manylinux_x86_64")
def test_build_limited_python():
def test_build_limited_python() -> None:
build_selector = BuildSelector(
build_config="*",
skip_config="",
@@ -190,7 +190,7 @@ def test_build_limited_python():
assert build_selector("gp311_242-win_amd64")
def test_build_limited_python_partial():
def test_build_limited_python_partial() -> None:
build_selector = BuildSelector(
build_config="*", skip_config="", requires_python=SpecifierSet(">=3.6, !=3.7.*")
)
@@ -201,7 +201,7 @@ def test_build_limited_python_partial():
assert build_selector("cp39-manylinux_x86_64")
def test_build_limited_python_patch():
def test_build_limited_python_patch() -> None:
build_selector = BuildSelector(
build_config="*", skip_config="", requires_python=SpecifierSet(">=3.6.8")
)
@@ -210,13 +210,13 @@ def test_build_limited_python_patch():
assert build_selector("cp37-manylinux_x86_64")
def test_build_free_threaded_python():
def test_build_free_threaded_python() -> None:
build_selector = BuildSelector(build_config="*", skip_config="", enable=frozenset(EnableGroup))
assert build_selector("cp313t-manylinux_x86_64")
def test_testing_selector():
def test_testing_selector() -> None:
# This is not a global import to keep pytest from collecting it as a test
test_selector = cibuildwheel.selector.TestSelector(skip_config="cp36-*")
+3 -3
View File
@@ -6,7 +6,7 @@ import pytest
MOCK_PACKAGE_DIR = Path("some_package_dir")
def pytest_addoption(parser):
def pytest_addoption(parser: pytest.Parser) -> None:
parser.addoption("--run-docker", action="store_true", default=False, help="run docker tests")
parser.addoption("--run-podman", action="store_true", default=False, help="run podman tests")
parser.addoption(
@@ -18,13 +18,13 @@ def pytest_addoption(parser):
@pytest.fixture
def fake_package_dir(tmp_path, monkeypatch):
def fake_package_dir(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> list[str]:
"""
Monkey-patch enough for the main() function to run
"""
real_path_exists = Path.exists
def mock_path_exists(path):
def mock_path_exists(path: Path) -> bool:
if str(path).endswith(str(MOCK_PACKAGE_DIR / "setup.py")):
return True
else:
+4 -3
View File
@@ -1,4 +1,5 @@
import ssl
from pathlib import Path
import certifi
import pytest
@@ -8,21 +9,21 @@ from cibuildwheel.util.file import download
DOWNLOAD_URL = "https://cdn.jsdelivr.net/gh/pypa/cibuildwheel@v1.6.3/requirements-dev.txt"
def test_download(monkeypatch, tmp_path):
def test_download(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
monkeypatch.delenv("SSL_CERT_FILE", raising=False)
dest = tmp_path / "file.txt"
download(DOWNLOAD_URL, dest)
assert len(dest.read_bytes()) == 134
def test_download_good_ssl_cert_file(monkeypatch, tmp_path):
def test_download_good_ssl_cert_file(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
monkeypatch.setenv("SSL_CERT_FILE", certifi.where())
dest = tmp_path / "file.txt"
download(DOWNLOAD_URL, dest)
assert len(dest.read_bytes()) == 134
def test_download_bad_ssl_cert_file(monkeypatch, tmp_path):
def test_download_bad_ssl_cert_file(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
bad_cafile = tmp_path / "ca.pem"
bad_cafile.write_text("bad certificates")
monkeypatch.setenv("SSL_CERT_FILE", str(bad_cafile))
+11 -11
View File
@@ -7,7 +7,7 @@ from cibuildwheel.environment import parse_environment
PYTHON_ECHO = f"'{sys.executable}' -c \"import sys; print(*sys.argv[1:])\""
def test_basic_parsing():
def test_basic_parsing() -> None:
environment_recipe = parse_environment("VAR=1 VBR=2")
environment_dict = environment_recipe.as_dictionary(prev_environment={})
@@ -15,7 +15,7 @@ def test_basic_parsing():
assert environment_dict == {"VAR": "1", "VBR": "2"}
def test_quotes():
def test_quotes() -> None:
environment_recipe = parse_environment("A=1 VAR=\"1 NOT_A_VAR=2\" VBR='vbr'")
environment_dict = environment_recipe.as_dictionary(prev_environment={})
@@ -23,7 +23,7 @@ def test_quotes():
assert environment_dict == {"A": "1", "VAR": "1 NOT_A_VAR=2", "VBR": "vbr"}
def test_inheritance():
def test_inheritance() -> None:
environment_recipe = parse_environment("PATH=$PATH:/usr/local/bin")
environment_dict = environment_recipe.as_dictionary(prev_environment={"PATH": "/usr/bin"})
@@ -31,7 +31,7 @@ def test_inheritance():
assert environment_dict == {"PATH": "/usr/bin:/usr/local/bin"}
def test_shell_eval():
def test_shell_eval() -> None:
environment_recipe = parse_environment(f'VAR="$({PYTHON_ECHO} "a test" string)"')
env_copy = os.environ.copy()
@@ -42,7 +42,7 @@ def test_shell_eval():
assert environment_dict["VAR"] == "a test string"
def test_shell_eval_and_env():
def test_shell_eval_and_env() -> None:
environment_recipe = parse_environment(f'VAR="$({PYTHON_ECHO} "$PREV_VAR" string)"')
prev_environment = {**os.environ, "PREV_VAR": "1 2 3"}
@@ -51,7 +51,7 @@ def test_shell_eval_and_env():
assert environment_dict == {**prev_environment, "VAR": "1 2 3 string"}
def test_empty_var():
def test_empty_var() -> None:
environment_recipe = parse_environment("CFLAGS=")
environment_dict = environment_recipe.as_dictionary(prev_environment={"CFLAGS": "-Wall"})
@@ -59,7 +59,7 @@ def test_empty_var():
assert environment_dict == {"CFLAGS": ""}
def test_no_vars():
def test_no_vars() -> None:
environment_recipe = parse_environment("")
environment_dict = environment_recipe.as_dictionary(prev_environment={})
@@ -67,7 +67,7 @@ def test_no_vars():
assert environment_dict == {}
def test_no_vars_pass_through():
def test_no_vars_pass_through() -> None:
environment_recipe = parse_environment("")
environment_dict = environment_recipe.as_dictionary(
@@ -77,7 +77,7 @@ def test_no_vars_pass_through():
assert environment_dict == {"CIBUILDWHEEL": "awesome"}
def test_operators_inside_eval():
def test_operators_inside_eval() -> None:
environment_recipe = parse_environment(
f'SOMETHING="$({PYTHON_ECHO} a; {PYTHON_ECHO} b; {PYTHON_ECHO} c)"'
)
@@ -88,7 +88,7 @@ def test_operators_inside_eval():
assert environment_dict.get("SOMETHING") == "a\nb\nc"
def test_substitution_with_backslash():
def test_substitution_with_backslash() -> None:
environment_recipe = parse_environment('PATH2="somewhere_else;$PATH1"')
environment_dict = environment_recipe.as_dictionary(prev_environment={"PATH1": "c:\\folder\\"})
@@ -96,7 +96,7 @@ def test_substitution_with_backslash():
assert environment_dict.get("PATH2") == "somewhere_else;c:\\folder\\"
def test_awkwardly_quoted_variable():
def test_awkwardly_quoted_variable() -> None:
environment_recipe = parse_environment(
f'VAR2=something"like this""$VAR1"$VAR1$({PYTHON_ECHO} "there is more")"$({PYTHON_ECHO} "and more!")"'
)
+17 -6
View File
@@ -1,6 +1,7 @@
import errno
import shutil
import sys
from pathlib import Path
import pytest
@@ -8,7 +9,9 @@ import cibuildwheel.__main__ as main_module
from cibuildwheel.__main__ import main
def test_clean_cache_when_cache_exists(tmp_path, monkeypatch, capfd):
def test_clean_cache_when_cache_exists(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capfd: pytest.CaptureFixture[str]
) -> None:
fake_cache_dir = (tmp_path / "cibw_cache").resolve()
monkeypatch.setattr(main_module, "CIBW_CACHE_PATH", fake_cache_dir)
@@ -40,7 +43,9 @@ def test_clean_cache_when_cache_exists(tmp_path, monkeypatch, capfd):
assert not fake_cache_dir.exists()
def test_clean_cache_when_cache_does_not_exist(tmp_path, monkeypatch, capfd):
def test_clean_cache_when_cache_does_not_exist(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capfd: pytest.CaptureFixture[str]
) -> None:
fake_cache_dir = (tmp_path / "nonexistent_cache").resolve()
monkeypatch.setattr(main_module, "CIBW_CACHE_PATH", fake_cache_dir)
@@ -55,7 +60,9 @@ def test_clean_cache_when_cache_does_not_exist(tmp_path, monkeypatch, capfd):
assert f"Cache directory does not exist: {fake_cache_dir}" in out
def test_clean_cache_with_error(tmp_path, monkeypatch, capfd):
def test_clean_cache_with_error(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capfd: pytest.CaptureFixture[str]
) -> None:
fake_cache_dir = (tmp_path / "cibw_cache").resolve()
monkeypatch.setattr(main_module, "CIBW_CACHE_PATH", fake_cache_dir)
@@ -73,7 +80,7 @@ def test_clean_cache_with_error(tmp_path, monkeypatch, capfd):
monkeypatch.setattr(sys, "argv", ["cibuildwheel", "--clean-cache"])
def fake_rmtree(path): # noqa: ARG001
def fake_rmtree(path: Path) -> None: # noqa: ARG001
raise OSError(errno.EACCES, "Permission denied")
monkeypatch.setattr(shutil, "rmtree", fake_rmtree)
@@ -88,7 +95,9 @@ def test_clean_cache_with_error(tmp_path, monkeypatch, capfd):
assert "Error clearing cache:" in err
def test_clean_cache_without_sentinel(tmp_path, monkeypatch, capfd):
def test_clean_cache_without_sentinel(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capfd: pytest.CaptureFixture[str]
) -> None:
fake_cache_dir = (tmp_path / "not_a_cache").resolve()
monkeypatch.setattr(main_module, "CIBW_CACHE_PATH", fake_cache_dir)
@@ -106,7 +115,9 @@ def test_clean_cache_without_sentinel(tmp_path, monkeypatch, capfd):
assert fake_cache_dir.exists()
def test_clean_cache_with_invalid_signature(tmp_path, monkeypatch, capfd):
def test_clean_cache_with_invalid_signature(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capfd: pytest.CaptureFixture[str]
) -> None:
fake_cache_dir = (tmp_path / "fake_cache").resolve()
monkeypatch.setattr(main_module, "CIBW_CACHE_PATH", fake_cache_dir)
+15 -13
View File
@@ -2,7 +2,9 @@ import contextlib
import platform as platform_module
import subprocess
import sys
from collections.abc import Generator, Iterator
from pathlib import Path
from typing import Any
import pytest
@@ -15,27 +17,27 @@ from cibuildwheel.util import file
class ArgsInterceptor:
def __init__(self) -> None:
self.call_count = 0
self.args: tuple[object, ...] | None = None
self.kwargs: dict[str, object] | None = None
self.args: tuple[Any, ...] = ()
self.kwargs: dict[str, Any] = {}
def __call__(self, *args: object, **kwargs: object) -> None:
def __call__(self, *args: Any, **kwargs: Any) -> None:
self.call_count += 1
self.args = args
self.kwargs = kwargs
@pytest.fixture(autouse=True)
def mock_protection(monkeypatch):
def mock_protection(monkeypatch: pytest.MonkeyPatch) -> None:
"""
Ensure that a unit test will never actually run a cibuildwheel 'build'
function, which shouldn't be run on a developer's machine
"""
def fail_on_call(*args, **kwargs):
def fail_on_call(*args: object, **kwargs: object) -> None:
msg = "This should never be called"
raise RuntimeError(msg)
def ignore_call(*args, **kwargs):
def ignore_call(*args: object, **kwargs: object) -> None:
pass
monkeypatch.setattr(subprocess, "Popen", fail_on_call)
@@ -49,27 +51,27 @@ def mock_protection(monkeypatch):
@pytest.fixture(autouse=True)
def fake_package_dir_autouse(fake_package_dir):
def fake_package_dir_autouse(fake_package_dir: list[str]) -> None:
pass
@pytest.fixture(autouse=True)
def disable_print_wheels(monkeypatch):
def disable_print_wheels(monkeypatch: pytest.MonkeyPatch) -> None:
@contextlib.contextmanager
def empty_cm(*args, **kwargs):
def empty_cm(*args: object, **kwargs: object) -> Generator[None, None, None]:
yield
monkeypatch.setattr(Logger, "print_summary", empty_cm)
@pytest.fixture
def allow_empty(monkeypatch, fake_package_dir):
def allow_empty(monkeypatch: pytest.MonkeyPatch, fake_package_dir: list[str]) -> None:
monkeypatch.setattr(sys, "argv", [*fake_package_dir, "--allow-empty"])
@pytest.fixture(params=["linux", "macos", "windows"])
def platform(request, monkeypatch):
platform_value = request.param
def platform(request: pytest.FixtureRequest, monkeypatch: pytest.MonkeyPatch) -> str:
platform_value: str = request.param
monkeypatch.setenv("CIBW_PLATFORM", platform_value)
if platform_value == "windows":
@@ -84,7 +86,7 @@ def platform(request, monkeypatch):
@pytest.fixture
def intercepted_build_args(monkeypatch):
def intercepted_build_args(monkeypatch: pytest.MonkeyPatch) -> Iterator[ArgsInterceptor]:
intercepted = ArgsInterceptor()
monkeypatch.setattr(android, "build", intercepted)
+127 -35
View File
@@ -1,7 +1,9 @@
import sys
import tomllib
from collections.abc import Mapping
from fnmatch import fnmatch
from pathlib import Path
from typing import TYPE_CHECKING
import pytest
@@ -13,10 +15,15 @@ from cibuildwheel.selector import BuildSelector, EnableGroup
from cibuildwheel.util import resources
from cibuildwheel.util.packaging import DependencyConstraints
if TYPE_CHECKING:
from .conftest import ArgsInterceptor
# CIBW_PLATFORM is tested in main_platform_test.py
def test_old_free_threaded(monkeypatch, capsys):
def test_old_free_threaded(
monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
monkeypatch.setenv("CIBW_FREE_THREADED_SUPPORT", "ON")
with pytest.raises(SystemExit):
@@ -29,7 +36,9 @@ def test_old_free_threaded(monkeypatch, capsys):
@pytest.mark.usefixtures("platform")
def test_output_dir(intercepted_build_args, monkeypatch):
def test_output_dir(
intercepted_build_args: "ArgsInterceptor", monkeypatch: pytest.MonkeyPatch
) -> None:
OUTPUT_DIR = Path("some_output_dir")
monkeypatch.setenv("CIBW_OUTPUT_DIR", str(OUTPUT_DIR))
@@ -40,7 +49,7 @@ def test_output_dir(intercepted_build_args, monkeypatch):
@pytest.mark.usefixtures("platform")
def test_output_dir_default(intercepted_build_args):
def test_output_dir_default(intercepted_build_args: "ArgsInterceptor") -> None:
main()
assert intercepted_build_args.args[0].globals.output_dir == Path("wheelhouse").resolve()
@@ -48,7 +57,11 @@ def test_output_dir_default(intercepted_build_args):
@pytest.mark.usefixtures("platform")
@pytest.mark.parametrize("also_set_environment", [False, True])
def test_output_dir_argument(also_set_environment, intercepted_build_args, monkeypatch):
def test_output_dir_argument(
also_set_environment: bool,
intercepted_build_args: "ArgsInterceptor",
monkeypatch: pytest.MonkeyPatch,
) -> None:
OUTPUT_DIR = Path("some_output_dir")
monkeypatch.setattr(sys, "argv", [*sys.argv, "--output-dir", str(OUTPUT_DIR)])
@@ -61,7 +74,9 @@ def test_output_dir_argument(also_set_environment, intercepted_build_args, monke
@pytest.mark.usefixtures("platform", "allow_empty")
def test_build_selector(intercepted_build_args, monkeypatch):
def test_build_selector(
intercepted_build_args: "ArgsInterceptor", monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setenv("CIBW_BUILD", "cp313-*")
monkeypatch.setenv("CIBW_SKIP", "cp39-*")
@@ -76,7 +91,9 @@ def test_build_selector(intercepted_build_args, monkeypatch):
@pytest.mark.usefixtures("platform", "allow_empty")
def test_invalid_build_selector(monkeypatch, capsys):
def test_invalid_build_selector(
monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
monkeypatch.setenv("CIBW_BUILD", "invalid")
with pytest.raises(SystemExit) as e:
@@ -95,7 +112,12 @@ def test_invalid_build_selector(monkeypatch, capsys):
],
)
@pytest.mark.usefixtures("platform", "intercepted_build_args")
def test_invalid_skip_selector(monkeypatch, capsys, option_name, option_env_var):
def test_invalid_skip_selector(
monkeypatch: pytest.MonkeyPatch,
capsys: pytest.CaptureFixture[str],
option_name: str,
option_env_var: str,
) -> None:
monkeypatch.setenv(option_env_var, "invalid")
main()
@@ -109,7 +131,9 @@ def test_invalid_skip_selector(monkeypatch, capsys, option_name, option_env_var)
"selector", ["*-macosx_universal2:arm64", "*-macosx_universal2:x86_64", "*-macosx_arm64"]
)
@pytest.mark.usefixtures("platform", "intercepted_build_args")
def test_valid_test_skip_selector(monkeypatch, capsys, selector):
def test_valid_test_skip_selector(
monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str], selector: str
) -> None:
monkeypatch.setenv("CIBW_TEST_SKIP", selector)
main()
@@ -121,7 +145,9 @@ def test_valid_test_skip_selector(monkeypatch, capsys, selector):
@pytest.mark.parametrize("selector", ["*-macosx_universal2:invalid", "*-macosx_arm64:arm64"])
@pytest.mark.usefixtures("platform", "intercepted_build_args")
def test_invalid_test_skip_selector(monkeypatch, capsys, selector):
def test_invalid_test_skip_selector(
monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str], selector: str
) -> None:
monkeypatch.setenv("CIBW_TEST_SKIP", selector)
main()
@@ -132,7 +158,7 @@ def test_invalid_test_skip_selector(monkeypatch, capsys, selector):
@pytest.mark.usefixtures("platform", "intercepted_build_args")
def test_empty_selector(monkeypatch):
def test_empty_selector(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setenv("CIBW_SKIP", "*")
with pytest.raises(SystemExit) as e:
@@ -161,8 +187,13 @@ def test_empty_selector(monkeypatch):
],
)
def test_manylinux_images(
architecture, image, full_image, platform, intercepted_build_args, monkeypatch
):
architecture: str,
image: str | None,
full_image: str,
platform: str,
intercepted_build_args: "ArgsInterceptor",
monkeypatch: pytest.MonkeyPatch,
) -> None:
if image is not None:
monkeypatch.setenv("CIBW_MANYLINUX_" + architecture.upper() + "_IMAGE", image)
@@ -194,8 +225,12 @@ def get_default_repair_command(platform: str) -> str:
@pytest.mark.parametrize("repair_command", [None, "repair", "repair -w {dest_dir} {wheel}"])
@pytest.mark.parametrize("platform_specific", [False, True])
def test_repair_command(
repair_command, platform_specific, platform, intercepted_build_args, monkeypatch
):
repair_command: str | None,
platform_specific: bool,
platform: str,
intercepted_build_args: "ArgsInterceptor",
monkeypatch: pytest.MonkeyPatch,
) -> None:
if repair_command is not None:
if platform_specific:
monkeypatch.setenv("CIBW_REPAIR_WHEEL_COMMAND_" + platform.upper(), repair_command)
@@ -216,7 +251,13 @@ def test_repair_command(
[{}, {"something": "value"}, {"something": "value", "something_else": "other_value"}],
)
@pytest.mark.parametrize("platform_specific", [False, True])
def test_environment(environment, platform_specific, platform, intercepted_build_args, monkeypatch):
def test_environment(
environment: Mapping[str, str],
platform_specific: bool,
platform: str,
intercepted_build_args: "ArgsInterceptor",
monkeypatch: pytest.MonkeyPatch,
) -> None:
env_string = " ".join(f"{k}={v}" for k, v in environment.items())
if platform_specific:
monkeypatch.setenv("CIBW_ENVIRONMENT_" + platform.upper(), env_string)
@@ -236,8 +277,12 @@ def test_environment(environment, platform_specific, platform, intercepted_build
@pytest.mark.parametrize("test_requires", [None, "requirement other_requirement"])
@pytest.mark.parametrize("platform_specific", [False, True])
def test_test_requires(
test_requires, platform_specific, platform, intercepted_build_args, monkeypatch
):
test_requires: str | None,
platform_specific: bool,
platform: str,
intercepted_build_args: "ArgsInterceptor",
monkeypatch: pytest.MonkeyPatch,
) -> None:
if test_requires is not None:
if platform_specific:
monkeypatch.setenv("CIBW_TEST_REQUIRES_" + platform.upper(), test_requires)
@@ -254,7 +299,13 @@ def test_test_requires(
@pytest.mark.parametrize("test_extras", [None, "extras"])
@pytest.mark.parametrize("platform_specific", [False, True])
def test_test_extras(test_extras, platform_specific, platform, intercepted_build_args, monkeypatch):
def test_test_extras(
test_extras: str | None,
platform_specific: bool,
platform: str,
intercepted_build_args: "ArgsInterceptor",
monkeypatch: pytest.MonkeyPatch,
) -> None:
if test_extras is not None:
if platform_specific:
monkeypatch.setenv("CIBW_TEST_EXTRAS_" + platform.upper(), test_extras)
@@ -272,8 +323,12 @@ def test_test_extras(test_extras, platform_specific, platform, intercepted_build
@pytest.mark.parametrize("test_command", [None, "test --command"])
@pytest.mark.parametrize("platform_specific", [False, True])
def test_test_command(
test_command, platform_specific, platform, intercepted_build_args, monkeypatch
):
test_command: str | None,
platform_specific: bool,
platform: str,
intercepted_build_args: "ArgsInterceptor",
monkeypatch: pytest.MonkeyPatch,
) -> None:
if test_command is not None:
if platform_specific:
monkeypatch.setenv("CIBW_TEST_COMMAND_" + platform.upper(), test_command)
@@ -291,8 +346,12 @@ def test_test_command(
@pytest.mark.parametrize("before_build", [None, "before --build"])
@pytest.mark.parametrize("platform_specific", [False, True])
def test_before_build(
before_build, platform_specific, platform, intercepted_build_args, monkeypatch
):
before_build: str | None,
platform_specific: bool,
platform: str,
intercepted_build_args: "ArgsInterceptor",
monkeypatch: pytest.MonkeyPatch,
) -> None:
if before_build is not None:
if platform_specific:
monkeypatch.setenv("CIBW_BEFORE_BUILD_" + platform.upper(), before_build)
@@ -309,8 +368,12 @@ def test_before_build(
@pytest.mark.parametrize("build_verbosity", [None, 0, 2, -2, 4, -4])
@pytest.mark.parametrize("platform_specific", [False, True])
def test_build_verbosity(
build_verbosity, platform_specific, platform, intercepted_build_args, monkeypatch
):
build_verbosity: int | None,
platform_specific: bool,
platform: str,
intercepted_build_args: "ArgsInterceptor",
monkeypatch: pytest.MonkeyPatch,
) -> None:
if build_verbosity is not None:
if platform_specific:
monkeypatch.setenv("CIBW_BUILD_VERBOSITY_" + platform.upper(), str(build_verbosity))
@@ -326,7 +389,12 @@ def test_build_verbosity(
@pytest.mark.parametrize("platform_specific", [False, True])
def test_config_settings(platform_specific, platform, intercepted_build_args, monkeypatch):
def test_config_settings(
platform_specific: bool,
platform: str,
intercepted_build_args: "ArgsInterceptor",
monkeypatch: pytest.MonkeyPatch,
) -> None:
config_settings = (
'setting=value setting=value2 triplet=1 triplet=2 triplet=3 other="something else"'
)
@@ -376,7 +444,9 @@ def test_config_settings(platform_specific, platform, intercepted_build_args, mo
],
)
@pytest.mark.usefixtures("platform", "intercepted_build_args", "allow_empty")
def test_build_selector_deprecated_error(monkeypatch, selector, pattern, capsys):
def test_build_selector_deprecated_error(
monkeypatch: pytest.MonkeyPatch, selector: str, pattern: str, capsys: pytest.CaptureFixture[str]
) -> None:
monkeypatch.setenv(selector, pattern)
monkeypatch.delenv("CIBW_ENABLE", raising=False)
@@ -396,7 +466,13 @@ def test_build_selector_deprecated_error(monkeypatch, selector, pattern, capsys)
@pytest.mark.parametrize("before_all", ["", None, "test text"])
@pytest.mark.parametrize("platform_specific", [False, True])
def test_before_all(before_all, platform_specific, platform, intercepted_build_args, monkeypatch):
def test_before_all(
before_all: str | None,
platform_specific: bool,
platform: str,
intercepted_build_args: "ArgsInterceptor",
monkeypatch: pytest.MonkeyPatch,
) -> None:
if before_all is not None:
if platform_specific:
monkeypatch.setenv("CIBW_BEFORE_ALL_" + platform.upper(), before_all)
@@ -417,8 +493,13 @@ def test_before_all(before_all, platform_specific, platform, intercepted_build_a
)
@pytest.mark.parametrize("platform_specific", [False, True])
def test_dependency_versions(
dependency_versions, platform_specific, platform, intercepted_build_args, monkeypatch, tmp_path
):
dependency_versions: str | None,
platform_specific: bool,
platform: str,
intercepted_build_args: "ArgsInterceptor",
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
option_value = dependency_versions
if dependency_versions == "FILE":
@@ -443,13 +524,16 @@ def test_dependency_versions(
assert dependency_constraints == DependencyConstraints.latest()
elif dependency_versions == "FILE":
assert dependency_constraints.base_file_path
assert option_value is not None
assert dependency_constraints.base_file_path.samefile(Path(option_value))
elif dependency_versions.startswith("packages:"):
assert dependency_constraints.packages == ["pip==21.0.0"]
@pytest.mark.parametrize("method", ["unset", "command_line", "env_var"])
def test_debug_traceback(monkeypatch, method, capfd):
def test_debug_traceback(
monkeypatch: pytest.MonkeyPatch, method: str, capfd: pytest.CaptureFixture[str]
) -> None:
if method == "command_line":
monkeypatch.setattr(sys, "argv", [*sys.argv, "--debug-traceback"])
elif method == "env_var":
@@ -471,7 +555,9 @@ def test_debug_traceback(monkeypatch, method, capfd):
@pytest.mark.parametrize("method", ["unset", "command_line", "env_var"])
def test_enable(method, intercepted_build_args, monkeypatch):
def test_enable(
method: str, intercepted_build_args: "ArgsInterceptor", monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.delenv("CIBW_ENABLE", raising=False)
if method == "command_line":
@@ -489,7 +575,9 @@ def test_enable(method, intercepted_build_args, monkeypatch):
assert enable_groups == frozenset([EnableGroup.PyPy, EnableGroup.GraalPy])
def test_enable_all(intercepted_build_args, monkeypatch):
def test_enable_all(
intercepted_build_args: "ArgsInterceptor", monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setattr(sys, "argv", [*sys.argv, "--enable", "all"])
main()
@@ -498,7 +586,9 @@ def test_enable_all(intercepted_build_args, monkeypatch):
assert enable_groups == EnableGroup.all_groups()
def test_enable_arg_inherits(intercepted_build_args, monkeypatch):
def test_enable_arg_inherits(
intercepted_build_args: "ArgsInterceptor", monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setenv("CIBW_ENABLE", "pypy graalpy")
monkeypatch.setattr(sys, "argv", [*sys.argv, "--enable", "cpython-prerelease"])
@@ -511,7 +601,9 @@ def test_enable_arg_inherits(intercepted_build_args, monkeypatch):
)
def test_enable_arg_error_message(monkeypatch, capsys):
def test_enable_arg_error_message(
monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
monkeypatch.setattr(sys, "argv", [*sys.argv, "--enable", "invalid_group"])
with pytest.raises(SystemExit) as ex:
@@ -522,7 +614,7 @@ def test_enable_arg_error_message(monkeypatch, capsys):
assert "Valid group names are:" in err
def test_defaults(platform, intercepted_build_args):
def test_defaults(platform: str, intercepted_build_args: "ArgsInterceptor") -> None:
main()
build_options: BuildOptions = intercepted_build_args.args[0].build_options(identifier=None)
+60 -19
View File
@@ -5,12 +5,18 @@ import pytest
from cibuildwheel.__main__ import main
from cibuildwheel.architecture import Architecture
from cibuildwheel.selector import EnableGroup
from cibuildwheel.typing import PlatformName
from ..conftest import MOCK_PACKAGE_DIR
from .conftest import ArgsInterceptor
@pytest.mark.parametrize("option_value", [None, "auto", ""])
def test_platform_unset_or_auto(monkeypatch, intercepted_build_args, option_value):
def test_platform_unset_or_auto(
monkeypatch: pytest.MonkeyPatch,
intercepted_build_args: ArgsInterceptor,
option_value: str | None,
) -> None:
if option_value is None:
monkeypatch.delenv("CIBW_PLATFORM", raising=False)
else:
@@ -31,7 +37,9 @@ def test_platform_unset_or_auto(monkeypatch, intercepted_build_args, option_valu
pytest.fail(f"Unknown platform: {sys.platform}")
def test_unknown_platform_on_ci(monkeypatch, capsys):
def test_unknown_platform_on_ci(
monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
monkeypatch.setenv("CI", "true")
monkeypatch.setattr(sys, "platform", "nonexistent")
monkeypatch.delenv("CIBW_PLATFORM", raising=False)
@@ -44,7 +52,9 @@ def test_unknown_platform_on_ci(monkeypatch, capsys):
assert 'Unable to detect platform from "sys.platform"' in err
def test_unknown_platform(monkeypatch, capsys):
def test_unknown_platform(
monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
monkeypatch.setenv("CIBW_PLATFORM", "nonexistent")
with pytest.raises(SystemExit) as exit:
@@ -55,7 +65,9 @@ def test_unknown_platform(monkeypatch, capsys):
assert "Unsupported platform: nonexistent" in err
def test_platform_argument(platform, intercepted_build_args, monkeypatch):
def test_platform_argument(
platform: str, intercepted_build_args: ArgsInterceptor, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setenv("CIBW_PLATFORM", "nonexistent")
monkeypatch.setattr(sys, "argv", [*sys.argv, "--platform", platform])
@@ -67,14 +79,14 @@ def test_platform_argument(platform, intercepted_build_args, monkeypatch):
@pytest.mark.usefixtures("platform")
def test_platform_environment(intercepted_build_args):
def test_platform_environment(intercepted_build_args: ArgsInterceptor) -> None:
main()
options = intercepted_build_args.args[0]
assert options.globals.package_dir == MOCK_PACKAGE_DIR.resolve()
def test_archs_default(platform, intercepted_build_args):
def test_archs_default(platform: str, intercepted_build_args: ArgsInterceptor) -> None:
main()
options = intercepted_build_args.args[0]
@@ -87,7 +99,12 @@ def test_archs_default(platform, intercepted_build_args):
@pytest.mark.parametrize("use_env_var", [False, True])
def test_archs_argument(platform, intercepted_build_args, monkeypatch, use_env_var):
def test_archs_argument(
platform: str,
intercepted_build_args: ArgsInterceptor,
monkeypatch: pytest.MonkeyPatch,
use_env_var: bool,
) -> None:
if use_env_var:
monkeypatch.setenv("CIBW_ARCHS", "ppc64le")
else:
@@ -105,7 +122,9 @@ def test_archs_argument(platform, intercepted_build_args, monkeypatch, use_env_v
assert options.globals.architectures == {Architecture.ppc64le}
def test_archs_platform_specific(platform, intercepted_build_args, monkeypatch):
def test_archs_platform_specific(
platform: str, intercepted_build_args: ArgsInterceptor, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setenv("CIBW_ARCHS", "unused")
monkeypatch.setenv("CIBW_ARCHS_LINUX", "ppc64le")
monkeypatch.setenv("CIBW_ARCHS_WINDOWS", "x86")
@@ -122,7 +141,9 @@ def test_archs_platform_specific(platform, intercepted_build_args, monkeypatch):
assert options.globals.architectures == {Architecture.x86_64}
def test_archs_platform_native(platform, intercepted_build_args, monkeypatch):
def test_archs_platform_native(
platform: str, intercepted_build_args: ArgsInterceptor, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setenv("CIBW_ARCHS", "native")
main()
@@ -134,7 +155,9 @@ def test_archs_platform_native(platform, intercepted_build_args, monkeypatch):
assert options.globals.architectures == {Architecture.AMD64}
def test_archs_platform_auto64(platform, intercepted_build_args, monkeypatch):
def test_archs_platform_auto64(
platform: str, intercepted_build_args: ArgsInterceptor, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setenv("CIBW_ARCHS", "auto64")
main()
@@ -146,7 +169,9 @@ def test_archs_platform_auto64(platform, intercepted_build_args, monkeypatch):
assert options.globals.architectures == {Architecture.AMD64}
def test_archs_platform_auto32(platform, intercepted_build_args, monkeypatch):
def test_archs_platform_auto32(
platform: str, intercepted_build_args: ArgsInterceptor, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setenv("CIBW_ARCHS", "auto32")
if platform == "macos":
@@ -165,7 +190,9 @@ def test_archs_platform_auto32(platform, intercepted_build_args, monkeypatch):
assert options.globals.architectures == {Architecture.x86}
def test_archs_platform_all(platform, intercepted_build_args, monkeypatch):
def test_archs_platform_all(
platform: str, intercepted_build_args: ArgsInterceptor, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setenv("CIBW_ARCHS", "all")
main()
@@ -204,7 +231,12 @@ def test_archs_platform_all(platform, intercepted_build_args, monkeypatch):
("cp311-macosx_x86_64", "macos"),
),
)
def test_only_argument(intercepted_build_args, monkeypatch, only, plat):
def test_only_argument(
intercepted_build_args: ArgsInterceptor,
monkeypatch: pytest.MonkeyPatch,
only: str,
plat: PlatformName,
) -> None:
monkeypatch.setenv("CIBW_BUILD", "unused")
monkeypatch.setenv("CIBW_SKIP", "unused")
monkeypatch.setattr(sys, "argv", [*sys.argv, "--only", only])
@@ -220,14 +252,14 @@ def test_only_argument(intercepted_build_args, monkeypatch, only, plat):
@pytest.mark.parametrize("only", ("cp311-manylxinux_x86_64", "some_linux_thing"))
def test_only_failed(monkeypatch, only):
def test_only_failed(monkeypatch: pytest.MonkeyPatch, only: str) -> None:
monkeypatch.setattr(sys, "argv", [*sys.argv, "--only", only])
with pytest.raises(SystemExit):
main()
def test_only_no_platform(monkeypatch):
def test_only_no_platform(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(
sys, "argv", [*sys.argv, "--only", "cp311-manylinux_x86_64", "--platform", "macos"]
)
@@ -236,7 +268,7 @@ def test_only_no_platform(monkeypatch):
main()
def test_only_no_archs(monkeypatch):
def test_only_no_archs(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(
sys, "argv", [*sys.argv, "--only", "cp311-manylinux_x86_64", "--archs", "x86_64"]
)
@@ -254,7 +286,12 @@ def test_only_no_archs(monkeypatch):
("CIBW_PLATFORM", "macos"),
),
)
def test_only_overrides_env_vars(monkeypatch, intercepted_build_args, envvar_name, envvar_value):
def test_only_overrides_env_vars(
monkeypatch: pytest.MonkeyPatch,
intercepted_build_args: ArgsInterceptor,
envvar_name: str,
envvar_value: str,
) -> None:
monkeypatch.setattr(sys, "argv", [*sys.argv, "--only", "cp311-manylinux_x86_64"])
monkeypatch.setenv(envvar_name, envvar_value)
@@ -267,7 +304,9 @@ def test_only_overrides_env_vars(monkeypatch, intercepted_build_args, envvar_nam
assert options.globals.architectures == Architecture.all_archs("linux")
def test_pyodide_on_windows(monkeypatch, capsys):
def test_pyodide_on_windows(
monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
monkeypatch.setattr(sys, "platform", "win32")
monkeypatch.setattr(sys, "argv", [*sys.argv, "--only", "cp312-pyodide_wasm32"])
@@ -280,7 +319,9 @@ def test_pyodide_on_windows(monkeypatch, capsys):
assert "Building for pyodide is not supported on Windows" in err
def test_empty_archs_platform(platform, intercepted_build_args, monkeypatch):
def test_empty_archs_platform(
platform: PlatformName, intercepted_build_args: ArgsInterceptor, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setenv("CIBW_ARCHS", "")
main()
@@ -1,14 +1,17 @@
import sys
import textwrap
from pathlib import Path
import pytest
from packaging.specifiers import SpecifierSet
from cibuildwheel.__main__ import main
from .conftest import ArgsInterceptor
@pytest.fixture(autouse=True)
def fake_package_dir(monkeypatch, tmp_path):
def fake_package_dir(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> Path:
"""
Set up a fake project
"""
@@ -24,7 +27,7 @@ def fake_package_dir(monkeypatch, tmp_path):
@pytest.mark.usefixtures("platform")
def test_no_override(intercepted_build_args):
def test_no_override(intercepted_build_args: ArgsInterceptor) -> None:
main()
options = intercepted_build_args.args[0]
@@ -37,7 +40,9 @@ def test_no_override(intercepted_build_args):
@pytest.mark.usefixtures("platform")
def test_override_env(monkeypatch, intercepted_build_args):
def test_override_env(
monkeypatch: pytest.MonkeyPatch, intercepted_build_args: ArgsInterceptor
) -> None:
monkeypatch.setenv("CIBW_PROJECT_REQUIRES_PYTHON", ">=3.8")
main()
@@ -52,7 +57,9 @@ def test_override_env(monkeypatch, intercepted_build_args):
@pytest.mark.usefixtures("platform")
def test_override_setup_cfg(intercepted_build_args, fake_package_dir):
def test_override_setup_cfg(
intercepted_build_args: ArgsInterceptor, fake_package_dir: Path
) -> None:
fake_package_dir.joinpath("setup.cfg").write_text(
textwrap.dedent(
"""
@@ -74,7 +81,9 @@ def test_override_setup_cfg(intercepted_build_args, fake_package_dir):
@pytest.mark.usefixtures("platform")
def test_override_pyproject_toml(intercepted_build_args, fake_package_dir):
def test_override_pyproject_toml(
intercepted_build_args: ArgsInterceptor, fake_package_dir: Path
) -> None:
fake_package_dir.joinpath("pyproject.toml").write_text(
textwrap.dedent(
"""
@@ -96,7 +105,9 @@ def test_override_pyproject_toml(intercepted_build_args, fake_package_dir):
@pytest.mark.usefixtures("platform")
def test_override_setup_py_simple(intercepted_build_args, fake_package_dir):
def test_override_setup_py_simple(
intercepted_build_args: ArgsInterceptor, fake_package_dir: Path
) -> None:
fake_package_dir.joinpath("setup.py").write_text(
textwrap.dedent(
"""
+26 -15
View File
@@ -1,3 +1,4 @@
import contextlib
import json
import os
import random
@@ -6,6 +7,7 @@ import subprocess
import sys
import textwrap
import time
from collections.abc import Iterator
from contextlib import nullcontext
from pathlib import Path, PurePath, PurePosixPath
@@ -34,7 +36,7 @@ PODMAN = OCIContainerEngineConfig(name="podman")
@pytest.fixture(params=["docker", "podman"], scope="module")
def container_engine(request):
def container_engine(request: pytest.FixtureRequest) -> Iterator[OCIContainerEngineConfig]:
if request.param == "docker" and not request.config.getoption("--run-docker"):
pytest.skip("need --run-docker option to run")
if request.param == "podman" and not request.config.getoption("--run-podman"):
@@ -63,21 +65,21 @@ def container_engine(request):
# Tests
def test_simple(container_engine):
def test_simple(container_engine: OCIContainerEngineConfig) -> None:
with OCIContainer(
engine=container_engine, image=DEFAULT_IMAGE, oci_platform=DEFAULT_OCI_PLATFORM
) as container:
assert container.call(["echo", "hello"], capture_output=True) == "hello\n"
def test_no_lf(container_engine):
def test_no_lf(container_engine: OCIContainerEngineConfig) -> None:
with OCIContainer(
engine=container_engine, image=DEFAULT_IMAGE, oci_platform=DEFAULT_OCI_PLATFORM
) as container:
assert container.call(["printf", "hello"], capture_output=True) == "hello"
def test_debug_info(container_engine):
def test_debug_info(container_engine: OCIContainerEngineConfig) -> None:
container = OCIContainer(
engine=container_engine, image=DEFAULT_IMAGE, oci_platform=DEFAULT_OCI_PLATFORM
)
@@ -86,7 +88,7 @@ def test_debug_info(container_engine):
pass
def test_environment(container_engine):
def test_environment(container_engine: OCIContainerEngineConfig) -> None:
with OCIContainer(
engine=container_engine, image=DEFAULT_IMAGE, oci_platform=DEFAULT_OCI_PLATFORM
) as container:
@@ -98,7 +100,9 @@ def test_environment(container_engine):
)
def test_environment_pass(container_engine, monkeypatch):
def test_environment_pass(
container_engine: OCIContainerEngineConfig, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setenv("CIBUILDWHEEL", "1")
monkeypatch.setenv("SOURCE_DATE_EPOCH", "1489957071")
with OCIContainer(
@@ -111,7 +115,7 @@ def test_environment_pass(container_engine, monkeypatch):
)
def test_cwd(container_engine):
def test_cwd(container_engine: OCIContainerEngineConfig) -> None:
with OCIContainer(
engine=container_engine,
image=DEFAULT_IMAGE,
@@ -122,7 +126,7 @@ def test_cwd(container_engine):
assert container.call(["pwd"], capture_output=True, cwd="/opt") == "/opt\n"
def test_container_removed(container_engine):
def test_container_removed(container_engine: OCIContainerEngineConfig) -> None:
# test is flaky on some platforms, implement retry for 5 second
timeout = 50 # * 100 ms = 5s
with OCIContainer(
@@ -157,7 +161,7 @@ def test_container_removed(container_engine):
assert container_name not in docker_containers_listing
def test_large_environment(container_engine):
def test_large_environment(container_engine: OCIContainerEngineConfig) -> None:
# max environment variable size is 128kB
long_env_var_length = 127 * 1024
large_environment = {
@@ -177,7 +181,7 @@ def test_large_environment(container_engine):
)
def test_binary_output(container_engine):
def test_binary_output(container_engine: OCIContainerEngineConfig) -> None:
with OCIContainer(
engine=container_engine, image=DEFAULT_IMAGE, oci_platform=DEFAULT_OCI_PLATFORM
) as container:
@@ -472,7 +476,9 @@ def test_create_args_volume(tmp_path: Path, container_engine: OCIContainerEngine
),
],
)
def test_parse_engine_config(config, name, create_args, capsys):
def test_parse_engine_config(
config: str, name: str, create_args: tuple[str, ...], capsys: pytest.CaptureFixture[str]
) -> None:
engine_config = OCIContainerEngineConfig.from_config_string(config)
assert engine_config.name == name
assert engine_config.create_args == create_args
@@ -485,7 +491,7 @@ def test_parse_engine_config(config, name, create_args, capsys):
@pytest.mark.skipif(DEFAULT_OCI_PLATFORM != OCIPlatform.AMD64, reason="Only runs on x86_64")
def test_enforce_32_bit(container_engine):
def test_enforce_32_bit(container_engine: OCIContainerEngineConfig) -> None:
with OCIContainer(
engine=container_engine, image=DEFAULT_IMAGE, oci_platform=OCIPlatform.i386
) as container:
@@ -567,7 +573,7 @@ def test_local_image(
@pytest.mark.parametrize("platform", list(OCIPlatform))
def test_multiarch_image(container_engine, platform):
def test_multiarch_image(container_engine: OCIContainerEngineConfig, platform: OCIPlatform) -> None:
if detect_ci_provider() == CIProvider.travis_ci and DEFAULT_OCI_PLATFORM not in {
OCIPlatform.AMD64,
platform,
@@ -657,8 +663,13 @@ def test_multiarch_image(container_engine, platform):
("podman", '{"Client":{"Version":"2.1.0~rc1"}}', pytest.raises(OCIEngineTooOldError)),
],
)
def test_engine_version(engine_name, version, context, monkeypatch):
def mockcall(*args, **kwargs):
def test_engine_version(
engine_name: str,
version: str | None,
context: contextlib.AbstractContextManager[None],
monkeypatch: pytest.MonkeyPatch,
) -> None:
def mockcall(*args: object, **kwargs: object) -> str:
if version is None:
raise subprocess.CalledProcessError(1, " ".join(str(arg) for arg in args))
return version
+8 -8
View File
@@ -3,7 +3,7 @@ import subprocess
import sys
import typing
from contextlib import contextmanager
from pathlib import PurePosixPath
from pathlib import Path, PurePosixPath
from unittest import mock
import pytest
@@ -18,19 +18,19 @@ ALL_IDS = DEFAULT_IDS | {"cp313t", "pp38", "pp39", "pp310", "pp311", "gp311_242"
@pytest.fixture
def mock_build_container(monkeypatch):
def fail_on_call(*args, **kwargs):
def mock_build_container(monkeypatch: pytest.MonkeyPatch) -> None:
def fail_on_call(*args: object, **kwargs: object) -> None:
msg = "This should never be called"
raise RuntimeError(msg)
def ignore_call(*args, **kwargs):
def ignore_call(*args: object, **kwargs: object) -> None:
pass
@contextmanager
def nullcontext(enter_result=None):
def nullcontext(enter_result: object = None) -> typing.Generator[object, None, None]:
yield enter_result
def ignore_context_call(*args, **kwargs):
def ignore_context_call(*args: object, **kwargs: object) -> typing.ContextManager[object]:
return nullcontext(kwargs)
monkeypatch.setenv("CIBW_PLATFORM", "linux")
@@ -49,7 +49,7 @@ def mock_build_container(monkeypatch):
@pytest.mark.usefixtures("mock_build_container", "fake_package_dir")
def test_build_default_launches(monkeypatch):
def test_build_default_launches(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(sys, "argv", [*sys.argv, "--platform=linux"])
monkeypatch.setenv("CIBW_ARCHS", "auto64 auto32")
monkeypatch.delenv("CIBW_ENABLE", raising=False)
@@ -95,7 +95,7 @@ def test_build_default_launches(monkeypatch):
@pytest.mark.usefixtures("mock_build_container")
def test_build_with_override_launches(monkeypatch, tmp_path):
def test_build_with_override_launches(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
pkg_dir = tmp_path / "cibw_package"
pkg_dir.mkdir()
+7 -5
View File
@@ -48,7 +48,7 @@ manylinux-x86_64-image = "manylinux_2_34"
"""
def test_options_1(tmp_path, monkeypatch):
def test_options_1(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
with tmp_path.joinpath("pyproject.toml").open("w") as f:
f.write(PYPROJECT_1)
@@ -96,7 +96,7 @@ def test_options_1(tmp_path, monkeypatch):
assert local.pyodide_version == "0.28.0"
def test_passthrough(tmp_path, monkeypatch):
def test_passthrough(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
with tmp_path.joinpath("pyproject.toml").open("w") as f:
f.write(PYPROJECT_1)
@@ -126,7 +126,9 @@ def test_passthrough(tmp_path, monkeypatch):
"a trailing backslash \\",
],
)
def test_passthrough_evil(tmp_path, monkeypatch, env_var_value):
def test_passthrough_evil(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, env_var_value: str
) -> None:
args = CommandLineArguments.defaults()
args.package_dir = tmp_path
@@ -157,7 +159,7 @@ xfail_env_parse = pytest.mark.xfail(
pytest.param("a trailing backslash \\", marks=[xfail_env_parse]),
],
)
def test_toml_environment_evil(tmp_path, env_var_value):
def test_toml_environment_evil(tmp_path: Path, env_var_value: str) -> None:
args = CommandLineArguments.defaults()
args.package_dir = tmp_path
@@ -296,7 +298,7 @@ def test_container_engine_option(
assert parsed_container_engine.disable_host_mount == result_disable_host_mount
def test_environment_pass_references():
def test_environment_pass_references() -> None:
options = Options(
platform="linux",
command_line_arguments=CommandLineArguments.defaults(),
+33 -32
View File
@@ -1,5 +1,6 @@
import shlex
from typing import TYPE_CHECKING
from pathlib import Path
from typing import Any, cast
import pytest
@@ -12,9 +13,7 @@ from cibuildwheel.options import (
ShlexTableFormat,
_resolve_cascade,
)
if TYPE_CHECKING:
from pathlib import Path
from cibuildwheel.typing import PlatformName
PYPROJECT_1 = """
[tool.cibuildwheel]
@@ -39,12 +38,12 @@ test-requires = ["other", "many"]
@pytest.fixture(params=["linux", "macos", "windows"])
def platform(request):
return request.param
def platform(request: pytest.FixtureRequest) -> PlatformName:
return cast("PlatformName", request.param)
@pytest.mark.parametrize("fname", ["pyproject.toml", "cibuildwheel.toml"])
def test_simple_settings(tmp_path, platform, fname):
def test_simple_settings(tmp_path: Path, platform: PlatformName, fname: str) -> None:
config_file_path: Path = tmp_path / fname
config_file_path.write_text(PYPROJECT_1)
@@ -83,7 +82,7 @@ def test_simple_settings(tmp_path, platform, fname):
options_reader.get("test-extras", option_format=ShlexTableFormat())
def test_envvar_override(tmp_path, platform):
def test_envvar_override(tmp_path: Path, platform: PlatformName) -> None:
config_file_path: Path = tmp_path / "pyproject.toml"
config_file_path.write_text(PYPROJECT_1)
@@ -128,7 +127,7 @@ def test_envvar_override(tmp_path, platform):
assert options_reader.get("test-command") == "mytest"
def test_project_global_override_default_platform(tmp_path, platform):
def test_project_global_override_default_platform(tmp_path: Path, platform: PlatformName) -> None:
pyproject_toml = tmp_path / "pyproject.toml"
pyproject_toml.write_text(
"""
@@ -140,14 +139,14 @@ repair-wheel-command = "repair-project-global"
assert options_reader.get("repair-wheel-command") == "repair-project-global"
def test_env_global_override_default_platform(platform):
def test_env_global_override_default_platform(platform: PlatformName) -> None:
options_reader = OptionsReader(
platform=platform, env={"CIBW_REPAIR_WHEEL_COMMAND": "repair-env-global"}
)
assert options_reader.get("repair-wheel-command") == "repair-env-global"
def test_env_global_override_project_platform(tmp_path, platform):
def test_env_global_override_project_platform(tmp_path: Path, platform: PlatformName) -> None:
pyproject_toml = tmp_path / "pyproject.toml"
pyproject_toml.write_text(
"""
@@ -161,7 +160,7 @@ repair-wheel-command = "repair-project-macos"
)
options_reader = OptionsReader(
pyproject_toml,
platform=platform,
platform=cast("Any", platform),
env={
"CIBW_REPAIR_WHEEL_COMMAND": "repair-env-global",
},
@@ -169,7 +168,7 @@ repair-wheel-command = "repair-project-macos"
assert options_reader.get("repair-wheel-command") == "repair-env-global"
def test_global_platform_order(tmp_path, platform):
def test_global_platform_order(tmp_path: Path, platform: str) -> None:
pyproject_toml = tmp_path / "pyproject.toml"
pyproject_toml.write_text(
"""
@@ -183,11 +182,11 @@ repair-wheel-command = "repair-project-macos"
repair-wheel-command = "repair-project-global"
"""
)
options_reader = OptionsReader(pyproject_toml, platform=platform, env={})
options_reader = OptionsReader(pyproject_toml, platform=cast("Any", platform), env={})
assert options_reader.get("repair-wheel-command") == f"repair-project-{platform}"
def test_unexpected_key(tmp_path):
def test_unexpected_key(tmp_path: Path) -> None:
# Note that platform contents are only checked when running
# for that platform.
pyproject_toml = tmp_path / "pyproject.toml"
@@ -204,7 +203,7 @@ repairs-wheel-command = "repair-project-linux"
assert "repair-wheel-command" in str(excinfo.value)
def test_underscores_in_key(tmp_path):
def test_underscores_in_key(tmp_path: Path) -> None:
# Note that platform contents are only checked when running
# for that platform.
pyproject_toml = tmp_path / "pyproject.toml"
@@ -221,7 +220,7 @@ repair_wheel_command = "repair-project-linux"
assert "repair-wheel-command" in str(excinfo.value)
def test_unexpected_table(tmp_path):
def test_unexpected_table(tmp_path: Path) -> None:
pyproject_toml = tmp_path / "pyproject.toml"
pyproject_toml.write_text(
"""
@@ -233,7 +232,7 @@ repair-wheel-command = "repair-project-linux"
OptionsReader(pyproject_toml, platform="linux", env={})
def test_unsupported_join(tmp_path):
def test_unsupported_join(tmp_path: Path) -> None:
pyproject_toml = tmp_path / "pyproject.toml"
pyproject_toml.write_text(
"""
@@ -248,7 +247,7 @@ build = ["1", "2"]
options_reader.get("build")
def test_disallowed_a(tmp_path):
def test_disallowed_a(tmp_path: Path) -> None:
pyproject_toml = tmp_path / "pyproject.toml"
pyproject_toml.write_text(
"""
@@ -262,7 +261,7 @@ manylinux-x86_64-image = "manylinux1"
OptionsReader(pyproject_toml, platform="windows", disallow=disallow, env={})
def test_environment_override_empty(tmp_path):
def test_environment_override_empty(tmp_path: Path) -> None:
pyproject_toml = tmp_path / "pyproject.toml"
pyproject_toml.write_text(
"""
@@ -296,7 +295,7 @@ manylinux-x86_64-image = ""
@pytest.mark.parametrize("ignore_empty", [True, False], ids=["ignore_empty", "no_ignore_empty"])
def test_resolve_cascade(ignore_empty):
def test_resolve_cascade(ignore_empty: bool) -> None:
answer = _resolve_cascade(
("not", InheritRule.NONE),
(None, InheritRule.NONE),
@@ -327,7 +326,7 @@ def test_resolve_cascade(ignore_empty):
@pytest.mark.parametrize("ignore_empty", [True, False], ids=["ignore_empty", "no_ignore_empty"])
@pytest.mark.parametrize("rule", [InheritRule.PREPEND, InheritRule.NONE, InheritRule.APPEND])
def test_resolve_cascade_merge_list(ignore_empty, rule):
def test_resolve_cascade_merge_list(ignore_empty: bool, rule: InheritRule) -> None:
answer = _resolve_cascade(
(["a1", "a2"], InheritRule.NONE),
([], InheritRule.NONE),
@@ -348,7 +347,7 @@ def test_resolve_cascade_merge_list(ignore_empty, rule):
@pytest.mark.parametrize("rule", [InheritRule.PREPEND, InheritRule.NONE, InheritRule.APPEND])
def test_resolve_cascade_merge_dict(rule):
def test_resolve_cascade_merge_dict(rule: InheritRule) -> None:
answer = _resolve_cascade(
({"value": "a1", "base": "b1"}, InheritRule.NONE),
(None, InheritRule.NONE),
@@ -365,7 +364,7 @@ def test_resolve_cascade_merge_dict(rule):
assert answer == "value=override base=b1"
def test_resolve_cascade_merge_strings():
def test_resolve_cascade_merge_strings() -> None:
answer = _resolve_cascade(
("value=a1 base=b1", InheritRule.NONE),
("value=override", InheritRule.APPEND),
@@ -374,7 +373,7 @@ def test_resolve_cascade_merge_strings():
assert answer == "value=override base=b1"
def test_resolve_cascade_merge_different_types():
def test_resolve_cascade_merge_different_types() -> None:
answer = _resolve_cascade(
("value=a1 base=b1", InheritRule.NONE),
({"value": "override"}, InheritRule.APPEND),
@@ -420,11 +419,13 @@ test-command = ["extra-prepend"]
"""
def test_pyproject_2(tmp_path, platform):
def test_pyproject_2(tmp_path: Path, platform: str) -> None:
pyproject_toml: Path = tmp_path / "pyproject.toml"
pyproject_toml.write_text(PYPROJECT_2)
options_reader = OptionsReader(config_file_path=pyproject_toml, platform=platform, env={})
options_reader = OptionsReader(
config_file_path=pyproject_toml, platform=cast("Any", platform), env={}
)
assert options_reader.get("test-command", option_format=ListFormat(" && ")) == "pyproject"
with options_reader.identifier("random"):
@@ -451,7 +452,7 @@ def test_pyproject_2(tmp_path, platform):
)
def test_overrides_not_a_list(tmp_path, platform):
def test_overrides_not_a_list(tmp_path: Path, platform: str) -> None:
pyproject_toml: Path = tmp_path / "pyproject.toml"
pyproject_toml.write_text(
@@ -465,10 +466,10 @@ test-command = "pyproject-override"
)
with pytest.raises(OptionsReaderError):
OptionsReader(config_file_path=pyproject_toml, platform=platform, env={})
OptionsReader(config_file_path=pyproject_toml, platform=cast("Any", platform), env={})
def test_config_settings(tmp_path):
def test_config_settings(tmp_path: Path) -> None:
pyproject_toml: Path = tmp_path / "pyproject.toml"
pyproject_toml.write_text(
"""\
@@ -485,7 +486,7 @@ other = ["two", "three"]
)
def test_pip_config_settings(tmp_path):
def test_pip_config_settings(tmp_path: Path) -> None:
pyproject_toml: Path = tmp_path / "pyproject.toml"
pyproject_toml.write_text(
"""\
@@ -501,7 +502,7 @@ def test_pip_config_settings(tmp_path):
)
def test_overrides_inherit(tmp_path):
def test_overrides_inherit(tmp_path: Path) -> None:
pyproject_toml: Path = tmp_path / "pyproject.toml"
pyproject_toml.write_text(
"""\
+16 -15
View File
@@ -1,4 +1,5 @@
import tomllib
from pathlib import Path
from textwrap import dedent
import pytest
@@ -10,7 +11,7 @@ from cibuildwheel.projectfiles import (
)
def test_read_setup_py_simple(tmp_path):
def test_read_setup_py_simple(tmp_path: Path) -> None:
with open(tmp_path / "setup.py", "w") as f:
f.write(
dedent(
@@ -31,7 +32,7 @@ def test_read_setup_py_simple(tmp_path):
assert get_requires_python_str(tmp_path, {}) == "1.23"
def test_read_setup_py_if_main(tmp_path):
def test_read_setup_py_if_main(tmp_path: Path) -> None:
with open(tmp_path / "setup.py", "w") as f:
f.write(
dedent(
@@ -53,7 +54,7 @@ def test_read_setup_py_if_main(tmp_path):
assert get_requires_python_str(tmp_path, {}) == "1.23"
def test_read_setup_py_if_main_reversed(tmp_path):
def test_read_setup_py_if_main_reversed(tmp_path: Path) -> None:
with open(tmp_path / "setup.py", "w") as f:
f.write(
dedent(
@@ -75,7 +76,7 @@ def test_read_setup_py_if_main_reversed(tmp_path):
assert get_requires_python_str(tmp_path, {}) == "1.23"
def test_read_setup_py_if_invalid(tmp_path):
def test_read_setup_py_if_invalid(tmp_path: Path) -> None:
with open(tmp_path / "setup.py", "w") as f:
f.write(
dedent(
@@ -97,7 +98,7 @@ def test_read_setup_py_if_invalid(tmp_path):
assert not get_requires_python_str(tmp_path, {})
def test_read_setup_py_full(tmp_path):
def test_read_setup_py_full(tmp_path: Path) -> None:
with open(tmp_path / "setup.py", "w", encoding="utf8") as f:
f.write(
dedent(
@@ -123,7 +124,7 @@ def test_read_setup_py_full(tmp_path):
assert get_requires_python_str(tmp_path, {}) == "1.24"
def test_read_setup_py_assign(tmp_path):
def test_read_setup_py_assign(tmp_path: Path) -> None:
with open(tmp_path / "setup.py", "w") as f:
f.write(
dedent(
@@ -146,7 +147,7 @@ def test_read_setup_py_assign(tmp_path):
assert get_requires_python_str(tmp_path, {}) is None
def test_read_setup_py_None(tmp_path):
def test_read_setup_py_None(tmp_path: Path) -> None:
with open(tmp_path / "setup.py", "w") as f:
f.write(
dedent(
@@ -169,7 +170,7 @@ def test_read_setup_py_None(tmp_path):
assert get_requires_python_str(tmp_path, {}) is None
def test_read_setup_py_empty(tmp_path):
def test_read_setup_py_empty(tmp_path: Path) -> None:
with open(tmp_path / "setup.py", "w") as f:
f.write(
dedent(
@@ -191,7 +192,7 @@ def test_read_setup_py_empty(tmp_path):
assert get_requires_python_str(tmp_path, {}) is None
def test_read_setup_cfg(tmp_path):
def test_read_setup_cfg(tmp_path: Path) -> None:
with open(tmp_path / "setup.cfg", "w") as f:
f.write(
dedent(
@@ -207,7 +208,7 @@ def test_read_setup_cfg(tmp_path):
assert get_requires_python_str(tmp_path, {}) == "1.234"
def test_read_setup_cfg_empty(tmp_path):
def test_read_setup_cfg_empty(tmp_path: Path) -> None:
with open(tmp_path / "setup.cfg", "w") as f:
f.write(
dedent(
@@ -223,7 +224,7 @@ def test_read_setup_cfg_empty(tmp_path):
assert get_requires_python_str(tmp_path, {}) is None
def test_read_pyproject_toml(tmp_path):
def test_read_pyproject_toml(tmp_path: Path) -> None:
with open(tmp_path / "pyproject.toml", "w") as f:
f.write(
dedent(
@@ -242,7 +243,7 @@ def test_read_pyproject_toml(tmp_path):
assert get_requires_python_str(tmp_path, pyproject_toml) == "1.654"
def test_read_pyproject_toml_empty(tmp_path):
def test_read_pyproject_toml_empty(tmp_path: Path) -> None:
with open(tmp_path / "pyproject.toml", "w") as f:
f.write(
dedent(
@@ -258,7 +259,7 @@ def test_read_pyproject_toml_empty(tmp_path):
assert get_requires_python_str(tmp_path, pyproject_toml) is None
def test_read_dep_groups():
def test_read_dep_groups() -> None:
pyproject_toml = {"dependency-groups": {"group1": ["pkg1", "pkg2"], "group2": ["pkg3"]}}
assert resolve_dependency_groups(pyproject_toml) == ()
assert resolve_dependency_groups(pyproject_toml, "group1") == ("pkg1", "pkg2")
@@ -266,11 +267,11 @@ def test_read_dep_groups():
assert resolve_dependency_groups(pyproject_toml, "group1", "group2") == ("pkg1", "pkg2", "pkg3")
def test_dep_group_no_file_error():
def test_dep_group_no_file_error() -> None:
with pytest.raises(FileNotFoundError, match=r"pyproject\.toml"):
resolve_dependency_groups(None, "test")
def test_dep_group_no_section_error():
def test_dep_group_no_section_error() -> None:
with pytest.raises(KeyError, match=r"pyproject\.toml"):
resolve_dependency_groups({}, "test")
+18 -12
View File
@@ -1,5 +1,5 @@
import textwrap
from pathlib import PurePath
from pathlib import Path, PurePath
from unittest.mock import Mock, call
import pytest
@@ -18,7 +18,7 @@ from cibuildwheel.util.helpers import (
from cibuildwheel.util.packaging import find_compatible_wheel
def test_format_safe():
def test_format_safe() -> None:
assert format_safe("{wheel}", wheel="filename.whl") == "filename.whl"
assert format_safe("command #{wheel}", wheel="filename.whl") == "command {wheel}"
assert format_safe("{command #{wheel}}", wheel="filename.whl") == "{command {wheel}}"
@@ -37,7 +37,7 @@ def test_format_safe():
assert format_safe("#{not_a_param} {param}", param="1") == "#{not_a_param} 1"
def test_prepare_command():
def test_prepare_command() -> None:
assert prepare_command("python -m {project}", project="project") == "python -m project"
assert prepare_command("python -m {something}", project="project") == "python -m {something}"
assert (
@@ -103,7 +103,7 @@ def test_find_compatible_wheel_not_found(wheel: str, identifier: str) -> None:
assert find_compatible_wheel([PurePath(wheel)], identifier) is None
def test_fix_ansi_codes_for_github_actions():
def test_fix_ansi_codes_for_github_actions() -> None:
input = textwrap.dedent(
"""
This line is normal
@@ -131,7 +131,7 @@ def test_fix_ansi_codes_for_github_actions():
assert output == expected
def test_parse_key_value_string():
def test_parse_key_value_string() -> None:
assert parse_key_value_string("bar", positional_arg_names=["foo"]) == {"foo": ["bar"]}
assert parse_key_value_string("foo:bar", kw_arg_names=["foo"]) == {"foo": ["bar"]}
with pytest.raises(ValueError, match="Too many positional arguments"):
@@ -212,7 +212,7 @@ def test_parse_key_value_string():
}
def test_flexible_version_comparisons():
def test_flexible_version_comparisons() -> None:
assert FlexibleVersion("2.0") == FlexibleVersion("2")
assert FlexibleVersion("2.0") < FlexibleVersion("2.1")
assert FlexibleVersion("2.1") > FlexibleVersion("2")
@@ -227,7 +227,7 @@ def test_flexible_version_comparisons():
@pytest.fixture
def sample_project(tmp_path):
def sample_project(tmp_path: Path) -> Path:
"""Create a directory structure that contains a range of files."""
project_path = tmp_path / "project"
@@ -324,7 +324,13 @@ def sample_project(tmp_path):
),
],
)
def test_copy_test_sources(tmp_path, sample_project, test_sources, expected, not_expected):
def test_copy_test_sources(
tmp_path: Path,
sample_project: Path,
test_sources: list[str],
expected: list[str],
not_expected: list[str],
) -> None:
"""Test sources can be copied into the test directory."""
target = tmp_path / "somewhere/test_cwd"
copy_test_sources(test_sources, sample_project, target)
@@ -336,7 +342,7 @@ def test_copy_test_sources(tmp_path, sample_project, test_sources, expected, not
assert not (tmp_path / "somewhere/test_cwd" / path).exists()
def test_copy_test_sources_missing_file(tmp_path, sample_project):
def test_copy_test_sources_missing_file(tmp_path: Path, sample_project: Path) -> None:
"""If test_sources references a folder that doesn't exist, an error is raised."""
with pytest.raises(
@@ -350,7 +356,7 @@ def test_copy_test_sources_missing_file(tmp_path, sample_project):
)
def test_copy_test_sources_alternate_copy_into(sample_project):
def test_copy_test_sources_alternate_copy_into(sample_project: Path) -> None:
"""If an alternate copy_into method is provided, it is used."""
target = PurePath("/container/test_cwd")
@@ -367,7 +373,7 @@ def test_copy_test_sources_alternate_copy_into(sample_project):
)
def test_unwrap():
def test_unwrap() -> None:
assert (
unwrap("""
This is a
@@ -378,7 +384,7 @@ def test_unwrap():
)
def test_unwrap_preserving_paragraphs():
def test_unwrap_preserving_paragraphs() -> None:
assert (
unwrap("""
This is a
+2 -2
View File
@@ -9,7 +9,7 @@ OPTIONS_DEFAULTS = Options("linux", CommandLineArguments.defaults(), {}, default
FILE = Path(__file__)
def test_printout_wheels(capsys):
def test_printout_wheels(capsys: pytest.CaptureFixture[str]) -> None:
log = Logger()
log.fold_mode = "disabled"
log.colors_enabled = False
@@ -32,7 +32,7 @@ def test_printout_wheels(capsys):
assert "SHA256=" in captured.out
def test_no_printout_on_error(capsys):
def test_no_printout_on_error(capsys: pytest.CaptureFixture[str]) -> None:
log = Logger()
with pytest.raises(RuntimeError), log.print_summary(options=OPTIONS_DEFAULTS):
raise RuntimeError()