[Telepathy-commits] [telepathy-spec/master] More work on parsing bits and pieces

Davyd Madeley davyd at madeley.id.au
Mon Mar 23 12:29:16 PDT 2009


---
 tools/specparser.py |  127 +++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 104 insertions(+), 23 deletions(-)

diff --git a/tools/specparser.py b/tools/specparser.py
index 8322d9f..0d6f539 100644
--- a/tools/specparser.py
+++ b/tools/specparser.py
@@ -19,34 +19,77 @@ class base (object):
 
        Don't instantiate this class directly.
     """
-    def __init__ (self, namespace, dom):
+    def __init__ (self, parent, namespace, dom):
         name = dom.getAttribute ('name')
         self.name = '.'.join (
             filter (lambda n: n is not None,
                     [namespace, name.replace (' ', '')])
             )
-    
+
+        self.parent = parent
+
+    def get_interface (self):
+        return self.parent.get_interface ()
+
     def __repr__ (self):
         return '%s(%s)' % (self.__class__.__name__, self.name)
 
-class Method (base): pass
+class Method (base):
+    def __init__ (self, parent, namespace, dom):
+        super (Method, self).__init__ (parent, namespace, dom)
+
+        args = map (lambda n: Arg (self, None, n),
+                         dom.getElementsByTagName ('arg'))
+
+        # separate arguments as input and output arguments
+        self.in_args = filter (lambda a: a.direction == Arg.DIRECTION_IN, args)
+        self.out_args = filter (lambda a: a.direction == Arg.DIRECTION_OUT, args)
 
 class Property (base): pass
 
-class Signal (base): pass
+class Arg (base):
+    DIRECTION_IN, DIRECTION_OUT = range (2)
+
+    def __init__ (self, parent, namespace, dom):
+        super (Arg, self).__init__ (parent, namespace, dom)
+
+        type_ = dom.getAttributeNS (XMLNS_TP, 'type')
+        self.type = lookup_type (type_)
+
+        self.dbus_type = dom.getAttribute ('type')
+
+        direction = dom.getAttribute ('direction')
+        if direction == 'in':
+            self.direction = self.DIRECTION_IN
+        elif direction == 'out' or direction == '':
+            self.direction = self.DIRECTION_OUT
+        else:
+            class UnknownDirection (Exception): pass
+            raise UnknownDirection ("Unknown direction `%s' on %s" % (
+                                    direction, self.parent))
+
+    def __repr__ (self):
+        return '%s(%s:%s)' % (self.__class__.__name__, self.name, self.dbus_type)
+
+class Signal (base):
+    def __init__ (self, parent, namespace, dom):
+        super (Signal, self).__init__ (parent, namespace, dom)
+
+        self.args = map (lambda n: Arg (self, None, n),
+                         dom.getElementsByTagName ('arg'))
 
 class Interface (base):
-    def __init__ (self, namespace, dom):
-        super (Interface, self).__init__ (namespace, dom)
+    def __init__ (self, parent, namespace, dom):
+        super (Interface, self).__init__ (parent, namespace, dom)
 
-        # build a dictionary of methods in this spec
-        self.methods = build_dict (Method, self.name,
+        # build a dictionary of methods in this interface
+        self.methods = build_dict (self, Method, self.name,
                                    dom.getElementsByTagName ('method'))
-        # build a dictionary of properties in this spec
-        self.properties = build_dict (Property, self.name,
+        # build a dictionary of properties in this interface
+        self.properties = build_dict (self, Property, self.name,
                                       dom.getElementsByTagName ('property'))
-        # build a dictionary of signals in this spec
-        self.signals = build_dict (Signal, self.name,
+        # build a dictionary of signals in this interface
+        self.signals = build_dict (self, Signal, self.name,
                                    dom.getElementsByTagName ('signal'))
 
         # print '-'*78
@@ -54,6 +97,9 @@ class Interface (base):
         # print self.properties
         # print self.signals
 
+    def get_interface (self):
+        return self
+
 class Error (base): pass
 
 class DBusType (base):
@@ -67,7 +113,25 @@ class SimpleType (DBusType): pass
 
 class Mapping (DBusType): pass
 
-def build_dict (type_, namespace, nodes):
+class Struct (DBusType): pass
+
+class Enum (DBusType): pass
+
+class Flags (DBusType): pass
+
+def lookup_type (type_):
+    if type_.endswith ('[]'):
+        type_ = type_[:-2]
+
+    if type_ == '': return None
+    elif type_ in types:
+        return types[type_]
+
+    class UnknownType (Exception): pass
+
+    raise UnknownType ("Type `%s' is unknown" % type_)
+
+def build_dict (parent, type_, namespace, nodes):
     """Build a dictionary of D-Bus names to Python objects representing that
        name using the XML node for that item in the spec.
 
@@ -78,27 +142,44 @@ def build_dict (type_, namespace, nodes):
     """
 
     def build_tuple (node):
-        o = type_ (namespace, node)
+        o = type_ (parent, namespace, node)
         return (o.name, o)
 
     return dict (build_tuple (n) for n in nodes)
 
+def parse_types (parent, dom, d = None):
+    """Parse all of the types of type nodes mentioned in 't' from the node
+       'dom' and insert them into the dictionary 'd'.
+    """
+    t = [
+        (SimpleType,    'simple-type'),
+        (Enum,          'enum'),
+        (Flags,         'flags'),
+        (Mapping,       'mapping'),
+        (Struct,        'struct'),
+    ]
+
+    if d is None: d = {}
+
+    for (type_, tagname) in t:
+        d.update (build_dict (parent, type_, None,
+                    dom.getElementsByTagNameNS (XMLNS_TP, tagname)))
+
+    return d
+
 def parse (filename):
     dom = xml.dom.minidom.parse (filename)
     xincludator.xincludate (dom, filename)
 
     # build a dictionary of errors in this spec
     errorsnode = dom.getElementsByTagNameNS (XMLNS_TP, 'errors')[0]
-    errors.update (build_dict (Error, errorsnode.getAttribute ('namespace'),
-                         errorsnode.getElementsByTagNameNS (XMLNS_TP, 'error')))
-    # build a dictionary of types in this spec
-    typesnode = dom.getElementsByTagNameNS (XMLNS_TP, 'generic-types')[0]
-    types.update (build_dict (SimpleType, None,
-                    typesnode.getElementsByTagNameNS (XMLNS_TP, 'simple-type')))
-    types.update (build_dict (Mapping, None,
-                    typesnode.getElementsByTagNameNS (XMLNS_TP, 'mapping')))
+    errors.update (build_dict (None, Error,
+                    errorsnode.getAttribute ('namespace'),
+                    errorsnode.getElementsByTagNameNS (XMLNS_TP, 'error')))
+    # build a dictionary of ALL types in this spec
+    parse_types (None, dom, types)
     # build a dictionary of interfaces in this spec
-    interfaces = build_dict (Interface, None,
+    interfaces = build_dict (None, Interface, None,
                              dom.getElementsByTagName ('interface'))
 
     return interfaces
-- 
1.5.6.5




More information about the telepathy-commits mailing list