systemd/tools/check-version-history.py
Antonio Alvarez Feijoo 2ad44c22fe
tools/check-version-history: skip test if lxml is not installed
```
================================= 1070/1408 ==================================
test:         systemd:dist / check-version-history
start time:   07:55:05
duration:     0.03s
result:       exit status 1
...
----------------------------------- stderr -----------------------------------
Traceback (most recent call last):
  File "/mnt/work/systemd/upstream-fork/main/tools/check-version-history.py", line 6, in <module>
    import lxml.etree as tree
ModuleNotFoundError: No module named 'lxml'
==============================================================================
```

Follow-up for 3691e7fce7
2024-04-10 11:10:02 +02:00

141 lines
4.3 KiB
Python

#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later
import os
import sys
try:
import lxml.etree as tree
except ImportError as e:
print(str(e), file=sys.stderr)
sys.exit(77)
_parser = tree.XMLParser(resolve_entities=False)
tree.set_default_parser(_parser)
def find_undocumented_functions(pages, ignorelist):
undocumented = []
for page in pages:
filename = os.path.basename(page)
pagetree = tree.parse(page)
assert pagetree.getroot().tag == "refentry"
hist_section = pagetree.find("refsect1[title='History']")
for func in pagetree.findall("//funcprototype/funcdef/function"):
path = f"/refsynopsisdiv/funcsynopsis/funcprototype/funcdef/function[.='{func.text}']"
assert pagetree.findall(path) == [func]
if (
hist_section is None
or hist_section.find(f"para/function[.='{func.text}()']") is None
):
if func.text not in ignorelist:
undocumented.append((filename, func.text))
return undocumented
def construct_path(element):
tag = element.tag
if tag == "refentry":
return ""
predicate = ""
if tag == "varlistentry":
text = "".join(element.find("term").itertext())
predicate = f'[term="{text}"]'
elif tag.startswith("refsect"):
text = "".join(element.find("title").itertext())
predicate = f'[title="{text}"]'
elif tag == "variablelist":
varlists = element.getparent().findall(tag)
if len(varlists) > 1:
predicate = f"[{varlists.index(element)+1}]"
return construct_path(element.getparent()) + "/" + tag + predicate
def find_undocumented_commands(pages, ignorelist):
undocumented = []
for page in pages:
filename = os.path.basename(page)
pagetree = tree.parse(page)
if pagetree.getroot().tag != "refentry":
continue
for varlistentry in pagetree.findall("*//variablelist/varlistentry"):
path = construct_path(varlistentry)
assert pagetree.findall(path) == [varlistentry]
listitem = varlistentry.find("listitem")
parent = listitem if listitem is not None else varlistentry
rev = parent.getchildren()[-1]
if rev.get("href") != "version-info.xml":
if (filename, path) not in ignorelist:
undocumented.append((filename, path))
return undocumented
def process_pages(pages):
command_pages = []
function_pages = []
for page in pages:
filename = os.path.basename(page)
if filename.startswith("org.freedesktop."): # dbus
continue
if (
filename.startswith("sd_")
or filename.startswith("sd-")
or filename.startswith("udev_")
):
function_pages.append(page)
continue
command_pages.append(page)
undocumented_commands = find_undocumented_commands(
command_pages, command_ignorelist
)
undocumented_functions = find_undocumented_functions(
function_pages, function_ignorelist
)
return undocumented_commands, undocumented_functions
if __name__ == "__main__":
with open(os.path.join(os.path.dirname(__file__), "command_ignorelist")) as f:
command_ignorelist = []
for l in f.read().splitlines():
if l.startswith("#"):
continue
fname, path = l.split(" ", 1)
path = path.replace("\\n", "\n")
command_ignorelist.append((fname, path))
with open(os.path.join(os.path.dirname(__file__), "function_ignorelist")) as f:
function_ignorelist = f.read().splitlines()
undocumented_commands, undocumented_functions = process_pages(sys.argv[1:])
if undocumented_commands or undocumented_functions:
for filename, func in undocumented_functions:
print(
f"Function {func}() in {filename} isn't documented in the History section."
)
for filename, path in undocumented_commands:
print(filename, path, "is undocumented")
if undocumented_commands:
print(
"Hint: if you reorganized this part of the documentation, "
"please update tools/commands_ignorelist."
)
sys.exit(1)