mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-07-21 18:24:49 +00:00
libnm-util: build nm-setting-docs.xml from gtk-doc and GParamSpecs
Add generate-setting-docs.py, based on tools/generate-settings-spec.c, which generates a simple XML file describing all libnm setting properties (still getting the default values via GParamSpec introspection like generate-settings-spec.c does, but getting the documentation out of the gtk-doc strings in the GIR file instead).
This commit is contained in:
parent
e8577083ca
commit
dcc109516d
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -169,6 +169,7 @@ valgrind-*.log
|
|||
/test/libnm_glib_test
|
||||
/test/nm-online
|
||||
/test/nmtestdevices
|
||||
/libnm-util/nm-setting-docs.xml
|
||||
/libnm-util/test-crypto
|
||||
/libnm-util/tests/test-crypto
|
||||
/libnm-util/tests/test-settings-defaults
|
||||
|
|
11
Makefile.am
11
Makefile.am
|
@ -44,6 +44,17 @@ DISTCHECK_CONFIGURE_FLAGS = \
|
|||
--enable-ifupdown \
|
||||
--enable-ifnet
|
||||
|
||||
if HAVE_INTROSPECTION
|
||||
dist-check-introspection:
|
||||
else
|
||||
dist-check-introspection:
|
||||
@echo "*** gobject-introspection is needed to run 'make dist'. ***"
|
||||
@echo "*** It was not enabled when 'configure' ran. ***"
|
||||
@false
|
||||
endif
|
||||
|
||||
dist: dist-check-introspection
|
||||
|
||||
DISTCLEANFILES = intltool-extract intltool-merge intltool-update
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
|
|
|
@ -181,8 +181,20 @@ typelibdir = $(libdir)/girepository-1.0
|
|||
typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
|
||||
|
||||
CLEANFILES += $(gir_DATA) $(typelib_DATA)
|
||||
|
||||
noinst_DATA = nm-setting-docs.xml
|
||||
|
||||
nm-setting-docs.xml: generate-setting-docs.py NetworkManager-1.0.gir libnm-util.la
|
||||
$(srcdir)/generate-setting-docs.py \
|
||||
--gir $(builddir)/NetworkManager-1.0.gir \
|
||||
--output $@
|
||||
|
||||
endif
|
||||
|
||||
DISTCLEANFILES = nm-setting-docs.xml
|
||||
|
||||
EXTRA_DIST += generate-setting-docs.py
|
||||
|
||||
if ENABLE_TESTS
|
||||
|
||||
check-local:
|
||||
|
|
192
libnm-util/generate-setting-docs.py
Executable file
192
libnm-util/generate-setting-docs.py
Executable file
|
@ -0,0 +1,192 @@
|
|||
#!/usr/bin/env python
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the
|
||||
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
# Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Copyright 2009 - 2014 Red Hat, Inc.
|
||||
|
||||
from gi.repository import NetworkManager, GObject
|
||||
import argparse, datetime, re, sys
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
type_name_map = {
|
||||
'gchararray': 'string',
|
||||
'GSList_gchararray_': 'array of string',
|
||||
'GArray_guchar_': 'byte array',
|
||||
'gboolean': 'boolean',
|
||||
'guint64': 'uint64',
|
||||
'gint': 'int32',
|
||||
'guint': 'uint32',
|
||||
'GArray_guint_': 'array of uint32',
|
||||
'GPtrArray_GArray_guint__': 'array of array of uint32',
|
||||
'GPtrArray_GArray_guchar__': 'array of byte array',
|
||||
'GPtrArray_gchararray_': 'array of string',
|
||||
'GHashTable_gchararray+gchararray_': 'dict of (string::string)',
|
||||
'GPtrArray_GValueArray_GArray_guchar_+guint+GArray_guchar___': 'array of (byte array, uint32, byte array)',
|
||||
'GPtrArray_GValueArray_GArray_guchar_+guint+GArray_guchar_+guint__': 'array of (byte array, uint32, byte array, uint32)'
|
||||
}
|
||||
|
||||
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'
|
||||
}
|
||||
identifier_key = '{%s}identifier' % ns_map['c']
|
||||
nick_key = '{%s}nick' % ns_map['glib']
|
||||
symbol_prefix_key = '{%s}symbol-prefix' % ns_map['c']
|
||||
|
||||
constants = { 'TRUE': 'TRUE', 'FALSE': 'FALSE', 'NULL': 'NULL' }
|
||||
setting_names = {}
|
||||
|
||||
def init_constants(girxml):
|
||||
for const in girxml.findall('./gi:namespace/gi:constant', ns_map):
|
||||
cname = const.attrib['{%s}type' % ns_map['c']]
|
||||
cvalue = const.attrib['value']
|
||||
if const.find('./gi:type[@name="utf8"]', ns_map) is not None:
|
||||
cvalue = '"%s"' % cvalue
|
||||
constants[cname] = cvalue
|
||||
|
||||
for enum in girxml.findall('./gi:namespace/gi:enumeration', ns_map):
|
||||
flag = enum.attrib['name'].endswith('Flags')
|
||||
for enumval in enum.findall('./gi:member', ns_map):
|
||||
cname = enumval.attrib[identifier_key]
|
||||
cvalue = enumval.attrib['value']
|
||||
if flag:
|
||||
cvalue = '%s (0x%x)' % (cname, int(cvalue))
|
||||
else:
|
||||
cvalue = '%s (%s)' % (cname, cvalue)
|
||||
constants[cname] = cvalue
|
||||
|
||||
for setting in girxml.findall('./gi:namespace/gi:class[@parent="Setting"]', ns_map):
|
||||
setting_type_name = 'NM' + setting.attrib['name'];
|
||||
symbol_prefix = setting.attrib[symbol_prefix_key]
|
||||
setting_name = constants['NM_' + symbol_prefix.upper() + '_SETTING_NAME']
|
||||
setting_names[setting_type_name] = setting_name
|
||||
|
||||
def get_prop_type(setting, pspec, propxml):
|
||||
prop_type = pspec.value_type.name
|
||||
if type_name_map.has_key(prop_type):
|
||||
prop_type = type_name_map[prop_type]
|
||||
if prop_type is None:
|
||||
prop_type = ''
|
||||
return prop_type
|
||||
|
||||
def get_docs(setting, pspec, propxml):
|
||||
doc_xml = propxml.find('gi:doc', ns_map)
|
||||
if doc_xml is None:
|
||||
return None
|
||||
|
||||
doc = doc_xml.text
|
||||
if propxml.attrib.has_key('deprecated'):
|
||||
doc = doc + ' Deprecated: ' + propxml.attrib['deprecated']
|
||||
|
||||
doc = re.sub(r'\n\s*', r' ', doc)
|
||||
|
||||
# Expand constants
|
||||
doc = re.sub(r'%([^%]\w*)', lambda match: constants[match.group(1)], doc)
|
||||
|
||||
# #NMSettingWired:mac-address -> "mac-address"
|
||||
doc = re.sub(r'#[A-Za-z0-9_]*:([A-Za-z0-9_-]*)', r'"\1"', doc)
|
||||
|
||||
# #NMSettingWired setting -> "802-3-ethernet" setting
|
||||
doc = re.sub(r'#([A-Z]\w*) setting', lambda match: setting_names[match.group(1)] + ' setting', doc)
|
||||
|
||||
# remaining gtk-doc cleanup
|
||||
doc = doc.replace('%%', '%')
|
||||
doc = re.sub(r'#([A-Z]\w*)', r'\1', doc)
|
||||
|
||||
# Remove sentences that refer to functions
|
||||
doc = re.sub(r'\.\s+[^.]*\w\(\)[^.]*\.', r'.', doc)
|
||||
|
||||
return doc
|
||||
|
||||
def get_default_value(setting, pspec, propxml):
|
||||
default_value = setting.get_property(pspec.name.replace('-', '_'))
|
||||
if default_value is None:
|
||||
return default_value
|
||||
|
||||
value_type = get_prop_type(setting, pspec, propxml)
|
||||
if value_type == 'string' and default_value != '' and pspec.name != 'name':
|
||||
default_value = '"%s"' % default_value
|
||||
elif value_type == 'gchar' and default_value != '':
|
||||
default_value = "'%s'" % default_value
|
||||
elif value_type == 'boolean':
|
||||
default_value = str(default_value).upper()
|
||||
elif value_type == 'byte array':
|
||||
default_value = '[]'
|
||||
elif str(default_value).startswith('<'):
|
||||
default_value = None
|
||||
|
||||
return default_value
|
||||
|
||||
def escape(val):
|
||||
return str(val).replace('"', '"')
|
||||
|
||||
def usage():
|
||||
print "Usage: %s --gir FILE --output FILE" % sys.argv[0]
|
||||
exit()
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-g', '--gir', metavar='FILE', help='NetworkManager-1.0.gir file')
|
||||
parser.add_argument('-o', '--output', metavar='FILE', help='output file')
|
||||
|
||||
args = parser.parse_args()
|
||||
if args.gir is None or args.output is None:
|
||||
usage()
|
||||
|
||||
NetworkManager.utils_init()
|
||||
|
||||
girxml = ET.parse(args.gir).getroot()
|
||||
outfile = open(args.output, mode='w')
|
||||
|
||||
init_constants(girxml)
|
||||
|
||||
basexml = girxml.find('./gi:namespace/gi:class[@name="Setting"]', ns_map)
|
||||
settings = girxml.findall('./gi:namespace/gi:class[@parent="Setting"]', ns_map)
|
||||
settings = sorted(settings, key=lambda setting: setting.attrib['{%s}symbol-prefix' % ns_map['c']])
|
||||
|
||||
outfile.write("""<?xml version=\"1.0\"?>
|
||||
<!DOCTYPE nm-setting-docs [
|
||||
<!ENTITY quot """>
|
||||
]>
|
||||
<nm-setting-docs>
|
||||
""")
|
||||
|
||||
for settingxml in settings:
|
||||
new_func = NetworkManager.__getattr__(settingxml.attrib['name'])
|
||||
setting = new_func()
|
||||
|
||||
outfile.write(" <setting name=\"%s\">\n" % setting.props.name)
|
||||
|
||||
properties = sorted(GObject.list_properties(setting), key=lambda prop: prop.name)
|
||||
for pspec in properties:
|
||||
propxml = settingxml.find('./gi:property[@name="%s"]' % pspec.name, ns_map)
|
||||
if propxml is None:
|
||||
propxml = basexml.find('./gi:property[@name="%s"]' % pspec.name, ns_map)
|
||||
|
||||
value_type = get_prop_type(setting, pspec, propxml)
|
||||
value_desc = get_docs(setting, pspec, propxml)
|
||||
default_value = get_default_value(setting, pspec, propxml)
|
||||
|
||||
if default_value is not None:
|
||||
outfile.write(" <property name=\"%s\" type=\"%s\" default=\"%s\" description=\"%s\" />\n" %
|
||||
(pspec.name, value_type, escape(default_value), escape(value_desc)))
|
||||
else:
|
||||
outfile.write(" <property name=\"%s\" type=\"%s\" description=\"%s\" />\n" %
|
||||
(pspec.name, value_type, escape(value_desc)))
|
||||
|
||||
outfile.write(" </setting>\n")
|
||||
|
||||
outfile.write("</nm-setting-docs>\n")
|
||||
outfile.close()
|
Loading…
Reference in a new issue