From 42aa2251855fc82935b54a5d52631b85c9b2a161 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 17 May 2023 12:19:34 +0200 Subject: [PATCH] docs: better handle description tags in generate-docs-nm-settings-docs-merge.py When we generate the manual page for nm-settings-nmcli, we run: "/usr/bin/python" \ ./tools/generate-docs-nm-settings-docs-merge.py \ --only-from-first \ man/nm-settings-docs-nmcli.xml \ src/nmcli/gen-metadata-nm-settings-nmcli.xml \ src/libnm-client-impl/nm-property-infos-nmcli.xml \ src/libnm-client-impl/nm-settings-docs-gir.xml If "gen-metadata-nm-settings-nmcli.xml" contains either a or a , then we must not continue searching the other XML documents. The user provided an explicit override, and fallback (search further) is wrong. Previously, we might take from the first file, and from the second file. As "man/nm-settings-nmcli.xsl" prefers , it takes the wrong text. Instead, as we search the files during merge, we must prefer the first one. Note that the change doesn't really matter anymore, because each XML now must also contain both and . There is an assertion for that. Also, stop generating . First, it lacked the important "since=" attribute and was necessary. Also, it's redundant and does not contain anything interesting. So far, we don't need special formatting for the deprecated message, and we likely never will. Also, stop accepting or generating the "description=" attribute. This should always be an XML element now. --- man/nm-settings-nmcli.xsl | 6 +- tools/generate-docs-nm-property-infos.py | 11 ++- tools/generate-docs-nm-settings-docs-gir.py | 9 +-- tools/generate-docs-nm-settings-docs-merge.py | 70 +++++++++++++++---- 4 files changed, 70 insertions(+), 26 deletions(-) diff --git a/man/nm-settings-nmcli.xsl b/man/nm-settings-nmcli.xsl index 13c20c99e8..5817e8e266 100644 --- a/man/nm-settings-nmcli.xsl +++ b/man/nm-settings-nmcli.xsl @@ -154,11 +154,11 @@ - + - + - + diff --git a/tools/generate-docs-nm-property-infos.py b/tools/generate-docs-nm-property-infos.py index 9c7b38da84..d7e3c8c29b 100755 --- a/tools/generate-docs-nm-property-infos.py +++ b/tools/generate-docs-nm-property-infos.py @@ -133,7 +133,6 @@ keywords = collections.OrderedDict( ) - def keywords_allowed(tag, keyword): # certain keywords might not be valid for some tags. # Currently, all of them are always valid. @@ -177,11 +176,17 @@ def write_data(tag, setting_node, line_no, parsed_data): and parsed_data.get("description-docbook", None) is None ): # we have a description, but no docbook. Generate one. - node = ET.SubElement(property_node, 'description-docbook') + node = ET.SubElement(property_node, "description-docbook") for l in re.split("\n", parsed_data["description"]): paragraph = ET.SubElement(node, "para") paragraph.text = l - + elif ( + parsed_data.get("description-docbook", None) is not None + and parsed_data.get("description", None) is None + ): + raise Exception( + 'Invalid configuration. When specifying "description-docbook:" there MUST be also a "description:"' + ) kwd_first_line_re = re.compile(r"^ *\* ([-a-z0-9]+): (.*)$") diff --git a/tools/generate-docs-nm-settings-docs-gir.py b/tools/generate-docs-nm-settings-docs-gir.py index 342985dc3a..b8f29d3bc3 100755 --- a/tools/generate-docs-nm-settings-docs-gir.py +++ b/tools/generate-docs-nm-settings-docs-gir.py @@ -328,12 +328,9 @@ def main(gir_path_str, output_path_str): }, ).text = deprecated_desc - deprecated_docbook = ET.SubElement( - property_element, - "deprecated-docbook", - ) - - create_desc_docbook(deprecated_docbook, deprecated_desc) + # The text should only be one line. Otherwise, our simple "" element + # cannot be rendered nicely. + assert re.split("\n", deprecated_desc) == [deprecated_desc] docs_gir.write( output_path_str, diff --git a/tools/generate-docs-nm-settings-docs-merge.py b/tools/generate-docs-nm-settings-docs-merge.py index d61c7bd63e..69a972d65a 100755 --- a/tools/generate-docs-nm-settings-docs-merge.py +++ b/tools/generate-docs-nm-settings-docs-merge.py @@ -113,12 +113,62 @@ def node_set_attr(dst_node, name, nodes): def find_attr(properties_attrs, name): for p_attr in properties_attrs: - if p_attr is not None: - p_attr = p_attr.find(name) + if p_attr is None: + continue + p_attr = p_attr.find(name) if p_attr is not None: return p_attr +def find_description(properties_attrs): + for p in properties_attrs: + if p is None: + continue + + # These are not attributes, but XML element. + assert p.get("description", None) is None + assert p.get("description-docbook", None) is None + + p_elem = p.find("description") + p_elem_docbook = p.find("description-docbook") + + if p_elem is not None or p_elem_docbook is not None: + if p_elem is None or p_elem_docbook is None: + # invalid input! + if p_elem: + s = ET.tostring(p_elem) + else: + s = ET.tostring(p_elem_docbook) + raise Exception( + f"We expect both a and tag, but we only have {s}" + ) + return p_elem, p_elem_docbook + + return None, None + + +def find_deprecated(properties_attrs): + for p in properties_attrs: + if p is None: + continue + + # These are not attributes, but XML element. + assert p.get("deprecated", None) is None + assert p.get("deprecated-docbook", None) is None + + # We don't expect a tag. + assert p.find("deprecated-docbook") is None + + p_elem = p.find("deprecated") + + if p_elem is not None: + # We require a "since" attribute + assert p_elem.get("since", None) is not None + return p_elem + + return None + + ############################################################################### gl_only_from_first = False @@ -181,10 +231,9 @@ for setting_name in iter_keys_of_dicts(settings_roots, key_fcn_setting_name): dbg("> > > > property_name: %s" % (property_name)) properties_attrs = [p.get(property_name) for p in properties] - description_docbook = find_attr(properties_attrs, "description-docbook") - description = find_attr(properties_attrs, "description") - deprecated_docbook = find_attr(properties_attrs, "deprecated-docbook") - deprecated = find_attr(properties_attrs, "deprecated") + + description, description_docbook = find_description(properties_attrs) + deprecated = find_deprecated(properties_attrs) if gl_only_from_first and properties_attrs[0] is None: dbg("> > > > skip (only-from-first") @@ -203,20 +252,13 @@ for setting_name in iter_keys_of_dicts(settings_roots, key_fcn_setting_name): node_set_attr(property_node, "type", properties_attrs) node_set_attr(property_node, "default", properties_attrs) - desc_value = node_get_attr(properties_attrs, "description") node_set_attr(property_node, "alias", properties_attrs) if description_docbook is not None: property_node.insert(0, description_docbook) - if desc_value: - description = ET.Element("description") - description.text = desc_value - property_node.append(description) - elif description is not None: + if description is not None: property_node.append(description) - if deprecated_docbook is not None: - property_node.insert(0, deprecated_docbook) if deprecated is not None: property_node.insert(0, deprecated)