Skip to content

Commit 9f28012

Browse files
authored
Merge branch 'main' into pywin32--Add-win32gui._TrackMouseEvent
2 parents 19d2b9a + 3e76afe commit 9f28012

File tree

1,117 files changed

+18635
-8544
lines changed

Some content is hidden

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

1,117 files changed

+18635
-8544
lines changed

.flake8

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
[flake8]
22
# Y: Flake8 is only used to run flake8-pyi, everything else is in Ruff
3-
# F821: Typeshed is a testing ground for flake8-pyi, which monkeypatches F821
4-
select = Y, F821
3+
select = Y
54
# Ignore rules normally excluded by default
6-
extend-ignore = Y090
5+
extend-ignore = Y090,Y091
76
per-file-ignores =
87
# Generated protobuf files:
98
# Y021: Include docstrings

.github/workflows/tests.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ jobs:
7373
- run: uv pip install -r requirements-tests.txt --system
7474
- name: Install required APT packages
7575
run: |
76+
sudo apt-get update -qy
7677
DEPENDENCIES=$( python tests/get_external_apt_dependencies.py )
7778
if [ -n "$DEPENDENCIES" ]; then
7879
printf "Installing APT packages:\n $(echo $DEPENDENCIES | sed 's/ /\n /g')\n"
@@ -124,6 +125,7 @@ jobs:
124125
run: uv pip install -r requirements-tests.txt --system
125126
- name: Install required APT packages
126127
run: |
128+
sudo apt-get update -qy
127129
DEPENDENCIES=$( python tests/get_external_apt_dependencies.py )
128130
if [ -n "$DEPENDENCIES" ]; then
129131
printf "Installing APT packages:\n $(echo $DEPENDENCIES | sed 's/ /\n /g')\n"

.pre-commit-config.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ repos:
1111
args: [--fix=lf]
1212
- id: check-case-conflict
1313
- repo: https://github.com/astral-sh/ruff-pre-commit
14-
rev: v0.11.4 # must match requirements-tests.txt
14+
rev: v0.12.2 # must match requirements-tests.txt
1515
hooks:
1616
- id: ruff
1717
name: Run ruff on stubs, tests and scripts
@@ -31,12 +31,12 @@ repos:
3131
hooks:
3232
- id: black
3333
- repo: https://github.com/pycqa/flake8
34-
rev: 7.2.0
34+
rev: 7.3.0
3535
hooks:
3636
- id: flake8
3737
language: python
3838
additional_dependencies:
39-
- "flake8-pyi==24.9.0"
39+
- "flake8-pyi==25.5.0"
4040
types: [file]
4141
types_or: [python, pyi]
4242
- repo: meta

CONTRIBUTING.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,9 @@ Note that some tests require extra setup steps to install the required dependenc
7777
Run the following commands from a Windows terminal to install all requirements:
7878

7979
```powershell
80-
> python -m venv .venv
80+
> py -m venv .venv
8181
> .venv\Scripts\activate
82-
(.venv) > pip install -U pip
82+
(.venv) > python -m pip install -U pip
8383
(.venv) > pip install -r requirements-tests.txt
8484
```
8585

@@ -447,7 +447,7 @@ If a package ships its own `py.typed` file, please follow these steps:
447447

