mirror of
https://github.com/astral-sh/ruff.git
synced 2026-10-28 10:45:37 +08:00
140 lines
3.9 KiB
Python
140 lines
3.9 KiB
Python
# /// script
|
|
# requires-python = ">=3.12"
|
|
# dependencies = []
|
|
#
|
|
# [tool.ty.rules]
|
|
# blanket-ignore-comment = "warn"
|
|
# missing-type-argument = "warn"
|
|
# possibly-unresolved-reference = "warn"
|
|
# unsound-return-statement = "warn"
|
|
# unsound-yield = "warn"
|
|
# unsupported-dynamic-base = "warn"
|
|
# division-by-zero = "warn"
|
|
# dynamic-function-decorator-return = "warn"
|
|
# unsound-assignment = "warn"
|
|
# redundant-condition-strict = "warn"
|
|
# disjoint-cast = "warn"
|
|
# missing-direct-dependency = "warn"
|
|
#
|
|
# [tool.uv]
|
|
# no-build = true
|
|
# exclude-newer = "P7D"
|
|
# ///
|
|
|
|
"""Script to generate `crates/ruff_python_stdlib/src/sys/builtin_modules.rs`.
|
|
|
|
This script requires `uvx` to be available on PATH.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import builtins
|
|
import subprocess
|
|
import textwrap
|
|
from functools import partial
|
|
from pathlib import Path
|
|
from typing import Final
|
|
|
|
MODULE_CRATE = "ruff_python_stdlib"
|
|
MODULE_PATH = Path("crates") / MODULE_CRATE / "src" / "sys" / "builtin_modules.rs"
|
|
PYTHON_VERSIONS: Final = range(8, 16) # Python 3.8 through 3.15
|
|
|
|
|
|
def run(command: list[str]) -> str:
|
|
try:
|
|
proc = subprocess.run(
|
|
command,
|
|
check=True,
|
|
text=True,
|
|
capture_output=True,
|
|
)
|
|
except subprocess.CalledProcessError as e:
|
|
print(e.stdout)
|
|
print(e.stderr)
|
|
raise
|
|
return proc.stdout
|
|
|
|
|
|
def builtin_modules_on_version(minor_version: int) -> set[str]:
|
|
command_1 = [
|
|
"uv",
|
|
"--managed-python",
|
|
"python",
|
|
"install",
|
|
f"python3.{minor_version}",
|
|
"--upgrade",
|
|
]
|
|
run(command_1)
|
|
command_2 = [
|
|
"uvx",
|
|
"--managed-python",
|
|
f"python3.{minor_version}",
|
|
"-c",
|
|
"import sys; print(sys.builtin_module_names)",
|
|
]
|
|
return set(eval(run(command_2)))
|
|
|
|
|
|
def generate_module() -> None:
|
|
with MODULE_PATH.open("w") as f:
|
|
print = partial(builtins.print, file=f)
|
|
|
|
print(
|
|
textwrap.dedent(
|
|
"""\
|
|
//! This file is generated by `scripts/generate_builtin_modules.py`
|
|
|
|
/// Return `true` if `module` is a [builtin module] on the given
|
|
/// Python 3 version.
|
|
///
|
|
/// "Builtin modules" are modules that are compiled directly into the
|
|
/// Python interpreter. These can never be shadowed by first-party
|
|
/// modules; the normal rules of module resolution do not apply to these
|
|
/// modules.
|
|
///
|
|
/// [builtin module]: https://docs.python.org/3/library/sys.html#sys.builtin_module_names
|
|
#[allow(clippy::unnested_or_patterns)]
|
|
pub fn is_builtin_module(minor_version: u8, module: &str) -> bool {
|
|
matches!((minor_version, module),
|
|
""",
|
|
)
|
|
)
|
|
|
|
modules_by_version = {
|
|
minor_version: builtin_modules_on_version(minor_version)
|
|
for minor_version in PYTHON_VERSIONS
|
|
}
|
|
|
|
# First, add a case for the modules that are in all versions.
|
|
ubiquitous_modules = set.intersection(*modules_by_version.values())
|
|
|
|
print("(_, ")
|
|
for i, module in enumerate(sorted(ubiquitous_modules)):
|
|
if i > 0:
|
|
print(" | ", end="")
|
|
print(f'"{module}"')
|
|
print(")")
|
|
|
|
# Next, add any version-specific modules.
|
|
for minor_version in PYTHON_VERSIONS:
|
|
version_modules = set.difference(
|
|
modules_by_version[minor_version],
|
|
ubiquitous_modules,
|
|
)
|
|
|
|
print(" | ")
|
|
print(f"({minor_version}, ")
|
|
for i, module in enumerate(sorted(version_modules)):
|
|
if i > 0:
|
|
print(" | ", end="")
|
|
print(f'"{module}"')
|
|
print(")")
|
|
|
|
print(")}")
|
|
|
|
subprocess.run(["cargo", "fmt", "--package", MODULE_CRATE], check=True)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
generate_module()
|