Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strict typing #620

Merged
merged 21 commits into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading