]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-131507: Add a way to recreate the `Misc/mypy` symlinks if missing (#132274)
authorŁukasz Langa <lukasz@langa.pl>
Tue, 8 Apr 2025 23:01:36 +0000 (01:01 +0200)
committerGitHub <noreply@github.com>
Tue, 8 Apr 2025 23:01:36 +0000 (01:01 +0200)
They will be removed in source tarballs so they don't appear
in the SBOM.

Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com>
.github/workflows/mypy.yml
Misc/mypy/README.md
Misc/mypy/make_symlinks.py [new file with mode: 0755]
Misc/mypy/typed-stdlib.txt [new file with mode: 0644]

index 6d1c6b5b5e6347f089621555b0c0909687deb7dc..212f3e8d70c836ce8ae393dee8bb2477f23fb7b3 100644 (file)
@@ -59,4 +59,5 @@ jobs:
           cache: pip
           cache-dependency-path: Tools/requirements-dev.txt
       - run: pip install -r Tools/requirements-dev.txt
+      - run: python3 Misc/mypy/make_symlinks.py --symlink
       - run: mypy --config-file ${{ matrix.target }}/mypy.ini
index 05eda6c0b82f0ad047bbeba27d53f46e4a044aab..03eb8bce8d51137650d5e70910f4b0e2f89d4237 100644 (file)
@@ -4,6 +4,7 @@ This directory stores symlinks to standard library modules and packages
 that are fully type-annotated and ready to be used in type checking of
 the rest of the stdlib or Tools/ and so on.
 
+## Why this is necessary
 Due to most of the standard library being untyped, we prefer not to
 point mypy directly at `Lib/` for type checking.  Additionally, mypy
 as a tool does not support shadowing typing-related standard libraries
@@ -11,6 +12,13 @@ like `types`, `typing`, and `collections.abc`.
 
 So instead, we set `mypy_path` to include this directory,
 which only links modules and packages we know are safe to be
-type-checked themselves and used as dependencies.
+type-checked themselves and used as dependencies.  See
+`Lib/_pyrepl/mypy.ini` for a usage example.
 
-See `Lib/_pyrepl/mypy.ini` for an example.
\ No newline at end of file
+## I want to add a new type-checked module
+Add it to `typed-stdlib.txt` and run `make_symlinks.py --symlink`.
+
+## I don't see any symlinks in this directory
+The symlinks in this directory are skipped in source tarballs
+in Python releases. This ensures they don't end up in the SBOM. To
+recreate them, run the `make_symlinks.py --symlink` script.
diff --git a/Misc/mypy/make_symlinks.py b/Misc/mypy/make_symlinks.py
new file mode 100755 (executable)
index 0000000..9150604
--- /dev/null
@@ -0,0 +1,60 @@
+#!/usr/bin/env python3
+from __future__ import annotations
+
+import argparse
+import os
+from pathlib import Path
+
+CURRENT_DIR = Path(__file__).parent
+MISC_DIR = CURRENT_DIR.parent
+REPO_ROOT = MISC_DIR.parent
+LIB_DIR = REPO_ROOT / "Lib"
+FILE_LIST = CURRENT_DIR / "typed-stdlib.txt"
+
+parser = argparse.ArgumentParser(prog="make_symlinks.py")
+parser.add_argument(
+    "--symlink",
+    action="store_true",
+    help="Create symlinks",
+)
+parser.add_argument(
+    "--clean",
+    action="store_true",
+    help="Delete any pre-existing symlinks",
+)
+
+args = parser.parse_args()
+
+if args.clean:
+    for entry in CURRENT_DIR.glob("*"):
+        if entry.is_symlink():
+            entry_at_root = entry.relative_to(REPO_ROOT)
+            print(f"removing pre-existing {entry_at_root}")
+            entry.unlink()
+
+for link in FILE_LIST.read_text().splitlines():
+    link = link.strip()
+    if not link or link.startswith('#'):
+        continue
+
+    src = LIB_DIR / link
+    dst = CURRENT_DIR / link
+    src_at_root = src.relative_to(REPO_ROOT)
+    dst_at_root = dst.relative_to(REPO_ROOT)
+    if (
+        dst.is_symlink()
+        and src.resolve(strict=True) == dst.resolve(strict=True)
+    ):
+        continue
+
+    if not args.symlink and args.clean:
+        # when the user called --clean without --symlink, don't report missing
+        # symlinks that we just deleted ourselves
+        continue
+
+    # we specifically want to create relative-path links with ..
+    src_rel = os.path.relpath(src, CURRENT_DIR)
+    action = "symlinking" if args.symlink else "missing symlink to"
+    print(f"{action} {src_at_root} at {dst_at_root}")
+    if args.symlink:
+        os.symlink(src_rel, dst)
diff --git a/Misc/mypy/typed-stdlib.txt b/Misc/mypy/typed-stdlib.txt
new file mode 100644 (file)
index 0000000..8cd6858
--- /dev/null
@@ -0,0 +1,4 @@
+# These libraries in the stdlib can be type-checked.
+
+_colorize.py
+_pyrepl