448448
1. Open an issue with the earliest month of removal in the subject.
449449
2. A maintainer will add the
450-
["stubs: removal" label](https://github.com/python/typeshed/labels/stubs%3A%20removal).
450+
["stubs: removal" label](https://github.com/python/typeshed/labels/%22stubs%3A%20removal%22).
451451
3. Open a PR that sets the `obsolete_since` field in the `METADATA.toml`
452452
file to the first version of the package that shipped `py.typed`.
453453
4. After at least six months, open a PR to remove the stubs.
@@ -457,18 +457,19 @@ steps:
457457

458458
1. Open an issue explaining why the stubs should be removed.
459459
2. A maintainer will add the
460-
["stubs: removal" label](https://github.com/python/typeshed/labels/stubs%3A%20removal).
460+
["stubs: removal" label](https://github.com/python/typeshed/labels/%22stubs%3A%20removal%22).
461461
3. Open a PR that sets the `no_longer_updated` field in the `METADATA.toml`
462462
file to `true`.
463463
4. When a new version of the package was automatically uploaded to PyPI
464464
(which can take up to a day), open a PR to remove the stubs.
465465

466-
If feeling kindly, please update [mypy](https://github.com/python/mypy/blob/master/mypy/stubinfo.py)
466+
Don't forget to make sure the library is not in the [`pyrightconfig.stricter.json`](./pyrightconfig.stricter.json)
467+
exclusion list. If feeling kindly, please update [mypy](https://github.com/python/mypy/blob/master/mypy/stubinfo.py)
467468
for any stub obsoletions or removals.
468469

469470
### Marking PRs as "deferred"
470471

471-
We sometimes use the ["status: deferred" label](https://github.com/python/typeshed/labels/status%3A%20deferred)
472+
We sometimes use the ["status: deferred" label](https://github.com/python/typeshed/labels/%22status%3A%20deferred%22)
472473
to mark PRs and issues that we'd like to accept, but that are blocked by some
473474
external factor. Blockers can include:
474475

lib/ts_utils/metadata.py

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from __future__ import annotations
77

8+
import datetime
89
import functools
910
import re
1011
import urllib.parse
@@ -18,6 +19,7 @@
1819
import tomlkit
1920
from packaging.requirements import Requirement
2021
from packaging.specifiers import Specifier
22+
from tomlkit.items import String
2123

2224
from .paths import PYPROJECT_PATH, STUBS_PATH, distribution_path
2325

@@ -26,6 +28,7 @@
2628
"PackageDependencies",
2729
"StubMetadata",
2830
"StubtestSettings",
31+
"get_oldest_supported_python",
2932
"get_recursive_requirements",
3033
"read_dependencies",
3134
"read_metadata",
@@ -139,6 +142,13 @@ def read_stubtest_settings(distribution: str) -> StubtestSettings:
139142
)
140143

141144

145+
@final
146+
@dataclass(frozen=True)
147+
class ObsoleteMetadata:
148+
since_version: Annotated[str, "A string representing a specific version"]
149+
since_date: Annotated[datetime.date, "A date when the package became obsolete"]
150+
151+
142152
@final
143153
@dataclass(frozen=True)
144154
class StubMetadata:
@@ -153,7 +163,7 @@ class StubMetadata:
153163
extra_description: str | None
154164
stub_distribution: Annotated[str, "The name under which the distribution is uploaded to PyPI"]
155165
upstream_repository: Annotated[str, "The URL of the upstream repository"] | None
156-
obsolete_since: Annotated[str, "A string representing a specific version"] | None
166+
obsolete: Annotated[ObsoleteMetadata, "Metadata indicating when the stubs package became obsolete"] | None
157167
no_longer_updated: bool
158168
uploaded_to_pypi: Annotated[bool, "Whether or not a distribution is uploaded to PyPI"]
159169
partial_stub: Annotated[bool, "Whether this is a partial type stub package as per PEP 561."]
@@ -162,7 +172,7 @@ class StubMetadata:
162172

163173
@property
164174
def is_obsolete(self) -> bool:
165-
return self.obsolete_since is not None
175+
return self.obsolete is not None
166176

167177

168178
_KNOWN_METADATA_FIELDS: Final = frozenset(
@@ -213,27 +223,27 @@ def read_metadata(distribution: str) -> StubMetadata:
213223
"""
214224
try:
215225
with metadata_path(distribution).open("rb") as f:
216-
data: dict[str, object] = tomli.load(f)
226+
data = tomlkit.load(f)
217227
except FileNotFoundError:
218228
raise NoSuchStubError(f"Typeshed has no stubs for {distribution!r}!") from None
219229

220230
unknown_metadata_fields = data.keys() - _KNOWN_METADATA_FIELDS
221231
assert not unknown_metadata_fields, f"Unexpected keys in METADATA.toml for {distribution!r}: {unknown_metadata_fields}"
222232

223233
assert "version" in data, f"Missing 'version' field in METADATA.toml for {distribution!r}"
224-
version = data["version"]
234+
version: object = data.get("version") # pyright: ignore[reportUnknownMemberType]
225235
assert isinstance(version, str) and len(version) > 0, f"Invalid 'version' field in METADATA.toml for {distribution!r}"
226236
# Check that the version spec parses
227237
if version[0].isdigit():
228238
version = f"=={version}"
229239
version_spec = Specifier(version)
230240
assert version_spec.operator in {"==", "~="}, f"Invalid 'version' field in METADATA.toml for {distribution!r}"
231241

232-
requires_s: object = data.get("requires", [])
242+
requires_s: object = data.get("requires", []) # pyright: ignore[reportUnknownMemberType]
233243
assert isinstance(requires_s, list)
234244
requires = [parse_requires(distribution, req) for req in requires_s]
235245

236-
extra_description: object = data.get("extra_description")
246+
extra_description: object = data.get("extra_description") # pyright: ignore[reportUnknownMemberType]
237247
assert isinstance(extra_description, (str, type(None)))
238248

239249
if "stub_distribution" in data:
@@ -243,7 +253,7 @@ def read_metadata(distribution: str) -> StubMetadata:
243253
else:
244254
stub_distribution = f"types-{distribution}"
245255

246-
upstream_repository: object = data.get("upstream_repository")
256+
upstream_repository: object = data.get("upstream_repository") # pyright: ignore[reportUnknownMemberType]
247257
assert isinstance(upstream_repository, (str, type(None)))
248258
if isinstance(upstream_repository, str):
249259
parsed_url = urllib.parse.urlsplit(upstream_repository)
@@ -267,21 +277,28 @@ def read_metadata(distribution: str) -> StubMetadata:
267277
)
268278
assert num_url_path_parts == 2, bad_github_url_msg
269279

270-
obsolete_since: object = data.get("obsolete_since")
271-
assert isinstance(obsolete_since, (str, type(None)))
272-
no_longer_updated: object = data.get("no_longer_updated", False)
280+
obsolete_since: object = data.get("obsolete_since") # pyright: ignore[reportUnknownMemberType]
281+
assert isinstance(obsolete_since, (String, type(None)))
282+
if obsolete_since:
283+
comment = obsolete_since.trivia.comment
284+
since_date_string = comment.removeprefix("# Released on ")
285+
since_date = datetime.date.fromisoformat(since_date_string)
286+
obsolete = ObsoleteMetadata(since_version=obsolete_since, since_date=since_date)
287+
else:
288+
obsolete = None
289+
no_longer_updated: object = data.get("no_longer_updated", False) # pyright: ignore[reportUnknownMemberType]
273290
assert type(no_longer_updated) is bool
274-
uploaded_to_pypi: object = data.get("upload", True)
291+
uploaded_to_pypi: object = data.get("upload", True) # pyright: ignore[reportUnknownMemberType]
275292
assert type(uploaded_to_pypi) is bool
276-
partial_stub: object = data.get("partial_stub", True)
293+
partial_stub: object = data.get("partial_stub", True) # pyright: ignore[reportUnknownMemberType]
277294
assert type(partial_stub) is bool
278-
requires_python_str: object = data.get("requires_python")
295+
requires_python_str: object = data.get("requires_python") # pyright: ignore[reportUnknownMemberType]
279296
oldest_supported_python = get_oldest_supported_python()
280297
oldest_supported_python_specifier = Specifier(f">={oldest_supported_python}")
281298
if requires_python_str is None:
282299
requires_python = oldest_supported_python_specifier
283300
else:
284-
assert type(requires_python_str) is str
301+
assert isinstance(requires_python_str, str)
285302
requires_python = Specifier(requires_python_str)
286303
assert requires_python != oldest_supported_python_specifier, f'requires_python="{requires_python}" is redundant'
287304
# Check minimum Python version is not less than the oldest version of Python supported by typeshed
@@ -291,7 +308,7 @@ def read_metadata(distribution: str) -> StubMetadata:
291308
assert requires_python.operator == ">=", "'requires_python' should be a minimum version specifier, use '>=3.x'"
292309

293310
empty_tools: dict[object, object] = {}
294-
tools_settings: object = data.get("tool", empty_tools)
311+
tools_settings: object = data.get("tool", empty_tools) # pyright: ignore[reportUnknownMemberType]
295312
assert isinstance(tools_settings, dict)
296313
assert tools_settings.keys() <= _KNOWN_METADATA_TOOL_FIELDS.keys(), f"Unrecognised tool for {distribution!r}"
297314
for tool, tk in _KNOWN_METADATA_TOOL_FIELDS.items():
@@ -307,7 +324,7 @@ def read_metadata(distribution: str) -> StubMetadata:
307324
extra_description=extra_description,
308325
stub_distribution=stub_distribution,
309326
upstream_repository=upstream_repository,
310-
obsolete_since=obsolete_since,
327+
obsolete=obsolete,
311328
no_longer_updated=no_longer_updated,
312329
uploaded_to_pypi=uploaded_to_pypi,
313330
partial_stub=partial_stub,

lib/ts_utils/paths.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
PYPROJECT_PATH: Final = TS_BASE_PATH / "pyproject.toml"
1313
REQUIREMENTS_PATH: Final = TS_BASE_PATH / "requirements-tests.txt"
1414
GITIGNORE_PATH: Final = TS_BASE_PATH / ".gitignore"
15+
PYRIGHT_CONFIG: Final = TS_BASE_PATH / "pyrightconfig.stricter.json"
1516

1617
TESTS_DIR: Final = "@tests"
1718
TEST_CASES_DIR: Final = "test_cases"

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ ignore = [
159159
# Used for direct, non-subclass type comparison, for example: `type(val) is str`
160160
# see https://github.com/astral-sh/ruff/issues/6465
161161
"E721", # Do not compare types, use `isinstance()`
162+
# Highly opinionated, and it's often necessary to violate it
163+
"PLC0415", # `import` should be at the top-level of a file
162164
# Leave the size and complexity of tests to human interpretation
163165
"PLR09", # Too many ...
164166
# Too many magic number "2" that are preferable inline. https://github.com/astral-sh/ruff/issues/10009

pyrightconfig.stricter.json

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,23 @@
1818
"stdlib/optparse.pyi",
1919
"stdlib/_tkinter.pyi",
2020
"stdlib/tkinter/__init__.pyi",
21-
"stdlib/tkinter/commondialog.pyi",
2221
"stdlib/tkinter/filedialog.pyi",
2322
"stdlib/tkinter/dialog.pyi",
24-
"stdlib/tkinter/messagebox.pyi",
2523
"stdlib/tkinter/scrolledtext.pyi",
2624
"stdlib/tkinter/tix.pyi",
2725
"stdlib/tkinter/ttk.pyi",
28-
"stubs/aiofiles",
2926
"stubs/antlr4-python3-runtime",
3027
"stubs/auth0-python",
3128
"stubs/Authlib",
3229
"stubs/aws-xray-sdk",
3330
"stubs/beautifulsoup4",
3431
"stubs/boltons",
3532
"stubs/braintree",
36-
"stubs/caldav",
3733
"stubs/cffi",
38-
"stubs/click-web",
39-
"stubs/corus",
4034
"stubs/dateparser",
4135
"stubs/defusedxml",
4236
"stubs/docker",
4337
"stubs/docutils",
44-
"stubs/flake8-typing-imports",
4538
"stubs/Flask-SocketIO",
4639
"stubs/fpdf2",
4740
"stubs/gdb",
@@ -57,11 +50,10 @@
5750
"stubs/httplib2",
5851
"stubs/hvac",
5952
"stubs/icalendar",
60-
"stubs/jmespath",
6153
"stubs/jsonschema",
6254
"stubs/jwcrypto",
6355
"stubs/ldap3",
64-
"stubs/m3u8",
56+
"stubs/m3u8/m3u8/model.pyi",
6557
"stubs/Markdown",
6658
"stubs/mock/mock/mock.pyi",
6759
"stubs/mysqlclient",
@@ -78,21 +70,18 @@
7870
"stubs/peewee",
7971
"stubs/pexpect",
8072
"stubs/pika",
73+
"stubs/pony",
8174
"stubs/protobuf",
8275
"stubs/psutil",
8376
"stubs/psycopg2",
8477
"stubs/pyasn1",
8578
"stubs/pycurl",
8679
"stubs/Pygments",
8780
"stubs/PyMySQL",
88-
"stubs/python-crontab",
89-
"stubs/python-datemath",
9081
"stubs/python-dateutil",
91-
"stubs/python-http-client",
9282
"stubs/python-jose",
9383
"stubs/pytz/pytz/lazy.pyi",
9484
"stubs/pywin32",
95-
"stubs/pyxdg",
9685
"stubs/PyYAML",
9786
"stubs/reportlab",
9887
"stubs/requests",
@@ -104,7 +93,6 @@
10493
"stubs/tqdm",
10594
"stubs/vobject",
10695
"stubs/workalendar",
107-
"stubs/wurlitzer",
10896
],
10997
"typeCheckingMode": "strict",
11098
// TODO: Complete incomplete stubs

requirements-tests.txt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
# Type checkers that we test our stubs against. These should always
22
# be pinned to a specific version to make failure reproducible.
3-
mypy==1.15.0
4-
pyright==1.1.400
3+
mypy==1.16.1
4+
pyright==1.1.403
55
# pytype can be installed on Windows, but requires building wheels, let's not do that on the CI
66
pytype==2024.10.11; platform_system != "Windows" and python_version >= "3.10" and python_version < "3.13"
77

88
# Libraries used by our various scripts.
99
# TODO (2025-05-09): Installing this on Python 3.14 on Windows fails at
1010
# the moment.
11-
aiohttp==3.11.15; python_version < "3.14"
11+
aiohttp==3.12.14; python_version < "3.14"
1212
# TODO (2025-05-09): No wheels exist for Python 3.14 yet, slowing down CI
1313
# considerably and prone to fail.
1414
grpcio-tools>=1.66.2; python_version < "3.14" # For grpc_tools.protoc
1515
mypy-protobuf==3.6.0
16-
packaging==24.2
16+
packaging==25.0
1717
pathspec>=0.11.1
1818
pre-commit
1919
# Required by create_baseline_stubs.py. Must match .pre-commit-config.yaml.
20-
ruff==0.11.4
20+
ruff==0.12.2
2121
# TODO (2025-05-07): Dependency libcst doesn't support Python 3.14 yet.
2222
stubdefaulter==0.1.0; python_version < "3.14"
2323
termcolor>=2.3
2424
tomli==2.2.1
25-
tomlkit==0.13.2
26-
typing_extensions>=4.13.0rc1
27-
uv==0.7.4
25+
tomlkit==0.13.3
26+
typing_extensions>=4.14.0rc1
27+
uv==0.7.19
2828

2929
# Utilities for typeshed infrastructure scripts.
3030
ts_utils @ file:lib

scripts/create_baseline_stubs.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@
2323
import aiohttp
2424
import termcolor
2525

26-
from ts_utils.paths import STDLIB_PATH, STUBS_PATH
27-
28-
PYRIGHT_CONFIG = Path("pyrightconfig.stricter.json")
26+
from ts_utils.paths import PYRIGHT_CONFIG, STDLIB_PATH, STUBS_PATH
2927

3028

3129
def search_pip_freeze_output(project: str, output: str) -> tuple[str, str] | None:

0 commit comments

Comments
 (0)