Skip to content

Commit

Permalink
chore: stricter mypy (pypa#2053)
Browse files Browse the repository at this point in the history
* chore: improve mypy

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>

* chore(types): type functions in tests

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>

* chore(types): No partial types in tests

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>

---------

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
  • Loading branch information
henryiii authored Oct 22, 2024
1 parent b4d1e17 commit b986027
Show file tree
Hide file tree
Showing 27 changed files with 131 additions and 111 deletions.
2 changes: 2 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ repos:
- nox
- packaging
- pygithub
- pytest
- rich
- tomli
- tomli_w
Expand All @@ -40,6 +41,7 @@ repos:
- types-jinja2
- types-pyyaml
- types-requests
- types-setuptools
- uv
- validate-pyproject
- id: mypy
Expand Down
18 changes: 10 additions & 8 deletions bin/make_dependency_update_pr.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,29 @@
from __future__ import annotations

import os
import subprocess
import sys
import textwrap
import time
from pathlib import Path
from subprocess import run

import click


def shell(cmd, *, check: bool, **kwargs):
return run([cmd], shell=True, check=check, **kwargs)
def shell(cmd: str, *, check: bool, **kwargs: object) -> subprocess.CompletedProcess[str]:
return subprocess.run([cmd], shell=True, check=check, **kwargs) # type: ignore[call-overload, no-any-return]


def git_repo_has_changes():
unstaged_changes = shell("git diff-index --quiet HEAD --", check=False).returncode != 0
staged_changes = shell("git diff-index --quiet --cached HEAD --", check=False).returncode != 0
def git_repo_has_changes() -> bool:
unstaged_changes: bool = shell("git diff-index --quiet HEAD --", check=False).returncode != 0
staged_changes: bool = (
shell("git diff-index --quiet --cached HEAD --", check=False).returncode != 0
)
return unstaged_changes or staged_changes


@click.command()
def main():
def main() -> None:
project_root = Path(__file__).parent / ".."
os.chdir(project_root)

Expand Down Expand Up @@ -57,7 +59,7 @@ def main():
PR generated by `{os.path.basename(__file__)}`.
"""
)
run(
subprocess.run(
[
"gh",
"pr",
Expand Down
6 changes: 4 additions & 2 deletions bin/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,9 @@ def get_projects(
return sorted((Project(item, github) for item in config), reverse=online)


def render_projects(projects: Sequence[Project], *, dest_path: Path, include_info: bool = True):
def render_projects(
projects: Sequence[Project], *, dest_path: Path, include_info: bool = True
) -> str:
io = StringIO()
print = functools.partial(builtins.print, file=io)

Expand Down Expand Up @@ -203,7 +205,7 @@ def insert_projects_table(
projects: Sequence[Project],
input_filename: str,
include_info: bool = True,
):
) -> None:
text = file.read_text()
projects_table = render_projects(projects, include_info=include_info, dest_path=file)

Expand Down
16 changes: 8 additions & 8 deletions bin/run_example_ci_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,29 @@

import os
import shutil
import subprocess
import sys
import textwrap
import time
import typing
from glob import glob
from pathlib import Path
from subprocess import run
from urllib.parse import quote

import click


def shell(cmd, *, check: bool, **kwargs):
return run([cmd], shell=True, check=check, **kwargs)
def shell(cmd: str, *, check: bool, **kwargs: object) -> subprocess.CompletedProcess[str]:
return subprocess.run([cmd], shell=True, check=check, **kwargs) # type: ignore[call-overload, no-any-return]


def git_repo_has_changes():
def git_repo_has_changes() -> bool:
unstaged_changes = shell("git diff-index --quiet HEAD --", check=False).returncode != 0
staged_changes = shell("git diff-index --quiet --cached HEAD --", check=False).returncode != 0
return unstaged_changes or staged_changes


def generate_basic_project(path):
def generate_basic_project(path: Path) -> None:
sys.path.insert(0, "")
from test.test_projects.c import new_c_project

Expand Down Expand Up @@ -79,7 +79,7 @@ class CIService(typing.NamedTuple):
]


def ci_service_for_config_file(config_file):
def ci_service_for_config_file(config_file: str) -> CIService:
filename = Path(config_file).name

try:
Expand Down Expand Up @@ -134,7 +134,7 @@ def run_example_ci_configs(config_files=None):
dst_config_file.parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(src_config_file, dst_config_file)

run(["git", "add", example_project], check=True)
subprocess.run(["git", "add", example_project], check=True)
message = textwrap.dedent(
f"""\
Test example minimal configs
Expand All @@ -144,7 +144,7 @@ def run_example_ci_configs(config_files=None):
Time: {timestamp}
"""
)
run(["git", "commit", "--no-verify", "--message", message], check=True)
subprocess.run(["git", "commit", "--no-verify", "--message", message], check=True)
shell(f"git subtree --prefix={example_project} push origin {branch_name}", check=True)

print("---")
Expand Down
2 changes: 1 addition & 1 deletion bin/update_how_it_works_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
)


def main():
def main() -> None:
subprocess.run(["mkdocs", "build"], check=True)

hti = Html2Image(custom_flags=["--force-device-scale-factor=2"])
Expand Down
2 changes: 1 addition & 1 deletion bin/update_readme_changelog.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
)


def main():
def main() -> None:
changelog_text = CHANGELOG_FILE.read_text()
readme_text = README_FILE.read_text()

Expand Down
2 changes: 1 addition & 1 deletion bin/update_virtualenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class VersionTuple:
version_string: str


def git_ls_remote_versions(url) -> list[VersionTuple]:
def git_ls_remote_versions(url: str) -> list[VersionTuple]:
versions: list[VersionTuple] = []
tags = subprocess.run(
["git", "ls-remote", "--tags", url], check=True, text=True, capture_output=True
Expand Down
2 changes: 1 addition & 1 deletion docs/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
def define_env(env: Any) -> None:
"Hook function for mkdocs-macros"

@env.macro
@env.macro # type: ignore[misc]
def subprocess_run(*args: str) -> str:
"Run a subprocess and return the stdout"
env = os.environ.copy()
Expand Down
19 changes: 3 additions & 16 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -113,33 +113,20 @@ files = [
]
warn_unused_configs = true

warn_redundant_casts = true
no_implicit_reexport = true
strict_equality = true
warn_unused_ignores = true
check_untyped_defs = true

disallow_subclassing_any = true
disallow_any_generics = true
warn_return_any = true
no_implicit_optional = true
strict = true
disallow_untyped_defs = false

enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
warn_unreachable = true
warn_unreachable = false

[[tool.mypy.overrides]]
module = "cibuildwheel.*"
disallow_untyped_defs = true
disallow_untyped_calls = true
disallow_incomplete_defs = true
disallow_untyped_decorators = true

[[tool.mypy.overrides]]
module = [
"setuptools",
"setuptools._distutils", # needed even if only directly import setuptools._distutils.util
"setuptools._distutils.util",
"pytest", # ignored in pre-commit to speed up check
"bashlex",
"bashlex.*",
"importlib_resources",
Expand Down
2 changes: 1 addition & 1 deletion test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from .utils import EMULATED_ARCHS, platform


def pytest_addoption(parser) -> None:
def pytest_addoption(parser: pytest.Parser) -> None:
parser.addoption(
"--run-emulation",
action="store",
Expand Down
8 changes: 4 additions & 4 deletions test/test_custom_repair_wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,9 @@ def test(tmp_path, capfd):
basic_project.generate(project_dir)

num_builds = len(utils.cibuildwheel_get_build_identifiers(project_dir))
if num_builds > 1:
expectation = pytest.raises(subprocess.CalledProcessError)
else:
expectation = does_not_raise()
expectation = (
pytest.raises(subprocess.CalledProcessError) if num_builds > 1 else does_not_raise()
)

with expectation as exc_info:
result = utils.cibuildwheel_run(
Expand All @@ -48,6 +47,7 @@ def test(tmp_path, capfd):

captured = capfd.readouterr()
if num_builds > 1:
assert exc_info is not None
assert "Build failed because a wheel named" in captured.err
assert exc_info.value.returncode == 6
else:
Expand Down
5 changes: 3 additions & 2 deletions test/test_dependency_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import platform
import re
import textwrap
from pathlib import Path

import pytest

Expand Down Expand Up @@ -46,8 +47,8 @@
VERSION_REGEX = r"([\w-]+)==([^\s]+)"


def get_versions_from_constraint_file(constraint_file):
constraint_file_text = constraint_file.read_text(encoding="utf8")
def get_versions_from_constraint_file(constraint_file: Path) -> dict[str, str]:
constraint_file_text = constraint_file.read_text(encoding="utf-8")

return dict(re.findall(VERSION_REGEX, constraint_file_text))

Expand Down
7 changes: 6 additions & 1 deletion test/test_from_sdist.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import subprocess
import sys
import textwrap
from collections.abc import Mapping
from pathlib import Path
from tempfile import TemporaryDirectory

Expand All @@ -28,7 +29,11 @@ def make_sdist(project: TestProject, working_dir: Path) -> Path:
return next(sdist_dir.glob("*.tar.gz"))


def cibuildwheel_from_sdist_run(sdist_path, add_env=None, config_file=None):
def cibuildwheel_from_sdist_run(
sdist_path: Path | str,
add_env: Mapping[str, str] | None = None,
config_file: str | None = None,
) -> list[str]:
env = os.environ.copy()

if add_env:
Expand Down
2 changes: 1 addition & 1 deletion test/test_projects/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from pathlib import Path


def main():
def main() -> None:
parser = ArgumentParser(
prog="python -m test.test_projects", description="Generate a test project to check it out"
)
Expand Down
6 changes: 3 additions & 3 deletions test/test_projects/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ class TestProject:
files: FilesDict
template_context: TemplateContext

def __init__(self):
def __init__(self) -> None:
self.files = {}
self.template_context = {}

def generate(self, path: Path):
def generate(self, path: Path) -> None:
for filename, content in self.files.items():
file_path = path / filename
file_path.parent.mkdir(parents=True, exist_ok=True)
Expand All @@ -37,7 +37,7 @@ def generate(self, path: Path):

f.write(content)

def copy(self):
def copy(self) -> TestProject:
other = TestProject()
other.files = self.files.copy()
other.template_context = self.template_context.copy()
Expand Down
14 changes: 7 additions & 7 deletions test/test_projects/c.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@

def new_c_project(
*,
spam_c_top_level_add="",
spam_c_function_add="",
setup_py_add="",
setup_py_extension_args_add="",
setup_py_setup_args_add="",
setup_cfg_add="",
):
spam_c_top_level_add: str = "",
spam_c_function_add: str = "",
setup_py_add: str = "",
setup_py_extension_args_add: str = "",
setup_py_setup_args_add: str = "",
setup_cfg_add: str = "",
) -> TestProject:
project = TestProject()

project.files.update(
Expand Down
2 changes: 1 addition & 1 deletion test/test_testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ def test_failing_test(tmp_path):
@pytest.mark.parametrize("test_runner", ["pytest", "unittest"])
def test_bare_pytest_invocation(
tmp_path: Path, capfd: pytest.CaptureFixture[str], test_runner: str
):
) -> None:
"""Check that if a user runs pytest in the the test cwd, it raises a helpful error"""
project_dir = tmp_path / "project"
output_dir = tmp_path / "output"
Expand Down
2 changes: 1 addition & 1 deletion test/test_windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
basic_project = test_projects.new_c_project()


def skip_if_no_msvc(arm64=False):
def skip_if_no_msvc(arm64: bool = False) -> None:
programfiles = os.getenv("PROGRAMFILES(X86)", "") or os.getenv("PROGRAMFILES", "")
if not programfiles:
pytest.skip("Requires %PROGRAMFILES(X86)% variable to be set")
Expand Down
Loading

0 comments on commit b986027

Please sign in to comment.