mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-10-02 22:38:01 +00:00
28a1afca63
The base image for the "check-tree" test got bumped to Fedora 39. This brings a new python-black version (23.7.0 vs. 22.8.0) and requires reformatting. Maybe we should stick to 22.8.0, via `pip install`. But it seems better to just follow the latest black version (the one from current Fedora). So do the reformatting instead. https://black.readthedocs.io/en/stable/change_log.html#id38
311 lines
7.9 KiB
Python
Executable file
311 lines
7.9 KiB
Python
Executable file
#!/usr/bin/env python
|
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
from __future__ import print_function
|
|
|
|
import collections
|
|
import os
|
|
import sys
|
|
import xml.etree.ElementTree as ET
|
|
|
|
###############################################################################
|
|
|
|
|
|
DEBUG = os.environ.get("NM_GENERATE_DOCS_NM_SETTINGS_DOCS_MERGE_DEBUG", None) == "1"
|
|
|
|
|
|
def dbg(msg):
|
|
if DEBUG:
|
|
print("%s" % (msg,))
|
|
|
|
|
|
###############################################################################
|
|
|
|
_setting_name_order = [
|
|
"connection",
|
|
"6lowpan",
|
|
"802-1x",
|
|
"adsl",
|
|
"bluetooth",
|
|
"bond",
|
|
"bridge",
|
|
"bridge-port",
|
|
"cdma",
|
|
"dcb",
|
|
"dummy",
|
|
"ethtool",
|
|
"generic",
|
|
"gsm",
|
|
"infiniband",
|
|
"ipv4",
|
|
"ipv6",
|
|
"ip-tunnel",
|
|
"macsec",
|
|
"macvlan",
|
|
"match",
|
|
"802-11-olpc-mesh",
|
|
"ovs-bridge",
|
|
"ovs-dpdk",
|
|
"ovs-interface",
|
|
"ovs-patch",
|
|
"ovs-port",
|
|
"ppp",
|
|
"pppoe",
|
|
"proxy",
|
|
"serial",
|
|
"sriov",
|
|
"tc",
|
|
"team",
|
|
"team-port",
|
|
"tun",
|
|
"user",
|
|
"vlan",
|
|
"vpn",
|
|
"vrf",
|
|
"vxlan",
|
|
"wifi-p2p",
|
|
"wimax",
|
|
"802-3-ethernet",
|
|
"wireguard",
|
|
"802-11-wireless",
|
|
"802-11-wireless-security",
|
|
"wpan",
|
|
]
|
|
|
|
|
|
def _setting_name_order_idx(name):
|
|
try:
|
|
return _setting_name_order.index(name)
|
|
except ValueError:
|
|
return len(_setting_name_order)
|
|
|
|
|
|
def key_fcn_setting_name(n1):
|
|
return (_setting_name_order_idx(n1), n1)
|
|
|
|
|
|
def iter_keys_of_dicts(dicts, key=None):
|
|
keys = set([k for d in dicts for k in d.keys()])
|
|
return sorted(keys, key=key)
|
|
|
|
|
|
def node_to_dict(node, tag, key_attr):
|
|
dictionary = collections.OrderedDict()
|
|
if node is not None:
|
|
for n in node.iter(tag):
|
|
k = n.get(key_attr)
|
|
assert k is not None
|
|
dictionary[k] = n
|
|
return dictionary
|
|
|
|
|
|
def node_get_attr(nodes, name):
|
|
for n in nodes:
|
|
if n is None:
|
|
continue
|
|
x = n.get(name, None)
|
|
if x:
|
|
return x
|
|
return None
|
|
|
|
|
|
def node_set_attr(dst_node, name, nodes):
|
|
x = node_get_attr(nodes, name)
|
|
if x:
|
|
dst_node.set(name, x)
|
|
|
|
|
|
def find_attr(properties_attrs, name):
|
|
for p_attr in properties_attrs:
|
|
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(
|
|
"We expect both a <description> and <description-docbook> tag, but we only have %s"
|
|
% (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 <deprecated-docbook> 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
|
|
|
|
gl_only_properties_from = None
|
|
gl_output_xml_file = None
|
|
gl_input_files = []
|
|
|
|
|
|
def usage_and_quit(exit_code):
|
|
print(
|
|
"%s [--only-properties-from SLECTOR_FILE] [OUT_FILE] [SETTING_XML [...]]"
|
|
% (sys.argv[0])
|
|
)
|
|
exit(exit_code)
|
|
|
|
|
|
i = 1
|
|
special_args = True
|
|
while i < len(sys.argv):
|
|
if special_args and sys.argv[i] in ["-h", "--help"]:
|
|
usage_and_quit(0)
|
|
elif special_args and sys.argv[i] == "--only-properties-from":
|
|
i += 1
|
|
gl_only_properties_from = sys.argv[i]
|
|
elif special_args and sys.argv[i] == "--":
|
|
special_args = False
|
|
elif gl_output_xml_file is None:
|
|
gl_output_xml_file = sys.argv[i]
|
|
else:
|
|
gl_input_files.append(sys.argv[i])
|
|
i += 1
|
|
if len(gl_input_files) < 2:
|
|
usage_and_quit(1)
|
|
|
|
###############################################################################
|
|
|
|
for f in gl_input_files:
|
|
dbg("> input file %s" % (f))
|
|
|
|
xml_roots = [ET.parse(f).getroot() for f in gl_input_files]
|
|
|
|
assert all([root.tag == "nm-setting-docs" for root in xml_roots])
|
|
|
|
|
|
def skip_property(setting_name, property_name):
|
|
return False
|
|
|
|
|
|
if gl_only_properties_from:
|
|
xml_root = ET.parse(gl_only_properties_from).getroot()
|
|
opf_setting_root = node_to_dict(xml_root, "setting", "name")
|
|
opf_cache = {}
|
|
|
|
def skip_property(setting_name, property_name):
|
|
if setting_name not in opf_cache:
|
|
s = opf_setting_root.get(setting_name)
|
|
if s is not None:
|
|
s = node_to_dict(s, "property", "name")
|
|
opf_cache[setting_name] = s
|
|
else:
|
|
s = opf_cache[setting_name]
|
|
if not s:
|
|
return True
|
|
if property_name is not None:
|
|
p = s.get(property_name)
|
|
if p is None:
|
|
return True
|
|
return False
|
|
|
|
|
|
settings_roots = [node_to_dict(root, "setting", "name") for root in xml_roots]
|
|
|
|
root_node = ET.Element("nm-setting-docs")
|
|
|
|
for setting_name in iter_keys_of_dicts(settings_roots, key_fcn_setting_name):
|
|
dbg("> > setting_name: %s" % (setting_name))
|
|
|
|
if skip_property(setting_name, None):
|
|
dbg("> > > skip (only-properties-from)")
|
|
continue
|
|
|
|
settings = [d.get(setting_name) for d in settings_roots]
|
|
|
|
properties = [node_to_dict(s, "property", "name") for s in settings]
|
|
|
|
setting_node = ET.SubElement(root_node, "setting")
|
|
|
|
setting_node.set("name", setting_name)
|
|
|
|
node_set_attr(setting_node, "description", settings)
|
|
node_set_attr(setting_node, "name_upper", settings)
|
|
node_set_attr(setting_node, "alias", settings)
|
|
|
|
dbg("> > > create node")
|
|
|
|
for property_name in iter_keys_of_dicts(properties):
|
|
dbg("> > > > property_name: %s" % (property_name))
|
|
|
|
properties_attrs = [p.get(property_name) for p in properties]
|
|
|
|
description, description_docbook = find_description(properties_attrs)
|
|
deprecated = find_deprecated(properties_attrs)
|
|
|
|
if skip_property(setting_name, property_name):
|
|
dbg("> > > > skip (only-properties-from)")
|
|
continue
|
|
|
|
property_node = ET.SubElement(setting_node, "property")
|
|
property_node.set("name", property_name)
|
|
property_node.set("name_upper", property_name.upper().replace("-", "_"))
|
|
|
|
dbg("> > > > > create node")
|
|
|
|
x = node_get_attr(properties_attrs, "format")
|
|
if x:
|
|
property_node.set("type", x)
|
|
else:
|
|
node_set_attr(property_node, "type", properties_attrs)
|
|
|
|
node_set_attr(property_node, "values", properties_attrs)
|
|
node_set_attr(property_node, "special-values", properties_attrs)
|
|
node_set_attr(property_node, "default", properties_attrs)
|
|
node_set_attr(property_node, "alias", properties_attrs)
|
|
|
|
if description_docbook is not None:
|
|
property_node.insert(0, description_docbook)
|
|
if description is not None:
|
|
property_node.append(description)
|
|
|
|
if deprecated is not None:
|
|
property_node.insert(0, deprecated)
|
|
|
|
ET.ElementTree(root_node).write(gl_output_xml_file)
|