import argparse
import collections
-import sys
+import io
import os
import subprocess
-import io
+import sys
try:
from lxml import etree
except ImportError as e:
shlex_join = e
+
class NoCommand(Exception):
pass
+
BORING_INTERFACES = [
'org.freedesktop.DBus.Peer',
'org.freedesktop.DBus.Introspectable',
arguments = None
+
def xml_parser():
- return etree.XMLParser(no_network=True,
- remove_comments=False,
- strip_cdata=False,
- resolve_entities=False)
+ return etree.XMLParser(no_network=True, remove_comments=False, strip_cdata=False, resolve_entities=False)
+
def print_method(declarations, elem, *, prefix, file, is_signal=False):
name = elem.get('name')
if argname is None:
if arguments.print_errors:
- print(f'method {name}: argument {num+1} has no name', file=sys.stderr)
+ print(f'method {name}: argument {num + 1} has no name', file=sys.stderr)
argname = 'UNNAMED'
argtype = arg.get('type')
print(');', file=file)
+
ACCESS_MAP = {
- 'read' : 'readonly',
- 'write' : 'readwrite',
+ 'read': 'readonly',
+ 'write': 'readwrite',
}
+
def value_ellipsis(prop_type):
if prop_type == 's':
return "'...'"
if prop_type[0] == 'a':
inner = value_ellipsis(prop_type[1:])
- return f"[{inner}{', ...' if inner != '...' else ''}]"
+ return f'[{inner}{", ..." if inner != "..." else ""}]'
return '...'
+
def print_property(declarations, elem, *, prefix, file):
prop_name = elem.get('name')
prop_type = elem.get('type')
prop_access = ACCESS_MAP.get(prop_access, prop_access)
print(f'''{prefix}{prop_access} {prop_type} {prop_name} = {value_ellipsis(prop_type)};''', file=file)
+
def print_interface(iface, *, prefix, file, print_boring, only_interface, declarations):
name = iface.get('name')
- is_boring = (name in BORING_INTERFACES or
- only_interface is not None and name != only_interface)
+ is_boring = name in BORING_INTERFACES or only_interface is not None and name != only_interface
if is_boring and print_boring:
print(f'''{prefix}interface {name} {{ ... }};''', file=file)
print(f'''{prefix}}};''', file=file)
+
def check_documented(document, declarations, stats, interface, missing_version):
missing = []
- sections = document.findall("refsect1")
+ sections = document.findall('refsect1')
history_section = document.find("refsect1[title = 'History']")
if history_section is not None:
sections.remove(history_section)
missing.append((klass, item))
if history_section is None or history_section.find(predicate) is None:
- missing_version.append(f"{interface}.{item_repr}")
+ missing_version.append(f'{interface}.{item_repr}')
stats['missing'] += len(missing)
return missing
+
def xml_to_text(destination, xml, *, only_interface=None):
file = io.StringIO()
for print_boring in [False, True]:
for iface in xml.findall('./interface'):
- print_interface(iface, prefix=' ', file=file,
- print_boring=print_boring,
- only_interface=only_interface,
- declarations=declarations)
+ print_interface(
+ iface,
+ prefix=' ',
+ file=file,
+ print_boring=print_boring,
+ only_interface=only_interface,
+ declarations=declarations,
+ )
name = iface.get('name')
- if not name in BORING_INTERFACES:
+ if name not in BORING_INTERFACES:
interfaces.append(name)
print('''};''', file=file)
return file.getvalue(), declarations, interfaces
+
def subst_output(document, programlisting, stats, missing_version):
executable = programlisting.get('executable', None)
if executable is None:
parent.remove(child)
if child.tag is etree.Comment and 'not documented' in child.text:
parent.remove(child)
- if child.tag == "variablelist" and child.attrib.get("generated", False) == "True":
+ if child.tag == 'variablelist' and child.attrib.get('generated', False) == 'True':
parent.remove(child)
# insert pointer for systemd-directives generation
- the_tail = programlisting.tail #tail is erased by addnext, so save it here.
- prev_element = etree.Comment("Autogenerated cross-references for systemd.directives, do not edit")
+ the_tail = programlisting.tail # tail is erased by addnext, so save it here.
+ prev_element = etree.Comment('Autogenerated cross-references for systemd.directives, do not edit')
programlisting.addnext(prev_element)
programlisting.tail = the_tail
for interface in interfaces:
- variablelist = etree.Element("variablelist")
+ variablelist = etree.Element('variablelist')
variablelist.attrib['class'] = 'dbus-interface'
variablelist.attrib['generated'] = 'True'
variablelist.attrib['extra-ref'] = interface
prev_element.tail = the_tail
prev_element = variablelist
- for decl_type,decl_list in declarations.items():
+ for decl_type, decl_list in declarations.items():
for declaration in decl_list:
- variablelist = etree.Element("variablelist")
- variablelist.attrib['class'] = 'dbus-'+decl_type
+ variablelist = etree.Element('variablelist')
+ variablelist.attrib['class'] = 'dbus-' + decl_type
variablelist.attrib['generated'] = 'True'
if decl_type in ('method', 'signal'):
variablelist.attrib['extra-ref'] = declaration + '()'
prev_element.tail = the_tail
prev_element = variablelist
- last_element = etree.Comment("End of Autogenerated section")
+ last_element = etree.Comment('End of Autogenerated section')
prev_element.addnext(last_element)
prev_element.tail = the_tail
last_element.tail = the_tail
comment.tail = programlisting.tail
parent.insert(parent.index(programlisting) + 1, comment)
+
def process(page, missing_version):
src = open(page).read()
xml = etree.fromstring(src, parser=xml_parser())
out_text = etree.tostring(xml, encoding='unicode')
# massage format to avoid some lxml whitespace handling idiosyncrasies
# https://bugs.launchpad.net/lxml/+bug/526799
- out_text = (src[:src.find('<refentryinfo')] +
- out_text[out_text.find('<refentryinfo'):] +
- '\n')
+ out_text = src[: src.find('<refentryinfo')] + out_text[out_text.find('<refentryinfo') :] + '\n'
if not arguments.test:
with open(page, 'w') as out:
out.write(out_text)
- return { "stats" : stats, "modified" : out_text != src }
+ return {'stats': stats, 'modified': out_text != src}
+
def parse_args():
p = argparse.ArgumentParser()
- p.add_argument('--test', action='store_true',
- help='only verify that everything is up2date')
- p.add_argument('--build-dir', default='build')
- p.add_argument('pages', nargs='+')
+ p.add_argument(
+ '--test',
+ action='store_true',
+ help='only verify that everything is up2date',
+ )
+ p.add_argument(
+ '--build-dir',
+ default='build',
+ )
+ p.add_argument(
+ 'pages',
+ nargs='+',
+ )
opts = p.parse_args()
opts.print_errors = not opts.test
return opts
+
def main():
# pylint: disable=global-statement
global arguments
sys.exit(f"{arguments.build_dir} doesn't exist.")
missing_version = []
- stats = {page.split('/')[-1] : process(page, missing_version) for page in arguments.pages}
+ stats = {page.split('/')[-1]: process(page, missing_version) for page in arguments.pages}
ignore_list = open(os.path.join(os.path.dirname(__file__), 'dbus_ignorelist')).read().split()
missing_version = [x for x in missing_version if x not in ignore_list]
for missing in missing_version:
- print(f"{RED}Missing version information for {missing}{RESET}")
+ print(f'{RED}Missing version information for {missing}{RESET}')
if missing_version:
sys.exit(1)
# Let's print all statistics at the end
mlen = max(len(page) for page in stats)
total = sum((item['stats'] for item in stats.values()), start=collections.Counter())
- total = 'total', { "stats" : total, "modified" : False }
+ total = 'total', {'stats': total, 'modified': False}
modified = []
classification = 'OUTDATED' if arguments.test else 'MODIFIED'
for page, info in sorted(stats.items()) + [total]:
c = classification if info['modified'] else ''
if c:
modified.append(page)
- color = RED if m > t/2 else (YELLOW if m else GREEN)
+ color = RED if m > t / 2 else (YELLOW if m else GREEN)
print(f'{color}{p:{mlen + 1}} {t - m}/{t} {c}{RESET}')
if arguments.test and modified:
- sys.exit(f'Outdated pages: {", ".join(modified)}\n'
- f'Hint: ninja -C {arguments.build_dir} update-dbus-docs')
+ sys.exit(
+ f'Outdated pages: {", ".join(modified)}\n'
+ f'Hint: ninja -C {arguments.build_dir} update-dbus-docs'
+ ) # fmt: skip
+
if __name__ == '__main__':
main()