Skip to content

gh-132390: Apply Ruff linting to Tools/build #132391

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 46 commits into from
Apr 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
9cf54b1
lint `Tools/build/check_extension_modules.py`
picnixz Apr 10, 2025
7ee999a
lint `Tools/build/compute-changes.py`
picnixz Apr 10, 2025
c3dd400
lint `Tools/build/deepfreeze.py`
picnixz Apr 10, 2025
766a6dd
lint `Tools/build/freeze_modules.py`
picnixz Apr 10, 2025
2d4f851
lint `Tools/build/generate-build-details.py`
picnixz Apr 10, 2025
d95fb61
lint `Tools/build/generate_global_objects.py`
picnixz Apr 10, 2025
6805f4a
lint `Tools/build/generate_levenshtein_examples.py`
picnixz Apr 10, 2025
ebd1007
lint `Tools/build/generate_re_casefix.py`
picnixz Apr 10, 2025
cadcb03
lint `Tools/build/generate_sbom.py`
picnixz Apr 10, 2025
7965920
lint `Tools/build/generate_sre_constants.py`
picnixz Apr 10, 2025
3bdf24a
lint `Tools/build/generate_stdlib_module_names.py`
picnixz Apr 10, 2025
72e5eed
lint `Tools/build/generate_token.py`
picnixz Apr 10, 2025
23e1f43
lint `Tools/build/parse_html5_entities.py`
picnixz Apr 10, 2025
8b2d4da
lint `Tools/build/regen-configure.sh`
picnixz Apr 10, 2025
8717002
lint `Tools/build/smelly.py`
picnixz Apr 10, 2025
42922db
lint `Tools/build/stable_abi.py`
picnixz Apr 10, 2025
6cf0357
lint `Tools/build/umarshal.py`
picnixz Apr 10, 2025
921cc08
lint `Tools/build/verify_ensurepip_wheels.py`
picnixz Apr 10, 2025
7401104
force explicit Python version for known files
picnixz Apr 11, 2025
effe679
minimize implementation diff
picnixz Apr 11, 2025
043805d
minimize implementation diff
picnixz Apr 11, 2025
859bc91
minimize implementation diff
picnixz Apr 11, 2025
d0b1df4
minimize implementation diff
picnixz Apr 11, 2025
af4a0ea
fixup lint?
picnixz Apr 11, 2025
a7d4b02
Revert "fixup lint?"
picnixz Apr 11, 2025
6cfee13
bump ruff version
picnixz Apr 11, 2025
b14db8b
deepfreeze.py: address Hugo's review
picnixz Apr 11, 2025
3aaf9cc
remove un-necessary comment
picnixz Apr 11, 2025
dd8bfbb
update pre-commit config
picnixz Apr 11, 2025
175b1ee
fixup pattern
picnixz Apr 11, 2025
ba937f9
Consolidate E501 ignores
AA-Turner Apr 11, 2025
be3afe3
Consolidate E501 ignores
AA-Turner Apr 11, 2025
d2d7aa8
Consolidate UP031 ignores
AA-Turner Apr 11, 2025
e71dbd4
Consolidate UP031 ignores
AA-Turner Apr 11, 2025
c7dd4c4
Revert selected changes
AA-Turner Apr 11, 2025
d4c5707
Revert whitespace
AA-Turner Apr 11, 2025
407abef
Ignore F541
AA-Turner Apr 11, 2025
0986b77
Ignore UP038 (not recommended)
AA-Turner Apr 11, 2025
673aca0
Prefer 'encoding' over 'text=True'
AA-Turner Apr 11, 2025
ff185a4
Merge branch 'main' into lint/ruff/tools-build-fix-132390
picnixz Apr 12, 2025
561e343
Merge branch 'main' into lint/ruff/tools-build-fix-132390
picnixz Apr 13, 2025
4308c1f
align strings
picnixz Apr 13, 2025
eae5215
add new line
picnixz Apr 13, 2025
99a41ef
ignore UP031 for `Tools/build/generate_token.py`
picnixz Apr 13, 2025
26b288a
Merge remote-tracking branch 'upstream/main' into lint/ruff/tools-bui…
picnixz Apr 19, 2025
75a08cf
address review
picnixz Apr 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ repos:
args: [--exit-non-zero-on-fix]
files: ^Lib/test/
- id: ruff
name: Run Ruff (lint) on Tools/build/check_warnings.py
name: Run Ruff (lint) on Tools/build/
args: [--exit-non-zero-on-fix, --config=Tools/build/.ruff.toml]
files: ^Tools/build/check_warnings.py
files: ^Tools/build/
- id: ruff
name: Run Ruff (lint) on Argument Clinic
args: [--exit-non-zero-on-fix, --config=Tools/clinic/.ruff.toml]
Expand Down
19 changes: 19 additions & 0 deletions Tools/build/.ruff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,22 @@ select = [
"W", # pycodestyle
"YTT", # flake8-2020
]
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`
"UP038", # Use `X | Y` in `isinstance` call instead of `(X, Y)`
]

[per-file-target-version]
"deepfreeze.py" = "py310"
"stable_abi.py" = "py311" # requires 'tomllib'

[lint.per-file-ignores]
"{check_extension_modules,freeze_modules}.py" = [
"UP031", # Use format specifiers instead of percent format
]
"generate_{re_casefix,sre_constants,token}.py" = [
"UP031", # Use format specifiers instead of percent format
]
15 changes: 9 additions & 6 deletions Tools/build/check_extension_modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

See --help for more information
"""
import _imp
import argparse
import collections
import enum
Expand All @@ -27,12 +28,14 @@
import sys
import sysconfig
import warnings
import _imp

from collections.abc import Iterable
from importlib._bootstrap import _load as bootstrap_load
from importlib.machinery import BuiltinImporter, ExtensionFileLoader, ModuleSpec
from importlib.machinery import (
BuiltinImporter,
ExtensionFileLoader,
ModuleSpec,
)
from importlib.util import spec_from_file_location, spec_from_loader
from typing import Iterable

SRC_DIR = pathlib.Path(__file__).parent.parent.parent

Expand Down Expand Up @@ -195,7 +198,7 @@ def print_three_column(modinfos: list[ModuleInfo]):
# guarantee zip() doesn't drop anything
while len(names) % 3:
names.append("")
for l, m, r in zip(names[::3], names[1::3], names[2::3]):
for l, m, r in zip(names[::3], names[1::3], names[2::3]): # noqa: E741
print("%-*s %-*s %-*s" % (longest, l, longest, m, longest, r))

if verbose and self.builtin_ok:
Expand Down Expand Up @@ -420,7 +423,7 @@ def check_module_import(self, modinfo: ModuleInfo):
except ImportError as e:
logger.error("%s failed to import: %s", modinfo.name, e)
raise
except Exception as e:
except Exception:
if not hasattr(_imp, 'create_dynamic'):
logger.warning("Dynamic extension '%s' ignored", modinfo.name)
return
Expand Down
18 changes: 9 additions & 9 deletions Tools/build/deepfreeze.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import re
import time
import types
from typing import Dict, FrozenSet, TextIO, Tuple
from typing import TextIO

import umarshal

Expand Down Expand Up @@ -57,8 +57,8 @@ def get_localsplus(code: types.CodeType):


def get_localsplus_counts(code: types.CodeType,
names: Tuple[str, ...],
kinds: bytes) -> Tuple[int, int, int, int]:
names: tuple[str, ...],
kinds: bytes) -> tuple[int, int, int]:
nlocals = 0
ncellvars = 0
nfreevars = 0
Expand All @@ -84,7 +84,7 @@ def get_localsplus_counts(code: types.CodeType,
PyUnicode_4BYTE_KIND = 4


def analyze_character_width(s: str) -> Tuple[int, bool]:
def analyze_character_width(s: str) -> tuple[int, bool]:
maxchar = ' '
for c in s:
maxchar = max(maxchar, c)
Expand All @@ -109,7 +109,7 @@ class Printer:
def __init__(self, file: TextIO) -> None:
self.level = 0
self.file = file
self.cache: Dict[tuple[type, object, str], str] = {}
self.cache: dict[tuple[type, object, str], str] = {}
self.hits, self.misses = 0, 0
self.finis: list[str] = []
self.inits: list[str] = []
Expand Down Expand Up @@ -305,7 +305,7 @@ def generate_code(self, name: str, code: types.CodeType) -> str:
self.inits.append(f"_PyStaticCode_Init({name_as_code})")
return f"& {name}.ob_base.ob_base"

def generate_tuple(self, name: str, t: Tuple[object, ...]) -> str:
def generate_tuple(self, name: str, t: tuple[object, ...]) -> str:
if len(t) == 0:
return f"(PyObject *)& _Py_SINGLETON(tuple_empty)"
items = [self.generate(f"{name}_{i}", it) for i, it in enumerate(t)]
Expand Down Expand Up @@ -379,7 +379,7 @@ def generate_complex(self, name: str, z: complex) -> str:
self.write(f".cval = {{ {z.real}, {z.imag} }},")
return f"&{name}.ob_base"

def generate_frozenset(self, name: str, fs: FrozenSet[object]) -> str:
def generate_frozenset(self, name: str, fs: frozenset[object]) -> str:
try:
fs = sorted(fs)
except TypeError:
Expand Down Expand Up @@ -465,7 +465,7 @@ def generate(args: list[str], output: TextIO) -> None:
printer = Printer(output)
for arg in args:
file, modname = arg.rsplit(':', 1)
with open(file, "r", encoding="utf8") as fd:
with open(file, encoding="utf8") as fd:
source = fd.read()
if is_frozen_header(source):
code = decode_frozen_data(source)
Expand Down Expand Up @@ -513,7 +513,7 @@ def main() -> None:
if args.file:
if verbose:
print(f"Reading targets from {args.file}")
with open(args.file, "rt", encoding="utf-8-sig") as fin:
with open(args.file, encoding="utf-8-sig") as fin:
rules = [x.strip() for x in fin]
else:
rules = args.args
Expand Down
5 changes: 1 addition & 4 deletions Tools/build/freeze_modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
See the notes at the top of Python/frozen.c for more info.
"""

from collections import namedtuple
import hashlib
import ntpath
import os
import posixpath
from collections import namedtuple

from update_file import updating_file_with_tmpfile


ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
ROOT_DIR = os.path.abspath(ROOT_DIR)
FROZEN_ONLY = os.path.join(ROOT_DIR, 'Tools', 'freeze', 'flag.py')
Expand Down Expand Up @@ -482,7 +481,6 @@ def regen_frozen(modules):
header = relpath_for_posix_display(src.frozenfile, parentdir)
headerlines.append(f'#include "{header}"')

externlines = UniqueList()
bootstraplines = []
stdliblines = []
testlines = []
Expand Down Expand Up @@ -625,7 +623,6 @@ def regen_makefile(modules):
def regen_pcbuild(modules):
projlines = []
filterlines = []
corelines = []
for src in _iter_sources(modules):
pyfile = relpath_for_windows_display(src.pyfile, ROOT_DIR)
header = relpath_for_windows_display(src.frozenfile, ROOT_DIR)
Expand Down
5 changes: 3 additions & 2 deletions Tools/build/generate_global_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,8 @@ def generate_runtime_init(identifiers, strings):
break
else:
raise NotImplementedError
assert nsmallposints and nsmallnegints
assert nsmallposints
assert nsmallnegints

# Then target the runtime initializer.
filename = os.path.join(INTERNAL, 'pycore_runtime_init_generated.h')
Expand Down Expand Up @@ -434,7 +435,7 @@ def get_identifiers_and_strings() -> 'tuple[set[str], dict[str, str]]':
# To cover tricky cases (like "\n") we also generate C asserts.
raise ValueError(
'do not use &_Py_ID or &_Py_STR for one-character latin-1 '
+ f'strings, use _Py_LATIN1_CHR instead: {string!r}')
f'strings, use _Py_LATIN1_CHR instead: {string!r}')
if string not in strings:
strings[string] = name
elif name != strings[string]:
Expand Down
3 changes: 1 addition & 2 deletions Tools/build/generate_levenshtein_examples.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
"""Generate 10,000 unique examples for the Levenshtein short-circuit tests."""

import argparse
from functools import lru_cache
import json
import os.path
from functools import lru_cache
from random import choices, randrange


# This should be in sync with Lib/traceback.py. It's not importing those values
# because this script is being executed by PYTHON_FOR_REGEN and not by the in-tree
# build of Python.
Expand Down
4 changes: 2 additions & 2 deletions Tools/build/generate_re_casefix.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

def update_file(file, content):
try:
with open(file, 'r', encoding='utf-8') as fobj:
with open(file, encoding='utf-8') as fobj:
if fobj.read() == content:
return False
except (OSError, ValueError):
Expand Down Expand Up @@ -50,7 +50,7 @@ def main(outfile='Lib/re/_casefix.py'):
# List of codes of lowercased characters which have the same uppercase.
equivalent_lower_codes = [sorted(t)
for s in equivalent_chars
for t in [set(ord(c.lower()) for c in s)]
for t in [{ord(c.lower()) for c in s}]
if len(t) > 1]

bad_codes = []
Expand Down
13 changes: 7 additions & 6 deletions Tools/build/generate_sbom.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
"""Tool for generating Software Bill of Materials (SBOM) for Python's dependencies"""
import os
import re

import glob
import hashlib
import json
import glob
from pathlib import Path, PurePosixPath, PureWindowsPath
import os
import re
import subprocess
import sys
import urllib.request
import typing
import urllib.request
from pathlib import Path, PurePosixPath, PureWindowsPath

CPYTHON_ROOT_DIR = Path(__file__).parent.parent.parent

Expand Down Expand Up @@ -250,7 +251,7 @@ def check_sbom_packages(sbom_data: dict[str, typing.Any]) -> None:
license_concluded = package["licenseConcluded"]
error_if(
license_concluded != "NOASSERTION",
f"License identifier must be 'NOASSERTION'"
"License identifier must be 'NOASSERTION'"
)


Expand Down
2 changes: 1 addition & 1 deletion Tools/build/generate_sre_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

def update_file(file, content):
try:
with open(file, 'r') as fobj:
with open(file) as fobj:
if fobj.read() == content:
return False
except (OSError, ValueError):
Expand Down
1 change: 0 additions & 1 deletion Tools/build/generate_stdlib_module_names.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

from check_extension_modules import ModuleChecker


SCRIPT_NAME = 'Tools/build/generate_stdlib_module_names.py'

SRC_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
Expand Down
3 changes: 1 addition & 2 deletions Tools/build/generate_token.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

import re


SCRIPT_NAME = 'Tools/build/generate_token.py'
AUTO_GENERATED_BY_SCRIPT = f'Auto-generated by {SCRIPT_NAME}'
NT_OFFSET = 256
Expand Down Expand Up @@ -46,7 +45,7 @@ def load_tokens(path):

def update_file(file, content):
try:
with open(file, 'r') as fobj:
with open(file) as fobj:
if fobj.read() == content:
return False
except (OSError, ValueError):
Expand Down
18 changes: 9 additions & 9 deletions Tools/build/parse_html5_entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
Written by Ezio Melotti and Iuliia Proskurnia.
"""

import json
import os
import sys
import json
from urllib.request import urlopen
from html.entities import html5
from urllib.request import urlopen

SCRIPT_NAME = 'Tools/build/parse_html5_entities.py'
PAGE_URL = 'https://html.spec.whatwg.org/multipage/named-characters.html'
Expand All @@ -40,20 +40,20 @@ def compare_dicts(old, new):
"""Compare the old and new dicts and print the differences."""
added = new.keys() - old.keys()
if added:
print('{} entitie(s) have been added:'.format(len(added)))
print(f'{len(added)} entitie(s) have been added:')
for name in sorted(added):
print(' {!r}: {!r}'.format(name, new[name]))
print(f' {name!r}: {new[name]!r}')
removed = old.keys() - new.keys()
if removed:
print('{} entitie(s) have been removed:'.format(len(removed)))
print(f'{len(removed)} entitie(s) have been removed:')
for name in sorted(removed):
print(' {!r}: {!r}'.format(name, old[name]))
print(f' {name!r}: {old[name]!r}')
changed = set()
for name in (old.keys() & new.keys()):
if old[name] != new[name]:
changed.add((name, old[name], new[name]))
if changed:
print('{} entitie(s) have been modified:'.format(len(changed)))
print(f'{len(changed)} entitie(s) have been modified:')
for item in sorted(changed):
print(' {!r}: {!r} -> {!r}'.format(*item))

Expand Down Expand Up @@ -111,5 +111,5 @@ def write_items(entities, file=sys.stdout):
print('The current dictionary is updated.')
else:
compare_dicts(html5, new_html5)
print('Run "./python {0} --patch" to update Lib/html/entities.html '
'or "./python {0} --create" to see the generated ' 'dictionary.'.format(__file__))
print(f'Run "./python {__file__} --patch" to update Lib/html/entities.html '
f'or "./python {__file__} --create" to see the generated dictionary.')
11 changes: 5 additions & 6 deletions Tools/build/smelly.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import sys
import sysconfig


ALLOWED_PREFIXES = ('Py', '_Py')
if sys.platform == 'darwin':
ALLOWED_PREFIXES += ('__Py',)
Expand Down Expand Up @@ -52,8 +51,8 @@ def get_exported_symbols(library, dynamic=False):
if dynamic:
args.append('--dynamic')
args.append(library)
print("+ %s" % ' '.join(args))
proc = subprocess.run(args, stdout=subprocess.PIPE, universal_newlines=True)
print(f"+ {' '.join(args)}")
proc = subprocess.run(args, stdout=subprocess.PIPE, encoding='utf-8')
if proc.returncode:
sys.stdout.write(proc.stdout)
sys.exit(proc.returncode)
Expand All @@ -80,7 +79,7 @@ def get_smelly_symbols(stdout, dynamic=False):

symtype = parts[1].strip()
symbol = parts[-1]
result = '%s (type: %s)' % (symbol, symtype)
result = f'{symbol} (type: {symtype})'

if (symbol.startswith(ALLOWED_PREFIXES) or
symbol in EXCEPTIONS or
Expand Down Expand Up @@ -111,10 +110,10 @@ def check_library(library, dynamic=False):
print()
smelly_symbols.sort()
for symbol in smelly_symbols:
print("Smelly symbol: %s" % symbol)
print(f"Smelly symbol: {symbol}")

print()
print("ERROR: Found %s smelly symbols!" % len(smelly_symbols))
print(f"ERROR: Found {len(smelly_symbols)} smelly symbols!")
return len(smelly_symbols)


Expand Down
Loading
Loading