Skip to content

Commit

Permalink
Strict typing (#620)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dreamsorcerer authored Feb 26, 2025
1 parent e54ff1e commit 12829cc
Show file tree
Hide file tree
Showing 11 changed files with 82 additions and 121 deletions.
4 changes: 1 addition & 3 deletions .github/workflows/reusable-linters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,7 @@ jobs:
with:
token: ${{ secrets.codecov-token }}
files: >-
.tox/.tmp/.mypy/python-3.12/cobertura.xml,
.tox/.tmp/.mypy/python-3.10/cobertura.xml,
.tox/.tmp/.mypy/python-3.8/cobertura.xml
.tox/.tmp/.mypy/python-3.11/cobertura.xml
flags: >-
CI-GHA,
MyPy
Expand Down
61 changes: 23 additions & 38 deletions .mypy.ini
Original file line number Diff line number Diff line change
@@ -1,48 +1,33 @@
[mypy]
python_version = 3.8
color_output = True
error_summary = True
files =
frozenlist/,
packaging/,
tests/

files = frozenlist, packaging, tests
check_untyped_defs = True

disallow_untyped_defs = True
follow_imports_for_stubs = True
disallow_any_decorated = True
disallow_any_generics = True

enable_error_code =
ignore-without-code

follow_imports = normal

ignore_missing_imports = False

pretty = true

show_column_numbers = true
show_error_codes = true
strict_optional = True

warn_no_return = True
disallow_any_unimported = True
disallow_incomplete_defs = True
disallow_subclassing_any = True
disallow_untyped_calls = True
disallow_untyped_decorators = True
disallow_untyped_defs = True
# TODO(PY312): explicit-override
enable_error_code = ignore-without-code, possibly-undefined, redundant-expr, redundant-self, truthy-bool, truthy-iterable, unused-awaitable
extra_checks = True
implicit_reexport = False
no_implicit_optional = True
pretty = True
show_column_numbers = True
show_error_codes = True
show_error_code_links = True
strict_equality = True
warn_incomplete_stub = True
warn_redundant_casts = True
warn_return_any = True
warn_unreachable = True
warn_unused_ignores = True

[mypy-Cython.*]
ignore_missing_imports = true

[mypy-distutils.*]
ignore_missing_imports = true

[mypy-expandvars]
ignore_missing_imports = true

[mypy-pep517_backend.*]
check_untyped_defs = False
disallow_any_generics = False
disallow_untyped_defs = False
warn_unused_ignores = False

[mypy-tomllib]
[mypy-expandvars.*]
ignore_missing_imports = true
44 changes: 6 additions & 38 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,8 @@ repos:
rev: v1.14.1
hooks:
- id: mypy
alias: mypy-py312
name: MyPy, for Python 3.12
alias: mypy-py311
name: MyPy, for Python 3.11
additional_dependencies:
- lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report`
- pytest
Expand All @@ -178,42 +178,10 @@ repos:
args:
- --install-types
- --non-interactive
- --python-version=3.12
- --txt-report=.tox/.tmp/.mypy/python-3.12
- --cobertura-xml-report=.tox/.tmp/.mypy/python-3.12
- --html-report=.tox/.tmp/.mypy/python-3.12
pass_filenames: false
- id: mypy
alias: mypy-py310
name: MyPy, for Python 3.10
additional_dependencies:
- lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report`
- pytest
- tomli # requirement of packaging/pep517_backend/
- types-setuptools # requirement of packaging/pep517_backend/
args:
- --install-types
- --non-interactive
- --python-version=3.10
- --txt-report=.tox/.tmp/.mypy/python-3.10
- --cobertura-xml-report=.tox/.tmp/.mypy/python-3.10
- --html-report=.tox/.tmp/.mypy/python-3.10
pass_filenames: false
- id: mypy
alias: mypy-py38
name: MyPy, for Python 3.8
additional_dependencies:
- lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report`
- pytest
- tomli # requirement of packaging/pep517_backend/
- types-setuptools # requirement of packaging/pep517_backend/
args:
- --install-types
- --non-interactive
- --python-version=3.8
- --txt-report=.tox/.tmp/.mypy/python-3.8
- --cobertura-xml-report=.tox/.tmp/.mypy/python-3.8
- --html-report=.tox/.tmp/.mypy/python-3.8
- --python-version=3.11
- --txt-report=.tox/.tmp/.mypy/python-3.11
- --cobertura-xml-report=.tox/.tmp/.mypy/python-3.11
- --html-report=.tox/.tmp/.mypy/python-3.11
pass_filenames: false

- repo: https://github.com/rhysd/actionlint
Expand Down
39 changes: 20 additions & 19 deletions packaging/pep517_backend/_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
from __future__ import annotations

import os
import typing as t
from contextlib import contextmanager, nullcontext, suppress
from functools import partial
from pathlib import Path
from shutil import copytree
from sys import implementation as _system_implementation
from sys import stderr as _standard_error_stream
from tempfile import TemporaryDirectory
from typing import Dict, Iterator, List, Union
from warnings import warn as _warn_that

from setuptools.build_meta import build_sdist as _setuptools_build_sdist
Expand Down Expand Up @@ -55,7 +55,7 @@
'get_requires_for_build_wheel',
'prepare_metadata_for_build_wheel',
*(
() if _setuptools_build_editable is None
() if _setuptools_build_editable is None # type: ignore[redundant-expr]
else (
'build_editable',
'get_requires_for_build_editable',
Expand All @@ -64,7 +64,7 @@
),
)

_ConfigDict = t.Dict[str, t.Union[str, t.List[str], None]]
_ConfigDict = Dict[str, Union[str, List[str], None]]


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


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

Expand All @@ -107,7 +107,7 @@ def _get_setting_value(
continue

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

return default

Expand All @@ -124,7 +124,7 @@ def _make_pure_python(config_settings: _ConfigDict | None = None) -> bool:
def _include_cython_line_tracing(
config_settings: _ConfigDict | None = None,
*,
default=False,
default: bool = False,
) -> bool:
return _get_setting_value(
config_settings,
Expand All @@ -135,60 +135,61 @@ def _include_cython_line_tracing(


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

def new_finalize_options(self): # noqa: WPS430
def new_finalize_options(self: _distutils_install_cmd) -> None: # noqa: WPS430
self.install_lib = self.install_platlib
orig_finalize(self)

_distutils_install_cmd.finalize_options = new_finalize_options
_distutils_install_cmd.finalize_options = new_finalize_options # type: ignore[method-assign]
try:
yield
finally:
_distutils_install_cmd.finalize_options = orig_finalize
_distutils_install_cmd.finalize_options = orig_finalize # type: ignore[method-assign]


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

_DistutilsDistribution.has_ext_modules = lambda *args, **kwargs: True
_DistutilsDistribution.has_ext_modules = lambda *args, **kwargs: True # type: ignore[method-assign]
try:
yield
finally:
_DistutilsDistribution.has_ext_modules = orig_func
_DistutilsDistribution.has_ext_modules = orig_func # type: ignore[method-assign]


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

def _get_sanitized_long_description(self):
def _get_sanitized_long_description(self: _DistutilsDistributionMetadata) -> str:
assert self.long_description is not None
return sanitize_rst_roles(self.long_description)

_DistutilsDistributionMetadata.get_long_description = (
_DistutilsDistributionMetadata.get_long_description = ( # type: ignore[method-assign]
_get_sanitized_long_description
)
try:
yield
finally:
_DistutilsDistributionMetadata.get_long_description = _orig_func
_DistutilsDistributionMetadata.get_long_description = _orig_func # type: ignore[method-assign]


def _exclude_dir_path(
Expand All @@ -215,7 +216,7 @@ def _exclude_dir_path(


@contextmanager
def _in_temporary_directory(src_dir: Path) -> t.Iterator[None]:
def _in_temporary_directory(src_dir: Path) -> Iterator[None]:
with TemporaryDirectory(prefix='.tmp-frozenlist-pep517-') as tmp_dir:
tmp_dir_path = Path(tmp_dir)
root_tmp_dir_path = tmp_dir_path.parent
Expand All @@ -238,7 +239,7 @@ def maybe_prebuild_c_extensions(
line_trace_cython_when_unset: bool = False,
build_inplace: bool = False,
config_settings: _ConfigDict | None = None,
) -> t.Generator[None, t.Any, t.Any]:
) -> Iterator[None]:
"""Pre-build C-extensions in a temporary directory, when needed.
This context manager also patches metadata, setuptools and distutils.
Expand Down
19 changes: 8 additions & 11 deletions packaging/pep517_backend/_compat.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
"""Cross-python stdlib shims."""

import os
import typing as t
import sys
from contextlib import contextmanager
from pathlib import Path
from typing import Iterator

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

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


try:
from tomllib import loads as load_toml_from_string
except ImportError:
from tomli import loads as load_toml_from_string # type: ignore[no-redef]


__all__ = ("chdir_cm", "load_toml_from_string") # noqa: WPS410
16 changes: 12 additions & 4 deletions packaging/pep517_backend/_cython_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,22 @@
from contextlib import contextmanager
from pathlib import Path
from sys import version_info as _python_version_tuple
from typing import Iterator, TypedDict

from expandvars import expandvars

from ._compat import load_toml_from_string
from ._transformers import get_cli_kwargs_from_config, get_enabled_cli_flags_from_config


def get_local_cython_config() -> dict:
class Config(TypedDict):
env: dict[str, str]
flags: dict[str, bool]
kwargs: dict[str, str]
src: list[str]


def get_local_cython_config() -> Config:
"""Grab optional build dependencies from pyproject.toml config.
:returns: config section from ``pyproject.toml``
Expand Down Expand Up @@ -67,10 +75,10 @@ def get_local_cython_config() -> dict:
"""
config_toml_txt = (Path.cwd().resolve() / 'pyproject.toml').read_text()
config_mapping = load_toml_from_string(config_toml_txt)
return config_mapping['tool']['local']['cythonize']
return config_mapping['tool']['local']['cythonize'] # type: ignore[no-any-return]


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

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


@contextmanager
def patched_env(env: dict[str, str], cython_line_tracing_requested: bool):
def patched_env(env: dict[str, str], cython_line_tracing_requested: bool) -> Iterator[None]:
"""Temporary set given env vars.
:param env: tmp env vars to set
Expand Down
Loading

0 comments on commit 12829cc

Please sign in to comment.