[3.14] gh-139590: Stricter ruff rules for Tools/wasm (GH-139752) (#139811)

Co-authored-by: sobolevn <mail@sobolevn.me>
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
This commit is contained in:
Miss Islington (bot) 2025-10-14 09:29:32 +02:00 committed by GitHub
parent 7a13953bc3
commit 5848d80536
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 53 additions and 77 deletions

View file

@ -29,7 +29,6 @@ on:
- "Tools/jit/**"
- "Tools/peg_generator/**"
- "Tools/requirements-dev.txt"
- "Tools/wasm/**"
workflow_dispatch:
permissions:
@ -61,7 +60,6 @@ jobs:
"Tools/clinic",
"Tools/jit",
"Tools/peg_generator",
"Tools/wasm",
]
steps:
- uses: actions/checkout@v4

View file

@ -26,6 +26,10 @@ repos:
name: Run Ruff (lint) on Tools/peg_generator/
args: [--exit-non-zero-on-fix, --config=Tools/peg_generator/.ruff.toml]
files: ^Tools/peg_generator/
- id: ruff-check
name: Run Ruff (lint) on Tools/wasm/
args: [--exit-non-zero-on-fix, --config=Tools/wasm/.ruff.toml]
files: ^Tools/wasm/
- id: ruff-format
name: Run Ruff (format) on Doc/
args: [--check]

View file

@ -22,7 +22,4 @@ select = [
]
ignore = [
"E501", # Line too long
"F541", # f-string without any placeholders
"PYI024", # Use `typing.NamedTuple` instead of `collections.namedtuple`
"PYI025", # Use `from collections.abc import Set as AbstractSet`
]

View file

