2021-04-22 18:41:50 -04:00
|
|
|
#!/usr/bin/env python
|
|
|
|
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
|
|
2022-08-29 10:37:06 +02:00
|
|
|
import os
|
2021-05-27 08:52:30 +02:00
|
|
|
import re
|
|
|
|
|
import sys
|
2022-08-29 10:37:06 +02:00
|
|
|
import collections
|
2021-05-05 21:51:58 -04:00
|
|
|
import xml.etree.ElementTree as ET
|
2021-04-22 18:41:50 -04:00
|
|
|
|
|
|
|
|
|
2022-08-29 10:37:06 +02:00
|
|
|
class LineError(Exception):
|
|
|
|
|
def __init__(self, line_no, msg):
|
|
|
|
|
Exception.__init__(self, msg)
|
|
|
|
|
self.line_no = line_no
|
|
|
|
|
|
|
|
|
|
|
man nm-setting-*: add "expand enumvals" capability to property-infos
In some cases, properties documentation might require to provide an
explanation of each of the possible values that the property accepts.
If the possible values are the variants of an enum, we can use the
introspection data to get all the possible values for that enum and
their descriptions. With that info, we can automatically generate the
documentation with an always up to date list of accepted values.
Add a new "expand enumvals" feature: it will convert a token with the
format `#EnumName:*` to a list of all the possible values. For the
docbook (description-docbook field in the XML), it is expanded to a
bulleted list of all the values and their respective documentations.
This feature is limited to the "property-infos" comments (those like
---nmcli---, ---dbus---, etc). This comments are used only to generate
the nm-settings-* manual pages. For the documentation under the doc/
folder this is not needed: it's not supported by gtkdoc and, anyway,
it's better to use just `#EnumName` that will generate an HTML link.
Additionally, expansion of `%ENUM_VALUE` is now supported in the
property-infos comments. Instead of expanding them in the same style
than gtkdoc "ENUM_VALUE (num)", it is expanded in a format more suitable
for the nm-setting-* manual pages:
- for nmcli: value_nick (num)
- others: num (value_nick)
Also, fix typo in meson build file propery -> property.
2023-08-22 12:39:42 +02:00
|
|
|
enums = {}
|
|
|
|
|
enumvals = {}
|
|
|
|
|
|
2022-08-29 10:37:06 +02:00
|
|
|
_dbg_level = 0
|
|
|
|
|
try:
|
|
|
|
|
_dbg_level = int(os.getenv("NM_DEBUG_GENERATE_DOCS", 0))
|
|
|
|
|
except Exception:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def dbg(msg, level=1):
|
|
|
|
|
if level <= _dbg_level:
|
|
|
|
|
print(msg)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def iter_unique(iterable, default=None):
|
|
|
|
|
found = False
|
|
|
|
|
for i in iterable:
|
|
|
|
|
assert not found
|
|
|
|
|
found = True
|
|
|
|
|
i0 = i
|
|
|
|
|
if found:
|
|
|
|
|
return i0
|
|
|
|
|
return default
|
|
|
|
|
|
2021-04-22 18:41:50 -04:00
|
|
|
|
2022-08-29 10:37:06 +02:00
|
|
|
def xnode_get_or_create(root_node, node_name, name):
|
|
|
|
|
# From root_node, get the node "<{node_name} name={name} .../>"
|
|
|
|
|
# or create one, if it doesn't exist.
|
|
|
|
|
node = iter_unique(
|
|
|
|
|
(node for node in root_node.findall(node_name) if node.attrib["name"] == name)
|
|
|
|
|
)
|
|
|
|
|
if node is None:
|
|
|
|
|
created = True
|
|
|
|
|
node = ET.SubElement(root_node, node_name, name=name)
|
|
|
|
|
else:
|
|
|
|
|
created = False
|
2021-04-22 18:41:50 -04:00
|
|
|
|
2022-08-29 10:37:06 +02:00
|
|
|
return node, created
|
|
|
|
|
|
|
|
|
|
|
man nm-setting-*: add "expand enumvals" capability to property-infos
In some cases, properties documentation might require to provide an
explanation of each of the possible values that the property accepts.
If the possible values are the variants of an enum, we can use the
introspection data to get all the possible values for that enum and
their descriptions. With that info, we can automatically generate the
documentation with an always up to date list of accepted values.
Add a new "expand enumvals" feature: it will convert a token with the
format `#EnumName:*` to a list of all the possible values. For the
docbook (description-docbook field in the XML), it is expanded to a
bulleted list of all the values and their respective documentations.
This feature is limited to the "property-infos" comments (those like
---nmcli---, ---dbus---, etc). This comments are used only to generate
the nm-settings-* manual pages. For the documentation under the doc/
folder this is not needed: it's not supported by gtkdoc and, anyway,
it's better to use just `#EnumName` that will generate an HTML link.
Additionally, expansion of `%ENUM_VALUE` is now supported in the
property-infos comments. Instead of expanding them in the same style
than gtkdoc "ENUM_VALUE (num)", it is expanded in a format more suitable
for the nm-setting-* manual pages:
- for nmcli: value_nick (num)
- others: num (value_nick)
Also, fix typo in meson build file propery -> property.
2023-08-22 12:39:42 +02:00
|
|
|
def init_enumvals(girxml):
|
|
|
|
|
ns_map = {
|
|
|
|
|
"c": "http://www.gtk.org/introspection/c/1.0",
|
|
|
|
|
"gi": "http://www.gtk.org/introspection/core/1.0",
|
|
|
|
|
"glib": "http://www.gtk.org/introspection/glib/1.0",
|
|
|
|
|
}
|
|
|
|
|
type_key = "{%s}type" % ns_map["c"]
|
|
|
|
|
identifier_key = "{%s}identifier" % ns_map["c"]
|
|
|
|
|
nick_key = "{%s}nick" % ns_map["glib"]
|
|
|
|
|
|
|
|
|
|
for enum in girxml.findall("./gi:namespace/gi:enumeration", ns_map):
|
|
|
|
|
enum_cname = enum.attrib[type_key]
|
|
|
|
|
enums[enum_cname] = []
|
|
|
|
|
for enumval in enum.findall("./gi:member", ns_map):
|
|
|
|
|
cname = enumval.attrib[identifier_key]
|
|
|
|
|
doc = enumval.find("./gi:doc", ns_map)
|
|
|
|
|
|
|
|
|
|
enums[enum_cname].append(cname)
|
|
|
|
|
enumvals[cname] = {
|
|
|
|
|
"value": enumval.attrib["value"],
|
|
|
|
|
"nick": enumval.attrib.get(nick_key, cname),
|
|
|
|
|
"doc": doc.text if doc is not None else None,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for enum in girxml.findall("./gi:namespace/gi:bitfield", ns_map):
|
|
|
|
|
enum_cname = enum.attrib[type_key]
|
|
|
|
|
enums[enum_cname] = []
|
|
|
|
|
for enumval in enum.findall("./gi:member", ns_map):
|
|
|
|
|
cname = enumval.attrib[identifier_key]
|
|
|
|
|
doc = enumval.find("./gi:doc", ns_map)
|
|
|
|
|
|
|
|
|
|
enums[enum_cname].append(cname)
|
|
|
|
|
enumvals[cname] = {
|
|
|
|
|
"value": "0x%x" % int(enumval.attrib["value"]),
|
|
|
|
|
"nick": enumval.attrib.get(nick_key, cname),
|
|
|
|
|
"doc": doc.text if doc is not None else None,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-08-29 10:37:06 +02:00
|
|
|
def get_setting_names(source_file):
|
|
|
|
|
m = re.match(r"^(.*)/libnm-core-impl/(nm-setting-[^/]*)\.c$", source_file)
|
|
|
|
|
assert m
|
|
|
|
|
|
|
|
|
|
path_prefix, file_base = (m.group(1), m.group(2))
|
|
|
|
|
|
|
|
|
|
if file_base == "nm-setting-ip-config":
|
|
|
|
|
# Special case ip-config, which is a base class.
|
2022-10-04 10:15:17 +02:00
|
|
|
return 0, ("ipv4", "ipv6")
|
2022-08-29 10:37:06 +02:00
|
|
|
|
|
|
|
|
header_file = "%s/libnm-core-public/%s.h" % (path_prefix, file_base)
|
2021-04-22 18:41:50 -04:00
|
|
|
|
|
|
|
|
try:
|
2022-08-29 10:37:06 +02:00
|
|
|
f = open(header_file, "r")
|
2021-04-22 18:41:50 -04:00
|
|
|
except OSError:
|
2022-08-29 10:37:06 +02:00
|
|
|
raise Exception(
|
|
|
|
|
'Can not open header file "%s" for "%s"' % (header_file, source_file)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
with f:
|
|
|
|
|
for line in f:
|
|
|
|
|
m = re.search(r"^#define +NM_SETTING_.+SETTING_NAME\s+\"(\S+)\"$", line)
|
|
|
|
|
if m:
|
2022-10-04 10:15:17 +02:00
|
|
|
return 1, (m.group(1),)
|
2022-08-29 10:37:06 +02:00
|
|
|
|
|
|
|
|
raise Exception(
|
|
|
|
|
'Can\'t find setting name in header file "%s" for "%s"'
|
|
|
|
|
% (header_file, source_file)
|
|
|
|
|
)
|
2021-04-22 18:41:50 -04:00
|
|
|
|
2022-08-29 10:37:06 +02:00
|
|
|
|
|
|
|
|
def get_file_infos(source_files):
|
2022-10-04 10:15:17 +02:00
|
|
|
# This function parses the source files and detects the
|
|
|
|
|
# used setting name. The returned sections are sorted by setting
|
|
|
|
|
# name.
|
|
|
|
|
#
|
|
|
|
|
# The file "nm-setting-ip-config.c" can contain information
|
|
|
|
|
# for "ipv4" and "ipv6" settings. Thus, to sort the files
|
|
|
|
|
# is a bit more involved.
|
|
|
|
|
|
|
|
|
|
# First, get a list of priority and setting-names that belong
|
|
|
|
|
# to the source file. Sort by priority,setting-names. It's
|
|
|
|
|
# important that "nm-setting-ip-config.c" gets parsed before
|
|
|
|
|
# "nm-setting-ip[46]-config.c".
|
|
|
|
|
file_infos = []
|
2022-08-29 10:37:06 +02:00
|
|
|
for source_file in source_files:
|
2022-10-04 10:15:17 +02:00
|
|
|
priority, setting_names = get_setting_names(source_file)
|
|
|
|
|
file_infos.append((priority, setting_names, source_file))
|
|
|
|
|
file_infos.sort()
|
|
|
|
|
|
|
|
|
|
d = {}
|
|
|
|
|
for priority, setting_names, source_file in file_infos:
|
|
|
|
|
for setting_name in setting_names:
|
|
|
|
|
l = d.get(setting_name, None)
|
|
|
|
|
if l is None:
|
|
|
|
|
l = list()
|
|
|
|
|
d[setting_name] = l
|
|
|
|
|
l.append(source_file)
|
|
|
|
|
for key in sorted(d.keys()):
|
|
|
|
|
for f in d[key]:
|
|
|
|
|
yield key, f
|
2022-08-29 10:37:06 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
KEYWORD_XML_TYPE_NESTED = "nested"
|
2023-05-18 16:39:07 +02:00
|
|
|
KEYWORD_XML_TYPE_ELEM = "elem"
|
2022-08-29 10:37:06 +02:00
|
|
|
KEYWORD_XML_TYPE_ATTR = "attr"
|
|
|
|
|
|
|
|
|
|
keywords = collections.OrderedDict(
|
|
|
|
|
[
|
|
|
|
|
("property", KEYWORD_XML_TYPE_ATTR),
|
|
|
|
|
("variable", KEYWORD_XML_TYPE_ATTR),
|
|
|
|
|
("format", KEYWORD_XML_TYPE_ATTR),
|
|
|
|
|
("values", KEYWORD_XML_TYPE_ATTR),
|
2023-09-05 16:25:02 +02:00
|
|
|
("special-values", KEYWORD_XML_TYPE_ATTR),
|
2022-08-29 10:37:06 +02:00
|
|
|
("default", KEYWORD_XML_TYPE_ATTR),
|
|
|
|
|
("example", KEYWORD_XML_TYPE_ATTR),
|
2023-05-18 16:39:07 +02:00
|
|
|
("description", KEYWORD_XML_TYPE_ELEM),
|
2022-08-29 10:37:06 +02:00
|
|
|
("description-docbook", KEYWORD_XML_TYPE_NESTED),
|
|
|
|
|
]
|
2022-02-09 20:00:25 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2022-08-29 10:37:06 +02:00
|
|
|
def keywords_allowed(tag, keyword):
|
|
|
|
|
# certain keywords might not be valid for some tags.
|
|
|
|
|
# Currently, all of them are always valid.
|
|
|
|
|
assert keyword in keywords
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def write_data(tag, setting_node, line_no, parsed_data):
|
|
|
|
|
for k in parsed_data.keys():
|
|
|
|
|
assert keywords_allowed(tag, k)
|
|
|
|
|
assert k in keywords
|
|
|
|
|
|
|
|
|
|
name = parsed_data["property"]
|
|
|
|
|
property_node, created = xnode_get_or_create(setting_node, "property", name)
|
|
|
|
|
if not created:
|
|
|
|
|
raise LineError(line_no, 'Duplicate property <property name="%s"...' % (name,))
|
|
|
|
|
|
|
|
|
|
for k, xmltype in keywords.items():
|
|
|
|
|
if k == "property":
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
v = parsed_data.get(k, None)
|
|
|
|
|
if v is None:
|
2022-10-04 10:16:07 +02:00
|
|
|
continue
|
2022-08-29 10:37:06 +02:00
|
|
|
|
|
|
|
|
if xmltype == KEYWORD_XML_TYPE_NESTED:
|
|
|
|
|
# Set as XML nodes. The input data is XML itself.
|
|
|
|
|
des = ET.fromstring("<%s>%s</%s>" % (k, v, k))
|
|
|
|
|
property_node.append(des)
|
2023-05-18 16:39:07 +02:00
|
|
|
elif xmltype == KEYWORD_XML_TYPE_ELEM:
|
2022-08-29 10:37:06 +02:00
|
|
|
node = ET.SubElement(property_node, k)
|
|
|
|
|
node.text = v
|
|
|
|
|
elif xmltype == KEYWORD_XML_TYPE_ATTR:
|
|
|
|
|
property_node.set(k, v)
|
|
|
|
|
else:
|
|
|
|
|
assert False
|
|
|
|
|
|
man nm-setting-*: add "expand enumvals" capability to property-infos
In some cases, properties documentation might require to provide an
explanation of each of the possible values that the property accepts.
If the possible values are the variants of an enum, we can use the
introspection data to get all the possible values for that enum and
their descriptions. With that info, we can automatically generate the
documentation with an always up to date list of accepted values.
Add a new "expand enumvals" feature: it will convert a token with the
format `#EnumName:*` to a list of all the possible values. For the
docbook (description-docbook field in the XML), it is expanded to a
bulleted list of all the values and their respective documentations.
This feature is limited to the "property-infos" comments (those like
---nmcli---, ---dbus---, etc). This comments are used only to generate
the nm-settings-* manual pages. For the documentation under the doc/
folder this is not needed: it's not supported by gtkdoc and, anyway,
it's better to use just `#EnumName` that will generate an HTML link.
Additionally, expansion of `%ENUM_VALUE` is now supported in the
property-infos comments. Instead of expanding them in the same style
than gtkdoc "ENUM_VALUE (num)", it is expanded in a format more suitable
for the nm-setting-* manual pages:
- for nmcli: value_nick (num)
- others: num (value_nick)
Also, fix typo in meson build file propery -> property.
2023-08-22 12:39:42 +02:00
|
|
|
|
|
|
|
|
def expand_enumval(enumval_name, nick_first):
|
|
|
|
|
if enumval_name not in enumvals:
|
|
|
|
|
return enumval_name
|
|
|
|
|
|
|
|
|
|
enumval = enumvals[enumval_name]
|
|
|
|
|
if nick_first:
|
|
|
|
|
return "%s (%s)" % (enumval["nick"], enumval["value"])
|
|
|
|
|
else:
|
|
|
|
|
return "%s (%s)" % (enumval["value"], enumval["nick"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def expand_all_enumvals(enum, nick_first):
|
|
|
|
|
assert enum in enums, "Enum name not found: %s" % enum
|
|
|
|
|
return ", ".join(expand_enumval(val_name, nick_first) for val_name in enums[enum])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def expand_all_enumvals_with_docs(enum, nick_first):
|
|
|
|
|
assert enum in enums, "Enum name not found: %s" % enum
|
|
|
|
|
|
|
|
|
|
out_str = "<itemizedlist>"
|
|
|
|
|
for enumval_name in enums[enum]:
|
|
|
|
|
assert enumval_name in enumvals
|
|
|
|
|
enumval = enumvals[enumval_name]
|
|
|
|
|
out_str += "<listitem><para><literal>%s</literal>%s</para></listitem>" % (
|
|
|
|
|
expand_enumval(enumval_name, nick_first),
|
|
|
|
|
" - " + enumval["doc"] if enumval["doc"] else "",
|
|
|
|
|
)
|
|
|
|
|
out_str += "</itemizedlist>"
|
|
|
|
|
|
|
|
|
|
return out_str
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def format_descriptions(tag, parsed_data):
|
2023-05-18 16:39:07 +02:00
|
|
|
if (
|
|
|
|
|
parsed_data.get("description", None) is not None
|
|
|
|
|
and parsed_data.get("description-docbook", None) is None
|
|
|
|
|
):
|
|
|
|
|
# we have a description, but no docbook. Generate one.
|
man nm-setting-*: add "expand enumvals" capability to property-infos
In some cases, properties documentation might require to provide an
explanation of each of the possible values that the property accepts.
If the possible values are the variants of an enum, we can use the
introspection data to get all the possible values for that enum and
their descriptions. With that info, we can automatically generate the
documentation with an always up to date list of accepted values.
Add a new "expand enumvals" feature: it will convert a token with the
format `#EnumName:*` to a list of all the possible values. For the
docbook (description-docbook field in the XML), it is expanded to a
bulleted list of all the values and their respective documentations.
This feature is limited to the "property-infos" comments (those like
---nmcli---, ---dbus---, etc). This comments are used only to generate
the nm-settings-* manual pages. For the documentation under the doc/
folder this is not needed: it's not supported by gtkdoc and, anyway,
it's better to use just `#EnumName` that will generate an HTML link.
Additionally, expansion of `%ENUM_VALUE` is now supported in the
property-infos comments. Instead of expanding them in the same style
than gtkdoc "ENUM_VALUE (num)", it is expanded in a format more suitable
for the nm-setting-* manual pages:
- for nmcli: value_nick (num)
- others: num (value_nick)
Also, fix typo in meson build file propery -> property.
2023-08-22 12:39:42 +02:00
|
|
|
parsed_data["description-docbook"] = ""
|
|
|
|
|
for line in parsed_data["description"].split("\n"):
|
|
|
|
|
para = ET.Element("para")
|
|
|
|
|
para.text = line
|
|
|
|
|
parsed_data["description-docbook"] += ET.tostring(para, encoding="unicode")
|
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 <description>
or a <description-docbook>, 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
<description> from the first file, and <description-docbook> from the
second file. As "man/nm-settings-nmcli.xsl" prefers
<description-docbook>, 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 <description> and <description-docbook>.
There is an assertion for that.
Also, stop generating <deprecated-docbook>. 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.
2023-05-17 12:19:34 +02:00
|
|
|
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:"'
|
|
|
|
|
)
|
man nm-setting-*: add "expand enumvals" capability to property-infos
In some cases, properties documentation might require to provide an
explanation of each of the possible values that the property accepts.
If the possible values are the variants of an enum, we can use the
introspection data to get all the possible values for that enum and
their descriptions. With that info, we can automatically generate the
documentation with an always up to date list of accepted values.
Add a new "expand enumvals" feature: it will convert a token with the
format `#EnumName:*` to a list of all the possible values. For the
docbook (description-docbook field in the XML), it is expanded to a
bulleted list of all the values and their respective documentations.
This feature is limited to the "property-infos" comments (those like
---nmcli---, ---dbus---, etc). This comments are used only to generate
the nm-settings-* manual pages. For the documentation under the doc/
folder this is not needed: it's not supported by gtkdoc and, anyway,
it's better to use just `#EnumName` that will generate an HTML link.
Additionally, expansion of `%ENUM_VALUE` is now supported in the
property-infos comments. Instead of expanding them in the same style
than gtkdoc "ENUM_VALUE (num)", it is expanded in a format more suitable
for the nm-setting-* manual pages:
- for nmcli: value_nick (num)
- others: num (value_nick)
Also, fix typo in meson build file propery -> property.
2023-08-22 12:39:42 +02:00
|
|
|
elif parsed_data.get("description", None) is None:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# Expand enumvals expressions (%ENUM_VALUE and #EnumName:*)
|
|
|
|
|
nick_first = tag == "nmcli"
|
|
|
|
|
|
|
|
|
|
parsed_data["description"] = re.sub(
|
|
|
|
|
r"#([A-Za-z0-9_]*):\*",
|
|
|
|
|
lambda match: expand_all_enumvals(match.group(1), nick_first),
|
|
|
|
|
parsed_data["description"],
|
|
|
|
|
)
|
2023-05-18 16:39:07 +02:00
|
|
|
|
man nm-setting-*: add "expand enumvals" capability to property-infos
In some cases, properties documentation might require to provide an
explanation of each of the possible values that the property accepts.
If the possible values are the variants of an enum, we can use the
introspection data to get all the possible values for that enum and
their descriptions. With that info, we can automatically generate the
documentation with an always up to date list of accepted values.
Add a new "expand enumvals" feature: it will convert a token with the
format `#EnumName:*` to a list of all the possible values. For the
docbook (description-docbook field in the XML), it is expanded to a
bulleted list of all the values and their respective documentations.
This feature is limited to the "property-infos" comments (those like
---nmcli---, ---dbus---, etc). This comments are used only to generate
the nm-settings-* manual pages. For the documentation under the doc/
folder this is not needed: it's not supported by gtkdoc and, anyway,
it's better to use just `#EnumName` that will generate an HTML link.
Additionally, expansion of `%ENUM_VALUE` is now supported in the
property-infos comments. Instead of expanding them in the same style
than gtkdoc "ENUM_VALUE (num)", it is expanded in a format more suitable
for the nm-setting-* manual pages:
- for nmcli: value_nick (num)
- others: num (value_nick)
Also, fix typo in meson build file propery -> property.
2023-08-22 12:39:42 +02:00
|
|
|
parsed_data["description"] = re.sub(
|
|
|
|
|
r"%([^%]\w*)",
|
|
|
|
|
lambda match: expand_enumval(match.group(1), nick_first),
|
|
|
|
|
parsed_data["description"],
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
parsed_data["description-docbook"] = re.sub(
|
|
|
|
|
r"#([A-Za-z0-9_]*):\*",
|
|
|
|
|
lambda match: expand_all_enumvals_with_docs(match.group(1), nick_first),
|
|
|
|
|
parsed_data["description-docbook"],
|
|
|
|
|
)
|
2022-08-29 10:37:06 +02:00
|
|
|
|
man nm-setting-*: add "expand enumvals" capability to property-infos
In some cases, properties documentation might require to provide an
explanation of each of the possible values that the property accepts.
If the possible values are the variants of an enum, we can use the
introspection data to get all the possible values for that enum and
their descriptions. With that info, we can automatically generate the
documentation with an always up to date list of accepted values.
Add a new "expand enumvals" feature: it will convert a token with the
format `#EnumName:*` to a list of all the possible values. For the
docbook (description-docbook field in the XML), it is expanded to a
bulleted list of all the values and their respective documentations.
This feature is limited to the "property-infos" comments (those like
---nmcli---, ---dbus---, etc). This comments are used only to generate
the nm-settings-* manual pages. For the documentation under the doc/
folder this is not needed: it's not supported by gtkdoc and, anyway,
it's better to use just `#EnumName` that will generate an HTML link.
Additionally, expansion of `%ENUM_VALUE` is now supported in the
property-infos comments. Instead of expanding them in the same style
than gtkdoc "ENUM_VALUE (num)", it is expanded in a format more suitable
for the nm-setting-* manual pages:
- for nmcli: value_nick (num)
- others: num (value_nick)
Also, fix typo in meson build file propery -> property.
2023-08-22 12:39:42 +02:00
|
|
|
parsed_data["description-docbook"] = re.sub(
|
|
|
|
|
r"%([^%]\w*)",
|
|
|
|
|
lambda match: expand_enumval(match.group(1), nick_first),
|
|
|
|
|
parsed_data["description-docbook"],
|
|
|
|
|
)
|
2022-08-29 10:37:06 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def parse_data(tag, line_no, lines):
|
|
|
|
|
assert lines
|
2021-04-22 18:41:50 -04:00
|
|
|
parsed_data = {}
|
|
|
|
|
keyword = ""
|
2022-08-29 10:37:06 +02:00
|
|
|
indent = None
|
|
|
|
|
for line in lines:
|
|
|
|
|
assert "\n" not in line
|
|
|
|
|
line_no += 1
|
|
|
|
|
m = re.search(r"^ \*(| .*)$", line)
|
|
|
|
|
if not m:
|
|
|
|
|
raise LineError(line_no, 'Invalid formatted line "%s"' % (line,))
|
|
|
|
|
content = m.group(1)
|
|
|
|
|
|
|
|
|
|
m = re.search("^ ([-a-z0-9]+):(.*)$", content)
|
|
|
|
|
text_keyword_started = None
|
|
|
|
|
if m:
|
|
|
|
|
keyword = m.group(1)
|
|
|
|
|
if keyword in parsed_data:
|
|
|
|
|
raise LineError(line_no, 'Duplicated keyword "%s"' % (keyword,))
|
|
|
|
|
text = m.group(2)
|
|
|
|
|
text_keyword_started = text
|
|
|
|
|
if text:
|
|
|
|
|
if text[0] != " " or len(text) == 1:
|
|
|
|
|
raise LineError(line_no, 'Invalid formatted line "%s"' % (line,))
|
|
|
|
|
text = text[1:]
|
|
|
|
|
if not keywords_allowed(tag, keyword):
|
|
|
|
|
raise LineError(line_no, 'Invalid key "%s" for %s' % (keyword, tag))
|
|
|
|
|
if parsed_data and keyword == "property":
|
|
|
|
|
raise LineError(line_no, 'The "property:" keywork must be first')
|
|
|
|
|
parsed_data[keyword] = text
|
|
|
|
|
indent = None
|
|
|
|
|
else:
|
|
|
|
|
if content == "":
|
|
|
|
|
text = ""
|
|
|
|
|
elif content[0] == " " and len(content) > 1:
|
|
|
|
|
text = content[1:]
|
|
|
|
|
assert text
|
|
|
|
|
if indent is None:
|
|
|
|
|
indent = re.search("^( *)", text).group(1)
|
|
|
|
|
if not text.startswith(indent):
|
|
|
|
|
raise LineError(line_no, 'Unexpected indention in "%s"' % (line,))
|
|
|
|
|
text = text[len(indent) :]
|
2021-05-23 21:52:18 -04:00
|
|
|
else:
|
2022-08-29 10:37:06 +02:00
|
|
|
raise LineError(line_no, 'Unexpected line "%s"' % (line,))
|
2021-04-22 18:41:50 -04:00
|
|
|
if not keyword:
|
2022-08-29 10:37:06 +02:00
|
|
|
raise LineError(line_no, "Expected data in comment: %s" % (line))
|
|
|
|
|
if text and text[0] == "\\":
|
|
|
|
|
assert False
|
|
|
|
|
text = text[1:]
|
|
|
|
|
if separator == " " and text == "":
|
|
|
|
|
# No separator to add. This is a blank line
|
|
|
|
|
pass
|
2021-04-22 18:41:50 -04:00
|
|
|
else:
|
2022-10-04 12:12:51 +02:00
|
|
|
parsed_data[keyword] = parsed_data[keyword] + separator + text
|
2022-08-29 10:37:06 +02:00
|
|
|
|
|
|
|
|
if keywords[keyword] == KEYWORD_XML_TYPE_NESTED:
|
|
|
|
|
# This is plain XML. They lines are joined by newlines.
|
|
|
|
|
separator = "\n"
|
|
|
|
|
elif text_keyword_started == "":
|
|
|
|
|
# If the previous line was just "tag:$", we don't need a separator
|
|
|
|
|
# the next time.
|
|
|
|
|
separator = ""
|
|
|
|
|
elif not text:
|
|
|
|
|
# A blank line is used to mark a line break, while otherwise
|
|
|
|
|
# lines are joined by space.
|
2022-10-04 12:12:51 +02:00
|
|
|
separator = "\n"
|
2022-08-29 10:37:06 +02:00
|
|
|
else:
|
|
|
|
|
separator = " "
|
|
|
|
|
if "property" not in parsed_data:
|
|
|
|
|
raise LineError(line_no, 'Missing "property:" tag')
|
|
|
|
|
for keyword in keywords.keys():
|
|
|
|
|
if not keywords_allowed(tag, keyword):
|
|
|
|
|
continue
|
|
|
|
|
if keyword not in parsed_data:
|
|
|
|
|
parsed_data[keyword] = None
|
2021-04-22 18:41:50 -04:00
|
|
|
return parsed_data
|
|
|
|
|
|
|
|
|
|
|
2022-08-29 10:37:06 +02:00
|
|
|
def process_setting(tag, root_node, source_file, setting_name):
|
|
|
|
|
dbg(
|
|
|
|
|
"> > tag:%s, source_file:%s, setting_name:%s" % (tag, source_file, setting_name)
|
|
|
|
|
)
|
2021-05-05 21:51:58 -04:00
|
|
|
|
2022-08-29 10:37:06 +02:00
|
|
|
start_tag = "---" + tag + "---"
|
|
|
|
|
end_tag = "---end---"
|
2021-04-22 18:41:50 -04:00
|
|
|
|
2022-08-29 10:37:06 +02:00
|
|
|
setting_node, created = xnode_get_or_create(root_node, "setting", setting_name)
|
2021-04-22 18:41:50 -04:00
|
|
|
|
2022-08-29 10:37:06 +02:00
|
|
|
try:
|
|
|
|
|
f = open(source_file, "r")
|
|
|
|
|
except OSError:
|
|
|
|
|
raise Exception("Can not open file: %s" % (source_file))
|
|
|
|
|
|
|
|
|
|
lines = None
|
|
|
|
|
with f:
|
|
|
|
|
line_no = 0
|
|
|
|
|
just_had_end_tag = False
|
|
|
|
|
line_no_start = None
|
|
|
|
|
for line in f:
|
|
|
|
|
line_no += 1
|
|
|
|
|
if line and line[-1] == "\n":
|
|
|
|
|
line = line[:-1]
|
|
|
|
|
if just_had_end_tag:
|
|
|
|
|
# After the end-tag, we still expect one particular line. Be strict about
|
|
|
|
|
# this.
|
|
|
|
|
just_had_end_tag = False
|
|
|
|
|
if line != " */":
|
|
|
|
|
raise LineError(
|
|
|
|
|
line_no,
|
|
|
|
|
'Invalid end tag "%s". Expects literally " */" after end-tag'
|
|
|
|
|
% (line,),
|
|
|
|
|
)
|
|
|
|
|
elif start_tag in line:
|
|
|
|
|
if line != " /* " + start_tag:
|
|
|
|
|
raise LineError(
|
|
|
|
|
line_no,
|
|
|
|
|
'Invalid start tag "%s". Expects literally " /* %s"'
|
|
|
|
|
% (line, start_tag),
|
|
|
|
|
)
|
|
|
|
|
if lines is not None:
|
|
|
|
|
raise LineError(
|
|
|
|
|
line_no, 'Invalid start tag "%s", missing end-tag' % (line,)
|
|
|
|
|
)
|
|
|
|
|
lines = []
|
|
|
|
|
line_no_start = line_no
|
|
|
|
|
elif end_tag in line and lines is not None:
|
|
|
|
|
if line != " * " + end_tag:
|
|
|
|
|
raise LineError(line_no, 'Invalid end tag: "%s"' % (line,))
|
|
|
|
|
parsed_data = parse_data(tag, line_no_start, lines)
|
|
|
|
|
if not parsed_data:
|
|
|
|
|
raise Exception('invalid data: line %s, "%s"' % (line_no, lines))
|
man nm-setting-*: add "expand enumvals" capability to property-infos
In some cases, properties documentation might require to provide an
explanation of each of the possible values that the property accepts.
If the possible values are the variants of an enum, we can use the
introspection data to get all the possible values for that enum and
their descriptions. With that info, we can automatically generate the
documentation with an always up to date list of accepted values.
Add a new "expand enumvals" feature: it will convert a token with the
format `#EnumName:*` to a list of all the possible values. For the
docbook (description-docbook field in the XML), it is expanded to a
bulleted list of all the values and their respective documentations.
This feature is limited to the "property-infos" comments (those like
---nmcli---, ---dbus---, etc). This comments are used only to generate
the nm-settings-* manual pages. For the documentation under the doc/
folder this is not needed: it's not supported by gtkdoc and, anyway,
it's better to use just `#EnumName` that will generate an HTML link.
Additionally, expansion of `%ENUM_VALUE` is now supported in the
property-infos comments. Instead of expanding them in the same style
than gtkdoc "ENUM_VALUE (num)", it is expanded in a format more suitable
for the nm-setting-* manual pages:
- for nmcli: value_nick (num)
- others: num (value_nick)
Also, fix typo in meson build file propery -> property.
2023-08-22 12:39:42 +02:00
|
|
|
format_descriptions(tag, parsed_data)
|
2022-08-29 10:37:06 +02:00
|
|
|
dbg("> > > property: %s" % (parsed_data["property"],))
|
|
|
|
|
if _dbg_level > 1:
|
|
|
|
|
for keyword in sorted(parsed_data.keys()):
|
|
|
|
|
v = parsed_data[keyword]
|
|
|
|
|
if v is not None:
|
|
|
|
|
v = '"%s"' % (v,)
|
|
|
|
|
dbg(
|
|
|
|
|
"> > > > [%s] (%s) = %s" % (keyword, keywords[keyword], v),
|
|
|
|
|
level=2,
|
|
|
|
|
)
|
|
|
|
|
write_data(tag, setting_node, line_no_start, parsed_data)
|
|
|
|
|
lines = None
|
|
|
|
|
elif lines is not None:
|
|
|
|
|
lines.append(line)
|
|
|
|
|
if lines is not None or just_had_end_tag:
|
|
|
|
|
raise LineError(line_no_start, "Unterminated start tag")
|
|
|
|
|
|
|
|
|
|
|
man nm-setting-*: add "expand enumvals" capability to property-infos
In some cases, properties documentation might require to provide an
explanation of each of the possible values that the property accepts.
If the possible values are the variants of an enum, we can use the
introspection data to get all the possible values for that enum and
their descriptions. With that info, we can automatically generate the
documentation with an always up to date list of accepted values.
Add a new "expand enumvals" feature: it will convert a token with the
format `#EnumName:*` to a list of all the possible values. For the
docbook (description-docbook field in the XML), it is expanded to a
bulleted list of all the values and their respective documentations.
This feature is limited to the "property-infos" comments (those like
---nmcli---, ---dbus---, etc). This comments are used only to generate
the nm-settings-* manual pages. For the documentation under the doc/
folder this is not needed: it's not supported by gtkdoc and, anyway,
it's better to use just `#EnumName` that will generate an HTML link.
Additionally, expansion of `%ENUM_VALUE` is now supported in the
property-infos comments. Instead of expanding them in the same style
than gtkdoc "ENUM_VALUE (num)", it is expanded in a format more suitable
for the nm-setting-* manual pages:
- for nmcli: value_nick (num)
- others: num (value_nick)
Also, fix typo in meson build file propery -> property.
2023-08-22 12:39:42 +02:00
|
|
|
def process_settings_docs(tag, output, gir_file, source_files):
|
2022-08-29 10:37:06 +02:00
|
|
|
dbg("> tag:%s, output:%s" % (tag, output))
|
|
|
|
|
|
|
|
|
|
root_node = ET.Element("nm-setting-docs")
|
|
|
|
|
|
man nm-setting-*: add "expand enumvals" capability to property-infos
In some cases, properties documentation might require to provide an
explanation of each of the possible values that the property accepts.
If the possible values are the variants of an enum, we can use the
introspection data to get all the possible values for that enum and
their descriptions. With that info, we can automatically generate the
documentation with an always up to date list of accepted values.
Add a new "expand enumvals" feature: it will convert a token with the
format `#EnumName:*` to a list of all the possible values. For the
docbook (description-docbook field in the XML), it is expanded to a
bulleted list of all the values and their respective documentations.
This feature is limited to the "property-infos" comments (those like
---nmcli---, ---dbus---, etc). This comments are used only to generate
the nm-settings-* manual pages. For the documentation under the doc/
folder this is not needed: it's not supported by gtkdoc and, anyway,
it's better to use just `#EnumName` that will generate an HTML link.
Additionally, expansion of `%ENUM_VALUE` is now supported in the
property-infos comments. Instead of expanding them in the same style
than gtkdoc "ENUM_VALUE (num)", it is expanded in a format more suitable
for the nm-setting-* manual pages:
- for nmcli: value_nick (num)
- others: num (value_nick)
Also, fix typo in meson build file propery -> property.
2023-08-22 12:39:42 +02:00
|
|
|
init_enumvals(ET.parse(gir_file).getroot())
|
|
|
|
|
|
2022-08-29 10:37:06 +02:00
|
|
|
for setting_name, source_file in get_file_infos(source_files):
|
|
|
|
|
try:
|
|
|
|
|
process_setting(tag, root_node, source_file, setting_name)
|
|
|
|
|
except LineError as e:
|
|
|
|
|
raise Exception(
|
|
|
|
|
"Error parsing %s, line %s (tag:%s, setting_name:%s): %s"
|
|
|
|
|
% (source_file, e.line_no, tag, setting_name, str(e))
|
|
|
|
|
)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
raise Exception(
|
|
|
|
|
"Error parsing %s (tag:%s, setting_name:%s): %s"
|
|
|
|
|
% (source_file, tag, setting_name, str(e))
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
ET.ElementTree(root_node).write(output)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
if len(sys.argv) < 4:
|
man nm-setting-*: add "expand enumvals" capability to property-infos
In some cases, properties documentation might require to provide an
explanation of each of the possible values that the property accepts.
If the possible values are the variants of an enum, we can use the
introspection data to get all the possible values for that enum and
their descriptions. With that info, we can automatically generate the
documentation with an always up to date list of accepted values.
Add a new "expand enumvals" feature: it will convert a token with the
format `#EnumName:*` to a list of all the possible values. For the
docbook (description-docbook field in the XML), it is expanded to a
bulleted list of all the values and their respective documentations.
This feature is limited to the "property-infos" comments (those like
---nmcli---, ---dbus---, etc). This comments are used only to generate
the nm-settings-* manual pages. For the documentation under the doc/
folder this is not needed: it's not supported by gtkdoc and, anyway,
it's better to use just `#EnumName` that will generate an HTML link.
Additionally, expansion of `%ENUM_VALUE` is now supported in the
property-infos comments. Instead of expanding them in the same style
than gtkdoc "ENUM_VALUE (num)", it is expanded in a format more suitable
for the nm-setting-* manual pages:
- for nmcli: value_nick (num)
- others: num (value_nick)
Also, fix typo in meson build file propery -> property.
2023-08-22 12:39:42 +02:00
|
|
|
print(
|
|
|
|
|
"Usage: %s [tag] [output-xml-file] [gir-file] [srcfiles...]" % (sys.argv[0])
|
|
|
|
|
)
|
2022-08-29 10:37:06 +02:00
|
|
|
exit(1)
|
|
|
|
|
|
|
|
|
|
process_settings_docs(
|
man nm-setting-*: add "expand enumvals" capability to property-infos
In some cases, properties documentation might require to provide an
explanation of each of the possible values that the property accepts.
If the possible values are the variants of an enum, we can use the
introspection data to get all the possible values for that enum and
their descriptions. With that info, we can automatically generate the
documentation with an always up to date list of accepted values.
Add a new "expand enumvals" feature: it will convert a token with the
format `#EnumName:*` to a list of all the possible values. For the
docbook (description-docbook field in the XML), it is expanded to a
bulleted list of all the values and their respective documentations.
This feature is limited to the "property-infos" comments (those like
---nmcli---, ---dbus---, etc). This comments are used only to generate
the nm-settings-* manual pages. For the documentation under the doc/
folder this is not needed: it's not supported by gtkdoc and, anyway,
it's better to use just `#EnumName` that will generate an HTML link.
Additionally, expansion of `%ENUM_VALUE` is now supported in the
property-infos comments. Instead of expanding them in the same style
than gtkdoc "ENUM_VALUE (num)", it is expanded in a format more suitable
for the nm-setting-* manual pages:
- for nmcli: value_nick (num)
- others: num (value_nick)
Also, fix typo in meson build file propery -> property.
2023-08-22 12:39:42 +02:00
|
|
|
tag=sys.argv[1],
|
|
|
|
|
output=sys.argv[2],
|
|
|
|
|
gir_file=sys.argv[3],
|
|
|
|
|
source_files=sys.argv[4:],
|
2022-08-29 10:37:06 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
# Tests
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def setup_module():
|
|
|
|
|
global pytest
|
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def t_srcdir():
|
|
|
|
|
return os.path.abspath(os.path.dirname(__file__) + "/..")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def t_setting_c(name):
|
2022-10-07 21:08:00 +02:00
|
|
|
return t_srcdir() + "/src/libnm-core-impl/nm-setting-" + name + ".c"
|
2022-08-29 10:37:06 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_file_location():
|
|
|
|
|
assert t_srcdir() + "/tools/generate-docs-nm-property-infos.py" == os.path.abspath(
|
|
|
|
|
__file__
|
|
|
|
|
)
|
|
|
|
|
assert os.path.isfile(t_srcdir() + "/src/libnm-core-impl/nm-setting-connection.c")
|
|
|
|
|
|
|
|
|
|
assert os.path.isfile(t_setting_c("ip-config"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_get_setting_names():
|
2022-10-04 10:15:17 +02:00
|
|
|
assert (1, ("connection",)) == get_setting_names(
|
2022-08-29 10:37:06 +02:00
|
|
|
t_srcdir() + "/src/libnm-core-impl/nm-setting-connection.c"
|
|
|
|
|
)
|
2022-10-04 10:15:17 +02:00
|
|
|
assert (1, ("ipv4",)) == get_setting_names(
|
2022-08-29 10:37:06 +02:00
|
|
|
t_srcdir() + "/src/libnm-core-impl/nm-setting-ip4-config.c"
|
|
|
|
|
)
|
2022-10-04 10:15:17 +02:00
|
|
|
assert (0, ("ipv4", "ipv6")) == get_setting_names(
|
2022-08-29 10:37:06 +02:00
|
|
|
t_srcdir() + "/src/libnm-core-impl/nm-setting-ip-config.c"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_get_file_infos():
|
|
|
|
|
t = ["connection", "ip-config", "ip4-config", "proxy", "wired"]
|
|
|
|
|
|
|
|
|
|
assert [
|
2022-10-04 10:15:17 +02:00
|
|
|
(
|
|
|
|
|
"802-3-ethernet",
|
|
|
|
|
t_setting_c("wired"),
|
|
|
|
|
),
|
2022-08-29 10:37:06 +02:00
|
|
|
(
|
|
|
|
|
"connection",
|
|
|
|
|
t_setting_c("connection"),
|
|
|
|
|
),
|
2022-10-04 10:15:17 +02:00
|
|
|
(
|
|
|
|
|
"ipv4",
|
|
|
|
|
t_setting_c("ip-config"),
|
|
|
|
|
),
|
2022-08-29 10:37:06 +02:00
|
|
|
(
|
|
|
|
|
"ipv4",
|
|
|
|
|
t_setting_c("ip4-config"),
|
|
|
|
|
),
|
|
|
|
|
(
|
2022-10-04 10:15:17 +02:00
|
|
|
"ipv6",
|
|
|
|
|
t_setting_c("ip-config"),
|
2022-08-29 10:37:06 +02:00
|
|
|
),
|
2022-10-04 10:15:17 +02:00
|
|
|
("proxy", t_setting_c("proxy")),
|
2022-08-29 10:37:06 +02:00
|
|
|
] == list(get_file_infos([t_setting_c(x) for x in t]))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_process_setting():
|
|
|
|
|
root_node = ET.Element("nm-setting-docs")
|
|
|
|
|
process_setting("nmcli", root_node, t_setting_c("connection"), "connection")
|