cpw.gillux.detachablepurple: a82660ab: Added a DBus code generation script.
gillux at soc.pidgin.im
gillux at soc.pidgin.im
Thu May 19 16:21:19 EDT 2011
----------------------------------------------------------------------
Revision: a82660ab5e31dbe1d7e86014eaafa25264b0d438
Parent: 14c4e310f1830a05a41b1898e2b7a4dff51b047a
Author: gillux at soc.pidgin.im
Date: 05/19/11 14:39:54
Branch: im.pidgin.cpw.gillux.detachablepurple
URL: http://d.pidgin.im/viewmtn/revision/info/a82660ab5e31dbe1d7e86014eaafa25264b0d438
Changelog:
Added a DBus code generation script.
Actually, it only generates the DBus interface information data in
C source form. It's mainly copied from glib's gdbus-codegen code script.
We needed our own script, because the code generated by gdbus-codegen
doesn't suit our needs. It's good if you have DBus-dedicated gobjects,
but not if you want e.g. to directly export the existing properties and
methods of your gobjects.
But it still worth to have such a script to keep the XML DBus interface
information in static C structures instead of generating it at runtime
from hardcoded XML strings, so here it is.
Changes against parent 14c4e310f1830a05a41b1898e2b7a4dff51b047a
added libpurple/dbus/codegen.py
added libpurple/dbus/dbusxml-to-c.py
added libpurple/dbus/parser.py
patched libpurple/Makefile.am
attr on libpurple/dbus/dbusxml-to-c.py
set mtn:execute
to true
-------------- next part --------------
============================================================
--- libpurple/Makefile.am 79c96e27a874752a61f0ac452ad2c17958a2f931
+++ libpurple/Makefile.am 7ffa75dbdf1c225955adcf330e6fe6cfd9277a45
@@ -207,15 +207,15 @@ purple_builtheaders = \
purple_builtheaders = \
purple.h version.h marshallers.h enums.h \
- dbus/account-server.h dbus/account-client.h \
- dbus/blist-server.h dbus/blist-client.h \
- dbus/buddy-server.h dbus/buddy-client.h \
- dbus/chat-server.h dbus/chat-client.h \
- dbus/connection-server.h dbus/connection-client.h \
- dbus/contact-server.h dbus/contact-client.h \
- dbus/group-server.h dbus/group-client.h \
- dbus/constructor-server.h dbus/constructor-client.h \
- dbus/callback-server.h dbus/callback-client.h
+ dbus/account.xml.h \
+ dbus/blist.xml.h \
+ dbus/buddy.xml.h \
+ dbus/callback.xml.h \
+ dbus/chat.xml.h \
+ dbus/connection.xml.h \
+ dbus/constructor.xml.h \
+ dbus/contact.xml.h \
+ dbus/group.xml.h
purple_enumheaders = \
account.h \
@@ -264,60 +264,33 @@ if ENABLE_DBUS
if ENABLE_DBUS
-dbus/constructor-server.h: dbus/constructor.xml
- $(AM_V_GEN)dbus-binding-tool --prefix=DBUS_purple_constructor --mode=glib-server --output=$@ $<
+dbus/constructor.xml.h: dbus/constructor.xml
+ $(AM_V_GEN)dbus/dbusxml-to-c.py $< purple_constructor $@
-dbus/constructor-client.h: dbus/constructor.xml
- $(AM_V_GEN)dbus-binding-tool --prefix=DBUS_purple_constructor --mode=glib-client --output=$@ $<
+dbus/callback.xml.h: dbus/callback.xml
+ $(AM_V_GEN)dbus/dbusxml-to-c.py $< purple_callback $@
-dbus/callback-server.h: dbus/callback.xml
- $(AM_V_GEN)dbus-binding-tool --prefix=DBUS_purple_callback --mode=glib-server --output=$@ $<
+dbus/account.xml.h: dbus/account.xml
+ $(AM_V_GEN)dbus/dbusxml-to-c.py $< purple_account $@
-dbus/callback-client.h: dbus/callback.xml
- $(AM_V_GEN)dbus-binding-tool --prefix=DBUS_purple_callback --mode=glib-client --output=$@ $<
+dbus/blist.xml.h: dbus/blist.xml
+ $(AM_V_GEN)dbus/dbusxml-to-c.py $< purple_blist $@
-dbus/account-server.h: dbus/account.xml
- $(AM_V_GEN)dbus-binding-tool --prefix=DBUS_purple_account --mode=glib-server --output=$@ $<
+dbus/buddy.xml.h: dbus/buddy.xml
+ $(AM_V_GEN)dbus/dbusxml-to-c.py $< purple_buddy $@
-dbus/account-client.h: dbus/account.xml
- $(AM_V_GEN)dbus-binding-tool --prefix=DBUS_purple_account --mode=glib-client --output=$@ $<
+dbus/chat.xml.h: dbus/chat.xml
+ $(AM_V_GEN)dbus/dbusxml-to-c.py $< purple_chat $@
-dbus/blist-server.h: dbus/blist.xml
- $(AM_V_GEN)dbus-binding-tool --prefix=DBUS_purple_blist --mode=glib-server --output=$@ $<
+dbus/connection.xml.h: dbus/connection.xml
+ $(AM_V_GEN)dbus/dbusxml-to-c.py $< purple_connection $@
-dbus/blist-client.h: dbus/blist.xml
- $(AM_V_GEN)dbus-binding-tool --prefix=DBUS_purple_blist --mode=glib-client --output=$@ $<
+dbus/contact.xml.h: dbus/contact.xml
+ $(AM_V_GEN)dbus/dbusxml-to-c.py $< purple_contact $@
-dbus/buddy-server.h: dbus/buddy.xml
- $(AM_V_GEN)dbus-binding-tool --prefix=DBUS_purple_buddy --mode=glib-server --output=$@ $<
+dbus/group.xml.h: dbus/group.xml
+ $(AM_V_GEN)dbus/dbusxml-to-c.py $< purple_group $@
-dbus/buddy-client.h: dbus/buddy.xml
- $(AM_V_GEN)dbus-binding-tool --prefix=DBUS_purple_buddy --mode=glib-client --output=$@ $<
-
-dbus/chat-server.h: dbus/chat.xml
- $(AM_V_GEN)dbus-binding-tool --prefix=DBUS_purple_chat --mode=glib-server --output=$@ $<
-
-dbus/chat-client.h: dbus/chat.xml
- $(AM_V_GEN)dbus-binding-tool --prefix=DBUS_purple_chat --mode=glib-client --output=$@ $<
-
-dbus/connection-server.h: dbus/connection.xml
- $(AM_V_GEN)dbus-binding-tool --prefix=DBUS_purple_connection --mode=glib-server --output=$@ $<
-
-dbus/connection-client.h: dbus/connection.xml
- $(AM_V_GEN)dbus-binding-tool --prefix=DBUS_purple_connection --mode=glib-client --output=$@ $<
-
-dbus/contact-server.h: dbus/contact.xml
- $(AM_V_GEN)dbus-binding-tool --prefix=DBUS_purple_contact --mode=glib-server --output=$@ $<
-
-dbus/contact-client.h: dbus/contact.xml
- $(AM_V_GEN)dbus-binding-tool --prefix=DBUS_purple_contact --mode=glib-client --output=$@ $<
-
-dbus/group-server.h: dbus/group.xml
- $(AM_V_GEN)dbus-binding-tool --prefix=DBUS_purple_group --mode=glib-server --output=$@ $<
-
-dbus/group-client.h: dbus/group.xml
- $(AM_V_GEN)dbus-binding-tool --prefix=DBUS_purple_group --mode=glib-client --output=$@ $<
-
CLEANFILES = \
dbus-bindings.c \
dbus-client-binding.c \
============================================================
--- /dev/null
+++ libpurple/dbus/codegen.py 3912c068c4e7de19cb5124b984083486ec7d96be
@@ -0,0 +1,218 @@
+# -*- Mode: Python -*-
+
+# GDBus - GLib D-Bus Library
+#
+# Copyright (C) 2008-2011 Red Hat, Inc.
+#
+# 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., 59 Temple Place, Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+# Author: David Zeuthen <davidz at redhat.com>
+
+# Shamelessly cut and pasted from the gdbus-codegen glib tool, with minor
+# modifications. Only the GDBusInterfaceVTable generation code is here.
+
+import sys
+
+class CodeGenerator:
+ def __init__(self, ifaces, namespace, c):
+ self.ifaces = ifaces
+ self.c = c
+ self.namespace = namespace
+
+ def generate_annotations(self, prefix, annotations):
+ if annotations == None:
+ return
+
+ n = 0
+ for a in annotations:
+ # skip internal annotations
+ if a.key.startswith('org.gtk.GDBus'):
+ continue
+
+ self.c.write('static const GDBusAnnotationInfo %s_%d =\n'
+ '{\n'
+ ' -1,\n'
+ ' "%s",\n'
+ ' "%s",\n'%(prefix, n, a.key, a.value))
+ if len(a.annotations) == 0:
+ self.c.write(' NULL\n')
+ else:
+ self.c.write(' (GDBusAnnotationInfo **) &%s_%d_pointers\n'%(prefix, n))
+ self.c.write('};\n'
+ '\n')
+ n += 1
+
+ if n > 0:
+ self.c.write('static const GDBusAnnotationInfo * const %s_pointers[] =\n'
+ '{\n'%(prefix))
+ m = 0;
+ for a in annotations:
+ if a.key.startswith('org.gtk.GDBus'):
+ continue
+ self.c.write(' &%s_%d,\n'%(prefix, m))
+ m += 1
+ self.c.write(' NULL\n'
+ '};\n'
+ '\n')
+ return n
+
+ def generate_args(self, prefix, args):
+ for a in args:
+ num_anno = self.generate_annotations('%s_arg_%s_annotation_info'%(prefix, a.name), a.annotations)
+
+ self.c.write('static const GDBusArgInfo %s_%s =\n'
+ '{\n'
+ ' -1,\n'
+ ' "%s",\n'
+ ' "%s",\n'%(prefix, a.name_lower, a.name, a.signature))
+ if num_anno == 0:
+ self.c.write(' NULL\n')
+ else:
+ self.c.write(' (GDBusAnnotationInfo **) &%s_arg_%s_annotation_info_pointers\n'%(prefix, a.name))
+ self.c.write('};\n'
+ '\n')
+
+ if len(args) > 0:
+ self.c.write('static const GDBusArgInfo * const %s_pointers[] =\n'
+ '{\n'%(prefix))
+ for a in args:
+ self.c.write(' &%s_%s,\n'%(prefix, a.name_lower))
+ self.c.write(' NULL\n'
+ '};\n'
+ '\n')
+
+ def generate_introspection_for_interface(self, i):
+ if len(i.methods) > 0:
+ for m in i.methods:
+ self.generate_args('%s_method_info_%s_IN_ARG'%(self.namespace, m.name_lower), m.in_args)
+ self.generate_args('%s_method_info_%s_OUT_ARG'%(self.namespace, m.name_lower), m.out_args)
+
+ num_anno = self.generate_annotations('%s_method_%s_annotation_info'%(self.namespace, m.name_lower), m.annotations)
+
+ self.c.write('static const GDBusMethodInfo %s_method_info_%s =\n'
+ '{\n'
+ ' -1,\n'
+ ' "%s",\n'%(self.namespace, m.name_lower, m.name))
+ if len(m.in_args) == 0:
+ self.c.write(' NULL,\n')
+ else:
+ self.c.write(' (GDBusArgInfo **) &%s_method_info_%s_IN_ARG_pointers,\n'%(self.namespace, m.name_lower))
+ if len(m.out_args) == 0:
+ self.c.write(' NULL,\n')
+ else:
+ self.c.write(' (GDBusArgInfo **) &%s_method_info_%s_OUT_ARG_pointers,\n'%(self.namespace, m.name_lower))
+ if num_anno == 0:
+ self.c.write(' NULL\n')
+ else:
+ self.c.write(' (GDBusAnnotationInfo **) &%s_method_%s_annotation_info_pointers\n'%(self.namespace, m.name_lower))
+ self.c.write('};\n'
+ '\n')
+
+ self.c.write('static const GDBusMethodInfo * const %s_method_info_pointers[] =\n'
+ '{\n'%(self.namespace))
+ for m in i.methods:
+ self.c.write(' &%s_method_info_%s,\n'%(self.namespace, m.name_lower))
+ self.c.write(' NULL\n'
+ '};\n'
+ '\n')
+
+ if len(i.signals) > 0:
+ for s in i.signals:
+ self.generate_args('%s_signal_info_%s_ARG'%(self.namespace, s.name_lower), s.args)
+
+ num_anno = self.generate_annotations('%s_signal_%s_annotation_info'%(self.namespace, s.name_lower), s.annotations)
+ self.c.write('static const GDBusSignalInfo %s_signal_info_%s =\n'
+ '{\n'
+ ' -1,\n'
+ ' "%s",\n'%(self.namespace, s.name_lower, s.name))
+ if len(s.args) == 0:
+ self.c.write(' NULL,\n')
+ else:
+ self.c.write(' (GDBusArgInfo **) &%s_signal_info_%s_ARG_pointers,\n'%(self.namespace, s.name_lower))
+ if num_anno == 0:
+ self.c.write(' NULL\n')
+ else:
+ self.c.write(' (GDBusAnnotationInfo **) &%s_signal_%s_annotation_info_pointers\n'%(self.namespace, s.name_lower))
+ self.c.write('};\n'
+ '\n')
+
+ self.c.write('static const GDBusSignalInfo * const %s_signal_info_pointers[] =\n'
+ '{\n'%(self.namespace))
+ for s in i.signals:
+ self.c.write(' &%s_signal_info_%s,\n'%(self.namespace, s.name_lower))
+ self.c.write(' NULL\n'
+ '};\n'
+ '\n')
+
+ if len(i.properties) > 0:
+ for p in i.properties:
+ if p.readable and p.writable:
+ access = 'G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE'
+ elif p.readable:
+ access = 'G_DBUS_PROPERTY_INFO_FLAGS_READABLE'
+ elif p.writable:
+ access = 'G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE'
+ else:
+ access = 'G_DBUS_PROPERTY_INFO_FLAGS_NONE'
+ num_anno = self.generate_annotations('%s_property_%s_annotation_info'%(self.namespace, p.name_lower), p.annotations)
+ self.c.write('static const GDBusPropertyInfo %s_property_info_%s =\n'
+ '{\n'
+ ' -1,\n'
+ ' "%s",\n'
+ ' "%s",\n'
+ ' %s,\n'%(self.namespace, p.name_lower, p.name, p.arg.signature, access))
+ if num_anno == 0:
+ self.c.write(' NULL\n')
+ else:
+ self.c.write(' (GDBusAnnotationInfo **) &%s_property_%s_annotation_info_pointers\n'%(self.namespace, p.name_lower))
+ self.c.write('};\n'
+ '\n')
+
+ self.c.write('static const GDBusPropertyInfo * const %s_property_info_pointers[] =\n'
+ '{\n'%(self.namespace))
+ for p in i.properties:
+ self.c.write(' &%s_property_info_%s,\n'%(self.namespace, p.name_lower))
+ self.c.write(' NULL\n'
+ '};\n'
+ '\n')
+
+ num_anno = self.generate_annotations('%s_annotation_info'%(self.namespace), i.annotations)
+ self.c.write('static GDBusInterfaceInfo %s_interface_info =\n'
+ '{\n'
+ ' -1,\n'
+ ' "%s",\n'%(self.namespace, i.name))
+ if len(i.methods) == 0:
+ self.c.write(' NULL,\n')
+ else:
+ self.c.write(' (GDBusMethodInfo **) &%s_method_info_pointers,\n'%(self.namespace))
+ if len(i.signals) == 0:
+ self.c.write(' NULL,\n')
+ else:
+ self.c.write(' (GDBusSignalInfo **) &%s_signal_info_pointers,\n'%(self.namespace))
+ if len(i.properties) == 0:
+ self.c.write(' NULL,\n')
+ else:
+ self.c.write(' (GDBusPropertyInfo **) &%s_property_info_pointers,\n'%(self.namespace))
+ if num_anno == 0:
+ self.c.write(' NULL\n')
+ else:
+ self.c.write(' (GDBusAnnotationInfo **) &%s_annotation_info_pointers\n'%(self.namespace))
+ self.c.write('};\n');
+
+ def generate(self):
+ for i in self.ifaces:
+ self.generate_introspection_for_interface(i)
+
============================================================
--- /dev/null
+++ libpurple/dbus/dbusxml-to-c.py 5ff712182a0ad21ead8c0436ff0dd0b6c5a48dcf
@@ -0,0 +1,41 @@
+#!/usr/bin/python
+
+# This file is a part of Purple.
+#
+# Purple is the legal property of its developers, whose names are too numerous
+# to list here. Please refer to the COPYRIGHT file distributed with this
+# source distribution.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+
+import sys
+import parser
+import codegen
+
+if len(sys.argv) < 3:
+ print("Usage: %s file.xml c_prefix generated.c" % sys.argv[0])
+ sys.exit(1)
+
+f = open(sys.argv[1])
+xml_data = f.read()
+f.close()
+parsed_ifaces = parser.parse_dbus_xml(xml_data)
+
+namespace = sys.argv[2]
+c = open(sys.argv[3], 'w')
+gen = codegen.CodeGenerator(parsed_ifaces, namespace, c)
+gen.generate()
+sys.exit(0)
+
============================================================
--- /dev/null
+++ libpurple/dbus/parser.py fb6c24e82e7f3542c110500aadf8b1a49a82ef63
@@ -0,0 +1,264 @@
+# -*- Mode: Python -*-
+
+# GDBus - GLib D-Bus Library
+#
+# Copyright (C) 2008-2011 Red Hat, Inc.
+#
+# 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., 59 Temple Place, Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+# Author: David Zeuthen <davidz at redhat.com>
+
+# Shamelessly cut and pasted from the gdbus-codegen glib tool, with minor
+# modifications. Only the GDBusInterfaceVTable generation code is here.
+
+import sys
+import xml.parsers.expat
+
+def camel_case_to_uscore(s):
+ ret = ''
+ insert_uscore = False
+ prev_was_lower = False
+ for c in s:
+ if c.isupper():
+ if prev_was_lower:
+ insert_uscore = True
+ prev_was_lower = False
+ else:
+ prev_was_lower = True
+ if insert_uscore:
+ ret += '_'
+ ret += c.lower().replace('-', '_')
+ insert_uscore = False
+ return ret
+
+class Annotation:
+ def __init__(self, key, value):
+ self.key = key
+ self.value = value
+ self.annotations = []
+
+class Arg:
+ def __init__(self, name, signature):
+ self.name = name
+ self.signature = signature
+ self.annotations = []
+ self.name_lower = camel_case_to_uscore(name)
+
+class Method:
+ def __init__(self, name):
+ self.name = name
+ self.in_args = []
+ self.out_args = []
+ self.annotations = []
+ self.name_lower = camel_case_to_uscore(name)
+
+class Signal:
+ def __init__(self, name):
+ self.name = name
+ self.args = []
+ self.annotations = []
+ self.name_lower = camel_case_to_uscore(name)
+
+
+class Property:
+ def __init__(self, name, signature, access):
+ self.name = name
+ self.signature = signature
+ self.access = access
+ self.annotations = []
+ self.arg = Arg('value', self.signature)
+ self.arg.annotations = self.annotations
+ self.readable = False
+ self.writable = False
+ if self.access == 'readwrite':
+ self.readable = True
+ self.writable = True
+ elif self.access == 'read':
+ self.readable = True
+ elif self.access == 'write':
+ self.writable = True
+ else:
+ raise RuntimeError('Invalid access type %s'%self.access)
+ self.name_lower = camel_case_to_uscore(name)
+
+class Interface:
+ def __init__(self, name):
+ self.name = name
+ self.methods = []
+ self.signals = []
+ self.properties = []
+ self.annotations = []
+
+class DBusXMLParser:
+ STATE_TOP = 'top'
+ STATE_NODE = 'node'
+ STATE_INTERFACE = 'interface'
+ STATE_METHOD = 'method'
+ STATE_SIGNAL = 'signal'
+ STATE_PROPERTY = 'property'
+ STATE_ARG = 'arg'
+ STATE_ANNOTATION = 'annotation'
+
+ def __init__(self, xml_data):
+ self._parser = xml.parsers.expat.ParserCreate()
+ self._parser.CharacterDataHandler = self.handle_char_data
+ self._parser.StartElementHandler = self.handle_start_element
+ self._parser.EndElementHandler = self.handle_end_element
+
+ self.parsed_interfaces = []
+ self._cur_object = None
+
+ self.state = DBusXMLParser.STATE_TOP
+ self.state_stack = []
+ self._cur_object = None
+ self._cur_object_stack = []
+
+ self._parser.Parse(xml_data)
+
+ COMMENT_STATE_BEGIN = 'begin'
+ COMMENT_STATE_PARAMS = 'params'
+ COMMENT_STATE_BODY = 'body'
+ COMMENT_STATE_SKIP = 'skip'
+
+ def handle_char_data(self, data):
+ #print 'char_data=%s'%data
+ pass
+
+ def handle_start_element(self, name, attrs):
+ old_state = self.state
+ old_cur_object = self._cur_object
+ if self.state == DBusXMLParser.STATE_TOP:
+ if name == DBusXMLParser.STATE_NODE:
+ self.state = DBusXMLParser.STATE_NODE
+ else:
+ raise RuntimeError('Cannot go from state "%s" to element with name "%s"'%(self.state, name))
+ elif self.state == DBusXMLParser.STATE_NODE:
+ if name == DBusXMLParser.STATE_INTERFACE:
+ self.state = DBusXMLParser.STATE_INTERFACE
+ iface = Interface(attrs['name'])
+ self._cur_object = iface
+ self.parsed_interfaces.append(iface)
+ elif name == DBusXMLParser.STATE_ANNOTATION:
+ self.state = DBusXMLParser.STATE_ANNOTATION
+ anno = parser.Annotation(attrs['name'], attrs['value'])
+ self._cur_object.annotations.append(anno)
+ self._cur_object = anno
+ else:
+ raise RuntimeError('Cannot go from state "%s" to element with name "%s"'%(self.state, name))
+
+ elif self.state == DBusXMLParser.STATE_INTERFACE:
+ if name == DBusXMLParser.STATE_METHOD:
+ self.state = DBusXMLParser.STATE_METHOD
+ method = Method(attrs['name'])
+ self._cur_object.methods.append(method)
+ self._cur_object = method
+ elif name == DBusXMLParser.STATE_SIGNAL:
+ self.state = DBusXMLParser.STATE_SIGNAL
+ signal = Signal(attrs['name'])
+ self._cur_object.signals.append(signal)
+ self._cur_object = signal
+ elif name == DBusXMLParser.STATE_PROPERTY:
+ self.state = DBusXMLParser.STATE_PROPERTY
+ prop = Property(attrs['name'], attrs['type'], attrs['access'])
+ self._cur_object.properties.append(prop)
+ self._cur_object = prop
+ elif name == DBusXMLParser.STATE_ANNOTATION:
+ self.state = DBusXMLParser.STATE_ANNOTATION
+ anno = Annotation(attrs['name'], attrs['value'])
+ self._cur_object.annotations.append(anno)
+ self._cur_object = anno
+ else:
+ raise RuntimeError('Cannot go from state "%s" to element with name "%s"'%(self.state, name))
+
+ elif self.state == DBusXMLParser.STATE_METHOD:
+ if name == DBusXMLParser.STATE_ARG:
+ self.state = DBusXMLParser.STATE_ARG
+ arg_name = None
+ if 'name' in attrs:
+ arg_name = attrs['name']
+ arg = Arg(arg_name, attrs['type'])
+ direction = attrs['direction']
+ if direction == 'in':
+ self._cur_object.in_args.append(arg)
+ elif direction == 'out':
+ self._cur_object.out_args.append(arg)
+ else:
+ raise RuntimeError('Invalid direction "%s"'%(direction))
+ self._cur_object = arg
+ elif name == DBusXMLParser.STATE_ANNOTATION:
+ self.state = DBusXMLParser.STATE_ANNOTATION
+ anno = Annotation(attrs['name'], attrs['value'])
+ self._cur_object.annotations.append(anno)
+ self._cur_object = anno
+ else:
+ raise RuntimeError('Cannot go from state "%s" to element with name "%s"'%(self.state, name))
+
+
+ elif self.state == DBusXMLParser.STATE_SIGNAL:
+ if name == DBusXMLParser.STATE_ARG:
+ self.state = DBusXMLParser.STATE_ARG
+ arg_name = None
+ if 'name' in attrs:
+ arg_name = attrs['name']
+ arg = Arg(arg_name, attrs['type'])
+ self._cur_object.args.append(arg)
+ self._cur_object = arg
+ elif name == DBusXMLParser.STATE_ANNOTATION:
+ self.state = DBusXMLParser.STATE_ANNOTATION
+ anno = Annotation(attrs['name'], attrs['value'])
+ self._cur_object.annotations.append(anno)
+ self._cur_object = anno
+ else:
+ raise RuntimeError('Cannot go from state "%s" to element with name "%s"'%(self.state, name))
+
+
+ elif self.state == DBusXMLParser.STATE_PROPERTY:
+ if name == DBusXMLParser.STATE_ANNOTATION:
+ self.state = DBusXMLParser.STATE_ANNOTATION
+ anno = Annotation(attrs['name'], attrs['value'])
+ self._cur_object.annotations.append(anno)
+ self._cur_object = anno
+ else:
+ raise RuntimeError('Cannot go from state "%s" to element with name "%s"'%(self.state, name))
+ elif self.state == DBusXMLParser.STATE_ARG:
+ if name == DBusXMLParser.STATE_ANNOTATION:
+ self.state = DBusXMLParser.STATE_ANNOTATION
+ anno = Annotation(attrs['name'], attrs['value'])
+ self._cur_object.annotations.append(anno)
+ self._cur_object = anno
+ else:
+ raise RuntimeError('Cannot go from state "%s" to element with name "%s"'%(self.state, name))
+ elif self.state == DBusXMLParser.STATE_ANNOTATION:
+ if name == DBusXMLParser.STATE_ANNOTATION:
+ self.state = DBusXMLParser.STATE_ANNOTATION
+ anno = Annotation(attrs['name'], attrs['value'])
+ self._cur_object.annotations.append(anno)
+ self._cur_object = anno
+ else:
+ raise RuntimeError('Cannot go from state "%s" to element with name "%s"'%(self.state, name))
+ else:
+ raise RuntimeError('Unhandled state "%s" while entering element with name "%s"'%(self.state, name))
+
+ self.state_stack.append(old_state)
+ self._cur_object_stack.append(old_cur_object)
+
+ def handle_end_element(self, name):
+ self.state = self.state_stack.pop()
+ self._cur_object = self._cur_object_stack.pop()
+
+def parse_dbus_xml(xml_data):
+ parser = DBusXMLParser(xml_data)
+ return parser.parsed_interfaces
More information about the Commits
mailing list