Skip to content

Commit 0e7c6e1

Browse files
Merge branch 'main' into 3.14-argparse-parameters
2 parents 98b2340 + 30b7b67 commit 0e7c6e1

75 files changed

Lines changed: 1438 additions & 893 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CONTRIBUTING.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,12 @@ This has the following keys:
229229
If not specified, stubtest is run only on `linux`.
230230
Only add extra OSes to the test
231231
if there are platform-specific branches in a stubs package.
232+
* `mypy_plugins` (default: `[]`): A list of Python modules to use as mypy plugins
233+
when running stubtest. For example: `mypy_plugins = ["mypy_django_plugin.main"]`
234+
* `mypy_plugins_config` (default: `{}`): A dictionary mapping plugin names to their
235+
configuration dictionaries for use by mypy plugins. For example:
236+
`mypy_plugins_config = {"django-stubs" = {"django_settings_module" = "@tests.django_settings"}}`
237+
232238

233239
`*_dependencies` are usually packages needed to `pip install` the implementation
234240
distribution.

lib/ts_utils/metadata.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from collections.abc import Mapping
1212
from dataclasses import dataclass
1313
from pathlib import Path
14-
from typing import Annotated, Final, NamedTuple, final
14+
from typing import Annotated, Any, Final, NamedTuple, final
1515
from typing_extensions import TypeGuard
1616

1717
import tomli
@@ -42,6 +42,10 @@ def _is_list_of_strings(obj: object) -> TypeGuard[list[str]]:
4242
return isinstance(obj, list) and all(isinstance(item, str) for item in obj)
4343

4444

45+
def _is_nested_dict(obj: object) -> TypeGuard[dict[str, dict[str, Any]]]:
46+
return isinstance(obj, dict) and all(isinstance(k, str) and isinstance(v, dict) for k, v in obj.items())
47+
48+
4549
@functools.cache
4650
def _get_oldest_supported_python() -> str:
4751
with PYPROJECT_PATH.open("rb") as config:
@@ -71,6 +75,8 @@ class StubtestSettings:
7175
ignore_missing_stub: bool
7276
platforms: list[str]
7377
stubtest_requirements: list[str]
78+
mypy_plugins: list[str]
79+
mypy_plugins_config: dict[str, dict[str, Any]]
7480

7581
def system_requirements_for_platform(self, platform: str) -> list[str]:
7682
assert platform in _STUBTEST_PLATFORM_MAPPING, f"Unrecognised platform {platform!r}"
@@ -93,6 +99,8 @@ def read_stubtest_settings(distribution: str) -> StubtestSettings:
9399
ignore_missing_stub: object = data.get("ignore_missing_stub", False)
94100
specified_platforms: object = data.get("platforms", ["linux"])
95101
stubtest_requirements: object = data.get("stubtest_requirements", [])
102+
mypy_plugins: object = data.get("mypy_plugins", [])
103+
mypy_plugins_config: object = data.get("mypy_plugins_config", {})
96104

97105
assert type(skip) is bool
98106
assert type(ignore_missing_stub) is bool
@@ -104,6 +112,8 @@ def read_stubtest_settings(distribution: str) -> StubtestSettings:
104112
assert _is_list_of_strings(choco_dependencies)
105113
assert _is_list_of_strings(extras)
106114
assert _is_list_of_strings(stubtest_requirements)
115+
assert _is_list_of_strings(mypy_plugins)
116+
assert _is_nested_dict(mypy_plugins_config)
107117

108118
unrecognised_platforms = set(specified_platforms) - _STUBTEST_PLATFORM_MAPPING.keys()
109119
assert not unrecognised_platforms, f"Unrecognised platforms specified for {distribution!r}: {unrecognised_platforms}"
@@ -124,6 +134,8 @@ def read_stubtest_settings(distribution: str) -> StubtestSettings:
124134
ignore_missing_stub=ignore_missing_stub,
125135
platforms=specified_platforms,
126136
stubtest_requirements=stubtest_requirements,
137+
mypy_plugins=mypy_plugins,
138+
mypy_plugins_config=mypy_plugins_config,
127139
)
128140

129141

@@ -179,6 +191,8 @@ def is_obsolete(self) -> bool:
179191
"ignore_missing_stub",
180192
"platforms",
181193
"stubtest_requirements",
194+
"mypy_plugins",
195+
"mypy_plugins_config",
182196
}
183197
}
184198
_DIST_NAME_RE: Final = re.compile(r"^[a-z0-9]([a-z0-9._-]*[a-z0-9])?$", re.IGNORECASE)

lib/ts_utils/mypy.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import tomli
88

9-
from ts_utils.metadata import metadata_path
9+
from ts_utils.metadata import StubtestSettings, metadata_path
1010
from ts_utils.utils import NamedTemporaryFile, TemporaryFileWrapper
1111

1212

@@ -50,14 +50,27 @@ def validate_configuration(section_name: str, mypy_section: dict[str, Any]) -> M
5050

5151

5252
@contextmanager
53-
def temporary_mypy_config_file(configurations: Iterable[MypyDistConf]) -> Generator[TemporaryFileWrapper[str]]:
53+
def temporary_mypy_config_file(
54+
configurations: Iterable[MypyDistConf], stubtest_settings: StubtestSettings | None = None
55+
) -> Generator[TemporaryFileWrapper[str]]:
5456
temp = NamedTemporaryFile("w+")
5557
try:
5658
for dist_conf in configurations:
5759
temp.write(f"[mypy-{dist_conf.module_name}]\n")
5860
for k, v in dist_conf.values.items():
5961
temp.write(f"{k} = {v}\n")
6062
temp.write("[mypy]\n")
63+
64+
if stubtest_settings:
65+
if stubtest_settings.mypy_plugins:
66+
temp.write(f"plugins = {'.'.join(stubtest_settings.mypy_plugins)}\n")
67+
68+
if stubtest_settings.mypy_plugins_config:
69+
for plugin_name, plugin_dict in stubtest_settings.mypy_plugins_config.items():
70+
temp.write(f"[mypy.plugins.{plugin_name}]\n")
71+
for k, v in plugin_dict.items():
72+
temp.write(f"{k} = {v}\n")
73+
6174
temp.flush()
6275
yield temp
6376
finally:

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ extra-standard-library = [
245245
# Extra modules not recognized by Ruff
246246
# Added in Python 3.9
247247
"zoneinfo",
248+
# Added in Python 3.14
249+
"compression",
248250
]
249251
known-first-party = ["_utils", "ts_utils"]
250252

pyrightconfig.stricter.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
"stubs/Authlib",
2929
"stubs/aws-xray-sdk",
3030
"stubs/beautifulsoup4",
31-
"stubs/bleach/bleach/sanitizer.pyi",
3231
"stubs/boltons",
3332
"stubs/braintree",
3433
"stubs/caldav",

0 commit comments

Comments
 (0)