Skip to content

Commit 12829cc

Browse files
Strict typing (#620)
1 parent e54ff1e commit 12829cc

File tree

11 files changed

+82
-121
lines changed

11 files changed

+82
-121
lines changed

.github/workflows/reusable-linters.yml

+1-3
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,7 @@ jobs:
7171
with:
7272
token: ${{ secrets.codecov-token }}
7373
files: >-
74-
.tox/.tmp/.mypy/python-3.12/cobertura.xml,
75-
.tox/.tmp/.mypy/python-3.10/cobertura.xml,
76-
.tox/.tmp/.mypy/python-3.8/cobertura.xml
74+
.tox/.tmp/.mypy/python-3.11/cobertura.xml
7775
flags: >-
7876
CI-GHA,
7977
MyPy

.mypy.ini

+23-38
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,33 @@
11
[mypy]
2-
python_version = 3.8
3-
color_output = True
4-
error_summary = True
5-
files =
6-
frozenlist/,
7-
packaging/,
8-
tests/
9-
2+
files = frozenlist, packaging, tests
103
check_untyped_defs = True
11-
12-
disallow_untyped_defs = True
4+
follow_imports_for_stubs = True
5+
disallow_any_decorated = True
136
disallow_any_generics = True
14-
15-
enable_error_code =
16-
ignore-without-code
17-
18-
follow_imports = normal
19-
20-
ignore_missing_imports = False
21-
22-
pretty = true
23-
24-
show_column_numbers = true
25-
show_error_codes = true
26-
strict_optional = True
27-
28-
warn_no_return = True
7+
disallow_any_unimported = True
8+
disallow_incomplete_defs = True
9+
disallow_subclassing_any = True
10+
disallow_untyped_calls = True
11+
disallow_untyped_decorators = True
12+
disallow_untyped_defs = True
13+
# TODO(PY312): explicit-override
14+
enable_error_code = ignore-without-code, possibly-undefined, redundant-expr, redundant-self, truthy-bool, truthy-iterable, unused-awaitable
15+
extra_checks = True
16+
implicit_reexport = False
17+
no_implicit_optional = True
18+
pretty = True
19+
show_column_numbers = True
20+
show_error_codes = True
21+
show_error_code_links = True
22+
strict_equality = True
23+
warn_incomplete_stub = True
2924
warn_redundant_casts = True
25+
warn_return_any = True
26+
warn_unreachable = True
3027
warn_unused_ignores = True
3128

3229
[mypy-Cython.*]
3330
ignore_missing_imports = true
3431

35-
[mypy-distutils.*]
36-
ignore_missing_imports = true
37-
38-
[mypy-expandvars]
39-
ignore_missing_imports = true
40-
41-
[mypy-pep517_backend.*]
42-
check_untyped_defs = False
43-
disallow_any_generics = False
44-
disallow_untyped_defs = False
45-
warn_unused_ignores = False
46-
47-
[mypy-tomllib]
32+
[mypy-expandvars.*]
4833
ignore_missing_imports = true

.pre-commit-config.yaml

+6-38
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,8 @@ repos:
168168
rev: v1.14.1
169169
hooks:
170170
- id: mypy
171-
alias: mypy-py312
172-
name: MyPy, for Python 3.12
171+
alias: mypy-py311
172+
name: MyPy, for Python 3.11
173173
additional_dependencies:
174174
- lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report`
175175
- pytest
@@ -178,42 +178,10 @@ repos:
178178
args:
179179
- --install-types
180180
- --non-interactive
181-
- --python-version=3.12
182-
- --txt-report=.tox/.tmp/.mypy/python-3.12
183-
- --cobertura-xml-report=.tox/.tmp/.mypy/python-3.12
184-
- --html-report=.tox/.tmp/.mypy/python-3.12
185-
pass_filenames: false
186-
- id: mypy
187-
alias: mypy-py310
188-
name: MyPy, for Python 3.10
189-
additional_dependencies:
190-
- lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report`
191-
- pytest
192-
- tomli # requirement of packaging/pep517_backend/
193-
- types-setuptools # requirement of packaging/pep517_backend/
194-
args:
195-
- --install-types
196-
- --non-interactive
197-
- --python-version=3.10
198-
- --txt-report=.tox/.tmp/.mypy/python-3.10
199-
- --cobertura-xml-report=.tox/.tmp/.mypy/python-3.10
200-
- --html-report=.tox/.tmp/.mypy/python-3.10
201-
pass_filenames: false
202-
- id: mypy
203-
alias: mypy-py38
204-
name: MyPy, for Python 3.8
205-
additional_dependencies:
206-
- lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report`
207-
- pytest
208-
- tomli # requirement of packaging/pep517_backend/
209-
- types-setuptools # requirement of packaging/pep517_backend/
210-
args:
211-
- --install-types
212-
- --non-interactive
213-
- --python-version=3.8
214-
- --txt-report=.tox/.tmp/.mypy/python-3.8
215-
- --cobertura-xml-report=.tox/.tmp/.mypy/python-3.8
216-
- --html-report=.tox/.tmp/.mypy/python-3.8
181+
- --python-version=3.11
182+
- --txt-report=.tox/.tmp/.mypy/python-3.11
183+
- --cobertura-xml-report=.tox/.tmp/.mypy/python-3.11
184+
- --html-report=.tox/.tmp/.mypy/python-3.11
217185
pass_filenames: false
218186

219187
- repo: https://github.com/rhysd/actionlint

packaging/pep517_backend/_backend.py

+20-19
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
from __future__ import annotations
55

66
import os
7-
import typing as t
87
from contextlib import contextmanager, nullcontext, suppress
98
from functools import partial
109
from pathlib import Path
1110
from shutil import copytree
1211
from sys import implementation as _system_implementation
1312
from sys import stderr as _standard_error_stream
1413
from tempfile import TemporaryDirectory
14+
from typing import Dict, Iterator, List, Union
1515
from warnings import warn as _warn_that
1616

1717
from setuptools.build_meta import build_sdist as _setuptools_build_sdist
@@ -55,7 +55,7 @@
5555
'get_requires_for_build_wheel',
5656
'prepare_metadata_for_build_wheel',
5757
*(
58-
() if _setuptools_build_editable is None
58+
() if _setuptools_build_editable is None # type: ignore[redundant-expr]
5959
else (
6060
'build_editable',
6161
'get_requires_for_build_editable',
@@ -64,7 +64,7 @@
6464
),
6565
)
6666

67-
_ConfigDict = t.Dict[str, t.Union[str, t.List[str], None]]
67+
_ConfigDict = Dict[str, Union[str, List[str], None]]
6868

6969

7070
CYTHON_TRACING_CONFIG_SETTING = 'with-cython-tracing'
@@ -86,7 +86,7 @@
8686
"""A fallback for ``pure-python`` is not set."""
8787

8888

89-
def _is_truthy_setting_value(setting_value) -> bool:
89+
def _is_truthy_setting_value(setting_value: str) -> bool:
9090
truthy_values = {'', None, 'true', '1', 'on'}
9191
return setting_value.lower() in truthy_values
9292

@@ -107,7 +107,7 @@ def _get_setting_value(
107107
continue
108108

109109
with suppress(lookup_errors): # type: ignore[arg-type]
110-
return _is_truthy_setting_value(src_mapping[src_key]) # type: ignore[index]
110+
return _is_truthy_setting_value(src_mapping[src_key]) # type: ignore[arg-type,index]
111111

112112
return default
113113

@@ -124,7 +124,7 @@ def _make_pure_python(config_settings: _ConfigDict | None = None) -> bool:
124124
def _include_cython_line_tracing(
125125
config_settings: _ConfigDict | None = None,
126126
*,
127-
default=False,
127+
default: bool = False,
128128
) -> bool:
129129
return _get_setting_value(
130130
config_settings,
@@ -135,60 +135,61 @@ def _include_cython_line_tracing(
135135

136136

137137
@contextmanager
138-
def patched_distutils_cmd_install():
138+
def patched_distutils_cmd_install() -> Iterator[None]:
139139
"""Make `install_lib` of `install` cmd always use `platlib`.
140140
141141
:yields: None
142142
"""
143143
# Without this, build_lib puts stuff under `*.data/purelib/` folder
144144
orig_finalize = _distutils_install_cmd.finalize_options
145145

146-
def new_finalize_options(self): # noqa: WPS430
146+
def new_finalize_options(self: _distutils_install_cmd) -> None: # noqa: WPS430
147147
self.install_lib = self.install_platlib
148148
orig_finalize(self)
149149

150-
_distutils_install_cmd.finalize_options = new_finalize_options
150+
_distutils_install_cmd.finalize_options = new_finalize_options # type: ignore[method-assign]
151151
try:
152152
yield
153153
finally:
154-
_distutils_install_cmd.finalize_options = orig_finalize
154+
_distutils_install_cmd.finalize_options = orig_finalize # type: ignore[method-assign]
155155

156156

157157
@contextmanager
158-
def patched_dist_has_ext_modules():
158+
def patched_dist_has_ext_modules() -> Iterator[None]:
159159
"""Make `has_ext_modules` of `Distribution` always return `True`.
160160
161161
:yields: None
162162
"""
163163
# Without this, build_lib puts stuff under `*.data/platlib/` folder
164164
orig_func = _DistutilsDistribution.has_ext_modules
165165

166-
_DistutilsDistribution.has_ext_modules = lambda *args, **kwargs: True
166+
_DistutilsDistribution.has_ext_modules = lambda *args, **kwargs: True # type: ignore[method-assign]
167167
try:
168168
yield
169169
finally:
170-
_DistutilsDistribution.has_ext_modules = orig_func
170+
_DistutilsDistribution.has_ext_modules = orig_func # type: ignore[method-assign]
171171

172172

173173
@contextmanager
174-
def patched_dist_get_long_description():
174+
def patched_dist_get_long_description() -> Iterator[None]:
175175
"""Make `has_ext_modules` of `Distribution` always return `True`.
176176
177177
:yields: None
178178
"""
179179
# Without this, build_lib puts stuff under `*.data/platlib/` folder
180180
_orig_func = _DistutilsDistributionMetadata.get_long_description
181181

182-
def _get_sanitized_long_description(self):
182+
def _get_sanitized_long_description(self: _DistutilsDistributionMetadata) -> str:
183+
assert self.long_description is not None
183184
return sanitize_rst_roles(self.long_description)
184185

185-
_DistutilsDistributionMetadata.get_long_description = (
186+
_DistutilsDistributionMetadata.get_long_description = ( # type: ignore[method-assign]
186187
_get_sanitized_long_description
187188
)
188189
try:
189190
yield
190191
finally:
191-
_DistutilsDistributionMetadata.get_long_description = _orig_func
192+
_DistutilsDistributionMetadata.get_long_description = _orig_func # type: ignore[method-assign]
192193

193194

194195
def _exclude_dir_path(
@@ -215,7 +216,7 @@ def _exclude_dir_path(
215216

216217

217218
@contextmanager
218-
def _in_temporary_directory(src_dir: Path) -> t.Iterator[None]:
219+
def _in_temporary_directory(src_dir: Path) -> Iterator[None]:
219220
with TemporaryDirectory(prefix='.tmp-frozenlist-pep517-') as tmp_dir:
220221
tmp_dir_path = Path(tmp_dir)
221222
root_tmp_dir_path = tmp_dir_path.parent
@@ -238,7 +239,7 @@ def maybe_prebuild_c_extensions(
238239
line_trace_cython_when_unset: bool = False,
239240
build_inplace: bool = False,
240241
config_settings: _ConfigDict | None = None,
241-
) -> t.Generator[None, t.Any, t.Any]:
242+
) -> Iterator[None]:
242243
"""Pre-build C-extensions in a temporary directory, when needed.
243244
244245
This context manager also patches metadata, setuptools and distutils.

packaging/pep517_backend/_compat.py

+8-11
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
"""Cross-python stdlib shims."""
22

33
import os
4-
import typing as t
4+
import sys
55
from contextlib import contextmanager
66
from pathlib import Path
7+
from typing import Iterator
78

8-
try:
9-
from contextlib import chdir as chdir_cm # type: ignore[attr-defined]
10-
except ImportError:
9+
if sys.version_info >= (3, 11):
10+
from contextlib import chdir as chdir_cm
11+
from tomllib import loads as load_toml_from_string
12+
else:
13+
from tomli import loads as load_toml_from_string
1114

1215
@contextmanager # type: ignore[no-redef]
13-
def chdir_cm(path: os.PathLike) -> t.Iterator[None]:
16+
def chdir_cm(path: "os.PathLike[str]") -> Iterator[None]:
1417
"""Temporarily change the current directory, recovering on exit."""
1518
original_wd = Path.cwd()
1619
os.chdir(path)
@@ -20,10 +23,4 @@ def chdir_cm(path: os.PathLike) -> t.Iterator[None]:
2023
os.chdir(original_wd)
2124

2225

23-
try:
24-
from tomllib import loads as load_toml_from_string
25-
except ImportError:
26-
from tomli import loads as load_toml_from_string # type: ignore[no-redef]
27-
28-
2926
__all__ = ("chdir_cm", "load_toml_from_string") # noqa: WPS410

packaging/pep517_backend/_cython_configuration.py

+12-4
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,22 @@
66
from contextlib import contextmanager
77
from pathlib import Path
88
from sys import version_info as _python_version_tuple
9+
from typing import Iterator, TypedDict
910

1011
from expandvars import expandvars
1112

1213
from ._compat import load_toml_from_string
1314
from ._transformers import get_cli_kwargs_from_config, get_enabled_cli_flags_from_config
1415

1516

16-
def get_local_cython_config() -> dict:
17+
class Config(TypedDict):
18+
env: dict[str, str]
19+
flags: dict[str, bool]
20+
kwargs: dict[str, str]
21+
src: list[str]
22+
23+
24+
def get_local_cython_config() -> Config:
1725
"""Grab optional build dependencies from pyproject.toml config.
1826
1927
:returns: config section from ``pyproject.toml``
@@ -67,10 +75,10 @@ def get_local_cython_config() -> dict:
6775
"""
6876
config_toml_txt = (Path.cwd().resolve() / 'pyproject.toml').read_text()
6977
config_mapping = load_toml_from_string(config_toml_txt)
70-
return config_mapping['tool']['local']['cythonize']
78+
return config_mapping['tool']['local']['cythonize'] # type: ignore[no-any-return]
7179

7280

73-
def make_cythonize_cli_args_from_config(config) -> list[str]:
81+
def make_cythonize_cli_args_from_config(config: Config) -> list[str]:
7482
py_ver_arg = f'-{_python_version_tuple.major!s}'
7583

7684
cli_flags = get_enabled_cli_flags_from_config(config['flags'])
@@ -80,7 +88,7 @@ def make_cythonize_cli_args_from_config(config) -> list[str]:
8088

8189

8290
@contextmanager
83-
def patched_env(env: dict[str, str], cython_line_tracing_requested: bool):
91+
def patched_env(env: dict[str, str], cython_line_tracing_requested: bool) -> Iterator[None]:
8492
"""Temporary set given env vars.
8593
8694
:param env: tmp env vars to set

0 commit comments

Comments
 (0)