Skip to content

Commit 4b18bfd

Browse files
committed
Include type checker versions in long description
Cf. python/typeshed#6843
1 parent 70038f2 commit 4b18bfd

File tree

2 files changed

+78
-6
lines changed

2 files changed

+78
-6
lines changed

stub_uploader/build_wheel.py

+15-6
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import argparse
2424
import os
2525
import os.path
26+
from pathlib import Path
2627
import shutil
2728
import subprocess
2829
import sys
@@ -37,6 +38,7 @@
3738
THIRD_PARTY_NAMESPACE,
3839
)
3940
from stub_uploader.metadata import Metadata, read_metadata
41+
from stub_uploader.ts_data import TypeshedData, read_typeshed_data
4042

4143
CHANGELOG = "CHANGELOG.md"
4244

@@ -108,7 +110,9 @@
108110

109111
DESCRIPTION_OUTRO_TEMPLATE = """
110112
See https://github.com/python/typeshed/blob/main/README.md for more details.
111-
This package was generated from typeshed commit `{commit}`.
113+
This package was generated from typeshed commit `{commit}` and was tested
114+
with mypy {ts_data.mypy_version}, pyright {ts_data.pyright_version}, and
115+
pytype {ts_data.pytype_version}.
112116
""".strip()
113117

114118

@@ -234,7 +238,11 @@ def add_partial_marker(package_data: dict[str, list[str]], stub_dir: str) -> Non
234238

235239

236240
def generate_setup_file(
237-
build_data: BuildData, metadata: Metadata, version: str, commit: str
241+
build_data: BuildData,
242+
ts_data: TypeshedData,
243+
metadata: Metadata,
244+
version: str,
245+
commit: str,
238246
) -> str:
239247
"""Auto-generate a setup.py file for given distribution using a template."""
240248
all_requirements = [
@@ -247,7 +255,7 @@ def generate_setup_file(
247255
distribution=build_data.distribution,
248256
stub_distribution=metadata.stub_distribution,
249257
long_description=generate_long_description(
250-
build_data.distribution, commit, metadata
258+
build_data.distribution, commit, ts_data, metadata
251259
),
252260
version=version,
253261
requires=all_requirements,
@@ -257,7 +265,7 @@ def generate_setup_file(
257265

258266

259267
def generate_long_description(
260-
distribution: str, commit: str, metadata: Metadata
268+
distribution: str, commit: str, ts_data: TypeshedData, metadata: Metadata
261269
) -> str:
262270
extra_description = metadata.extra_description.strip()
263271
parts: list[str] = []
@@ -280,7 +288,7 @@ def generate_long_description(
280288
)
281289
if metadata.partial:
282290
parts.append(PARTIAL_STUBS_DESCRIPTION)
283-
parts.append(DESCRIPTION_OUTRO_TEMPLATE.format(commit=commit))
291+
parts.append(DESCRIPTION_OUTRO_TEMPLATE.format(commit=commit, ts_data=ts_data))
284292
return "\n\n".join(parts)
285293

286294

@@ -294,6 +302,7 @@ def main(
294302
Note: the caller should clean the temporary directory where wheel is
295303
created after uploading it.
296304
"""
305+
ts_data = read_typeshed_data(Path(typeshed_dir))
297306
build_data = BuildData(typeshed_dir, distribution)
298307
if build_dir:
299308
tmpdir = build_dir
@@ -307,7 +316,7 @@ def main(
307316
).stdout.strip()
308317
metadata = read_metadata(typeshed_dir, distribution)
309318
with open(os.path.join(tmpdir, "setup.py"), "w") as f:
310-
f.write(generate_setup_file(build_data, metadata, version, commit))
319+
f.write(generate_setup_file(build_data, ts_data, metadata, version, commit))
311320
copy_stubs(build_data.stub_dir, tmpdir)
312321
copy_changelog(distribution, tmpdir)
313322
current_dir = os.getcwd()

stub_uploader/ts_data.py

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
"""
2+
Information about typeshed.
3+
"""
4+
5+
from __future__ import annotations
6+
import argparse
7+
from dataclasses import dataclass, fields
8+
from pathlib import Path
9+
from tomllib import load as toml_load
10+
from typing import Any
11+
12+
13+
REQUIREMENTS = "requirements-tests.txt"
14+
PYPROJECT = "pyproject.toml"
15+
16+
17+
@dataclass
18+
class TypeshedData:
19+
mypy_version: str
20+
pyright_version: str
21+
pytype_version: str
22+
23+
24+
def read_typeshed_data(typeshed_dir: Path) -> TypeshedData:
25+
pyproject = _read_pyproject_toml(typeshed_dir / PYPROJECT)
26+
requirements = _read_requirements(typeshed_dir / REQUIREMENTS)
27+
return TypeshedData(
28+
mypy_version=requirements["mypy"],
29+
pyright_version=pyproject["tool"]["typeshed"]["pyright_version"],
30+
pytype_version=requirements["pytype"],
31+
)
32+
33+
34+
def _read_pyproject_toml(path: Path) -> dict[str, Any]:
35+
with path.open("rb") as f:
36+
return toml_load(f)
37+
38+
39+
def _read_requirements(path: Path) -> dict[str, str]:
40+
requirements = {}
41+
with path.open() as f:
42+
for line in f:
43+
line = line.strip()
44+
line = line.split("#")[0] # strip comments
45+
line = line.split(";")[0] # strip extras
46+
if not line.strip(): # skip empty lines
47+
continue
48+
if "==" in line:
49+
name, version = line.split("==")
50+
else:
51+
name = line
52+
version = ""
53+
requirements[name.strip()] = version.strip()
54+
return requirements
55+
56+
57+
if __name__ == "__main__":
58+
parser = argparse.ArgumentParser()
59+
parser.add_argument("typeshed_dir", help="Path to typeshed checkout directory")
60+
args = parser.parse_args()
61+
data = read_typeshed_data(Path(args.typeshed_dir))
62+
for field in fields(data):
63+
print(f"{field.name}: {getattr(data, field.name)}")

0 commit comments

Comments
 (0)