@ -3,16 +3,16 @@
import argparse
import contextlib
import functools
import hashlib
import os
import shutil
import subprocess
import sys
import sysconfig
import hashlib
import tempfile
from urllib.request import urlopen
from pathlib import Path
from textwrap import dedent
from urllib.request import urlopen
try:
from os import process_cpu_count as cpu_count
@ -33,9 +33,7 @@ HOST_DIR = HOST_BUILD_DIR / "python"
PREFIX_DIR = CROSS_BUILD_DIR / HOST_TRIPLE / "prefix"
LOCAL_SETUP = CHECKOUT / "Modules" / "Setup.local"
LOCAL_SETUP_MARKER = "# Generated by Tools/wasm/emscripten.py\n".encode(
"utf-8"
)
LOCAL_SETUP_MARKER = b"# Generated by Tools/wasm/emscripten.py\n"
def updated_env(updates={}):
@ -432,6 +430,7 @@ def main():
make_build,
configure_host,
make_host,
clean,
):
subcommand.add_argument(
"--quiet",

View file

@ -15,7 +15,6 @@ import pathlib
import sys
import sysconfig
import zipfile
from typing import Dict
# source directory
SRCDIR = pathlib.Path(__file__).parents[3].absolute()
@ -134,7 +133,7 @@ def create_stdlib_zip(
pzf.writepy(entry, filterfunc=filterfunc)
def detect_extension_modules(args: argparse.Namespace) -> Dict[str, bool]:
def detect_extension_modules(args: argparse.Namespace) -> dict[str, bool]:
modules = {}
# disabled by Modules/Setup.local ?
@ -149,7 +148,7 @@ def detect_extension_modules(args: argparse.Namespace) -> Dict[str, bool]:
# disabled by configure?
with open(args.sysconfig_data) as f:
data = f.read()
loc: Dict[str, Dict[str, str]] = {}
loc: dict[str, dict[str, str]] = {}
exec(data, globals(), loc)
for key, value in loc["build_time_vars"].items():

View file

@ -1,11 +0,0 @@
[mypy]
files = Tools/wasm/wasm_*.py
pretty = True
show_traceback = True
# Make sure the wasm can be run using Python 3.8:
python_version = 3.8
# Be strict...
strict = True
enable_error_code = truthy-bool,ignore-without-code

View file

@ -16,7 +16,6 @@ import sys
import sysconfig
import tempfile
CHECKOUT = pathlib.Path(__file__).parent.parent.parent.parent
assert (CHECKOUT / "configure").is_file(), (
"Please update the location of the file"
@ -28,9 +27,9 @@ BUILD_DIR = CROSS_BUILD_DIR / sysconfig.get_config_var("BUILD_GNU_TYPE")
LOCAL_SETUP = CHECKOUT / "Modules" / "Setup.local"
LOCAL_SETUP_MARKER = (
"# Generated by Tools/wasm/wasi .\n"
"# Required to statically build extension modules."
).encode("utf-8")
b"# Generated by Tools/wasm/wasi .\n"
b"# Required to statically build extension modules."
)
WASI_SDK_VERSION = 24
@ -154,8 +153,7 @@ def build_python_is_pydebug():
test = "import sys, test.support; sys.exit(test.support.Py_DEBUG)"
result = subprocess.run(
[build_python_path(), "-c", test],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
capture_output=True,
)
return bool(result.returncode)

View file

@ -23,8 +23,8 @@ changes.
"""
import argparse
import enum
import dataclasses
import enum
import logging
import os
import pathlib
@ -39,18 +39,12 @@ import tempfile
import time
import warnings
import webbrowser
from collections.abc import Callable, Iterable
# for Python 3.8
from typing import (
cast,
Any,
Callable,
Dict,
Iterable,
List,
Optional,
Tuple,
Union,
cast,
)
logger = logging.getLogger("wasm_build")
@ -122,7 +116,7 @@ https://wasmtime.dev/ to install wasmtime.
def parse_emconfig(
emconfig: pathlib.Path = EM_CONFIG,
) -> Tuple[pathlib.Path, pathlib.Path]:
) -> tuple[pathlib.Path, pathlib.Path]:
"""Parse EM_CONFIG file and lookup EMSCRIPTEN_ROOT and NODE_JS.
The ".emscripten" config file is a Python snippet that uses "EM_CONFIG"
@ -134,7 +128,7 @@ def parse_emconfig(
with open(emconfig, encoding="utf-8") as f:
code = f.read()
# EM_CONFIG file is a Python snippet
local: Dict[str, Any] = {}
local: dict[str, Any] = {}
exec(code, globals(), local)
emscripten_root = pathlib.Path(local["EMSCRIPTEN_ROOT"])
node_js = pathlib.Path(local["NODE_JS"])
@ -192,16 +186,16 @@ class Platform:
name: str
pythonexe: str
config_site: Optional[pathlib.PurePath]
configure_wrapper: Optional[pathlib.Path]
make_wrapper: Optional[pathlib.PurePath]
environ: Dict[str, Any]
config_site: pathlib.PurePath | None
configure_wrapper: pathlib.Path | None
make_wrapper: pathlib.PurePath | None
environ: dict[str, Any]
check: Callable[[], None]
# Used for build_emports().
ports: Optional[pathlib.PurePath]
cc: Optional[pathlib.PurePath]
ports: pathlib.PurePath | None
cc: pathlib.PurePath | None
def getenv(self, profile: "BuildProfile") -> Dict[str, Any]:
def getenv(self, profile: "BuildProfile") -> dict[str, Any]:
return self.environ.copy()
@ -264,7 +258,7 @@ def _check_emscripten() -> None:
# git / upstream / tot-upstream installation
version = version[:-4]
version_tuple = cast(
Tuple[int, int, int], tuple(int(v) for v in version.split("."))
tuple[int, int, int], tuple(int(v) for v in version.split("."))
)
if version_tuple < EMSDK_MIN_VERSION:
raise ConditionError(
@ -388,7 +382,7 @@ class Host(enum.Enum):
return []
@property
def emport_args(self) -> List[str]:
def emport_args(self) -> list[str]:
"""Host-specific port args (Emscripten)."""
cls = type(self)
if self is cls.wasm64_emscripten:
@ -399,7 +393,7 @@ class Host(enum.Enum):
return []
@property
def embuilder_args(self) -> List[str]:
def embuilder_args(self) -> list[str]:
"""Host-specific embuilder args (Emscripten)."""
cls = type(self)
if self is cls.wasm64_emscripten:
@ -422,7 +416,7 @@ class EmscriptenTarget(enum.Enum):
return self in {cls.browser, cls.browser_debug}
@property
def emport_args(self) -> List[str]:
def emport_args(self) -> list[str]:
"""Target-specific port args."""
cls = type(self)
if self in {cls.browser_debug, cls.node_debug}:
@ -448,9 +442,9 @@ class BuildProfile:
name: str
support_level: SupportLevel
host: Host
target: Union[EmscriptenTarget, None] = None
dynamic_linking: Union[bool, None] = None
pthreads: Union[bool, None] = None
target: EmscriptenTarget | None = None
dynamic_linking: bool | None = None
pthreads: bool | None = None
default_testopts: str = "-j2"
@property
@ -474,7 +468,7 @@ class BuildProfile:
return self.builddir / "Makefile"
@property
def configure_cmd(self) -> List[str]:
def configure_cmd(self) -> list[str]:
"""Generate configure command"""
# use relative path, so WASI tests can find lib prefix.
# pathlib.Path.relative_to() does not work here.
@ -509,7 +503,7 @@ class BuildProfile:
return cmd
@property
def make_cmd(self) -> List[str]:
def make_cmd(self) -> list[str]:
"""Generate make command"""
cmd = ["make"]
platform = self.host.platform
@ -517,7 +511,7 @@ class BuildProfile:
cmd.insert(0, os.fspath(platform.make_wrapper))
return cmd
def getenv(self) -> Dict[str, Any]:
def getenv(self) -> dict[str, Any]:
"""Generate environ dict for platform"""
env = os.environ.copy()
if hasattr(os, "process_cpu_count"):
@ -531,7 +525,7 @@ class BuildProfile:
env.pop(key, None)
elif key == "PATH":
# list of path items, prefix with extra paths
new_path: List[pathlib.PurePath] = []
new_path: list[pathlib.PurePath] = []
new_path.extend(self.host.get_extra_paths())
new_path.extend(value)
env[key] = os.pathsep.join(os.fspath(p) for p in new_path)
@ -549,7 +543,7 @@ class BuildProfile:
self,
cmd: Iterable[str],
args: Iterable[str] = (),
cwd: Optional[pathlib.Path] = None,
cwd: pathlib.Path | None = None,
) -> int:
cmd = list(cmd)
cmd.extend(args)
@ -587,7 +581,7 @@ class BuildProfile:
self._check_execute()
return self.run_make("pythoninfo", *args)
def run_test(self, target: str, testopts: Optional[str] = None) -> int:
def run_test(self, target: str, testopts: str | None = None) -> int:
"""Run buildbottests"""
self._check_execute()
if testopts is None:
@ -823,10 +817,8 @@ parser.add_argument(
)
# Don't list broken and experimental variants in help
platforms_choices = list(p.name for p in _profiles) + ["cleanall"]
platforms_help = list(p.name for p in _profiles if p.support_level) + [
"cleanall"
]
platforms_choices = [p.name for p in _profiles] + ["cleanall"]
platforms_help = [p.name for p in _profiles if p.support_level] + ["cleanall"]
parser.add_argument(
"platform",
metavar="PLATFORM",
@ -834,18 +826,18 @@ parser.add_argument(
choices=platforms_choices,
)
ops = dict(
build="auto build (build 'build' Python, emports, configure, compile)",
configure="run ./configure",
compile="run 'make all'",
pythoninfo="run 'make pythoninfo'",
test="run 'make buildbottest TESTOPTS=...' (supports parallel tests)",
hostrunnertest="run 'make hostrunnertest TESTOPTS=...'",
repl="start interactive REPL / webserver + browser session",
clean="run 'make clean'",
cleanall="remove all build directories",
emports="build Emscripten port with embuilder (only Emscripten)",
)
ops = {
"build": "auto build (build 'build' Python, emports, configure, compile)",
"configure": "run ./configure",
"compile": "run 'make all'",
"pythoninfo": "run 'make pythoninfo'",
"test": "run 'make buildbottest TESTOPTS=...' (supports parallel tests)",
"hostrunnertest": "run 'make hostrunnertest TESTOPTS=...'",
"repl": "start interactive REPL / webserver + browser session",
"clean": "run 'make clean'",
"cleanall": "remove all build directories",
"emports": "build Emscripten port with embuilder (only Emscripten)",
}
ops_help = "\n".join(f"{op:16s} {help}" for op, help in ops.items())
parser.add_argument(
"ops",