Skip to content

Commit fde50f0

Browse files
committed
gh-141004: check-c-api-docs: Gather names from ReST upfront
This makes the check much faster. It also found 4 additional undocumented APIs, as it does not match substrings (e.g. documenting `PyErr_WarnEx` doesn't mean that `PyErr_Warn` is documented)
1 parent efaa56f commit fde50f0

File tree

2 files changed

+23
-20
lines changed

2 files changed

+23
-20
lines changed

Tools/check-c-api-docs/ignored_c_api.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,11 @@ Py_FrozenMain
9191
# cpython/unicodeobject.h
9292
PyUnicode_IS_COMPACT
9393
PyUnicode_IS_COMPACT_ASCII
94+
# pythonrun.h
95+
PyErr_Display
96+
# cpython/objimpl.h
97+
PyObject_GET_WEAKREFS_LISTPTR
98+
# cpython/pythonrun.h
99+
PyOS_Readline
100+
# cpython/warnings.h
101+
PyErr_Warn

Tools/check-c-api-docs/main.py

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
SIMPLE_MACRO_REGEX = re.compile(r"# *define *(\w+)(\(.+\))? ")
99
SIMPLE_INLINE_REGEX = re.compile(r"static inline .+( |\n)(\w+)")
1010
SIMPLE_DATA_REGEX = re.compile(r"PyAPI_DATA\(.+\) (\w+)")
11+
API_NAME_REGEX = re.compile(r'\bP[yY][a-zA-Z0-9_]+')
1112

1213
CPYTHON = Path(__file__).parent.parent.parent
1314
INCLUDE = CPYTHON / "Include"
@@ -72,24 +73,10 @@ def found_ignored_documented(singular: bool) -> str:
7273
)
7374

7475

75-
def is_documented(name: str) -> bool:
76-
"""
77-
Is a name present in the C API documentation?
78-
"""
79-
for path in C_API_DOCS.iterdir():
80-
if path.is_dir():
81-
continue
82-
if path.suffix != ".rst":
83-
continue
84-
85-
text = path.read_text(encoding="utf-8")
86-
if name in text:
87-
return True
88-
89-
return False
90-
91-
92-
def scan_file_for_docs(filename: str, text: str) -> tuple[list[str], list[str]]:
76+
def scan_file_for_docs(
77+
filename: str,
78+
text: str,
79+
names: set[str]) -> tuple[list[str], list[str]]:
9380
"""
9481
Scan a header file for C API functions.
9582
"""
@@ -98,7 +85,7 @@ def scan_file_for_docs(filename: str, text: str) -> tuple[list[str], list[str]]:
9885
colors = _colorize.get_colors()
9986

10087
def check_for_name(name: str) -> None:
101-
documented = is_documented(name)
88+
documented = name in names
10289
if documented and (name in IGNORED):
10390
documented_ignored.append(name)
10491
elif not documented and (name not in IGNORED):
@@ -152,6 +139,14 @@ def check_for_name(name: str) -> None:
152139

153140

154141
def main() -> None:
142+
print("Gathering C API names from docs...")
143+
names = set()
144+
for path in C_API_DOCS.glob('**/*.rst'):
145+
text = path.read_text(encoding="utf-8")
146+
for name in API_NAME_REGEX.findall(text):
147+
names.add(name)
148+
print(f"Got {len(names)} names!")
149+
155150
print("Scanning for undocumented C API functions...")
156151
files = [*INCLUDE.iterdir(), *(INCLUDE / "cpython").iterdir()]
157152
all_missing: list[str] = []
@@ -162,7 +157,7 @@ def main() -> None:
162157
continue
163158
assert file.exists()
164159
text = file.read_text(encoding="utf-8")
165-
missing, ignored = scan_file_for_docs(str(file.relative_to(INCLUDE)), text)
160+
missing, ignored = scan_file_for_docs(str(file.relative_to(INCLUDE)), text, names)
166161
all_found_ignored += ignored
167162
all_missing += missing
168163

0 commit comments

Comments
 (0)