[telepathy-spec/master] Support nested <tp:section> tags.

Davyd Madeley davyd at madeley.id.au
Thu Mar 26 19:55:09 PDT 2009


---
 doc/templates/index.html |   45 +++++++++++++-----------
 tools/specparser.py      |   83 +++++++++++++++++++++++++--------------------
 2 files changed, 70 insertions(+), 58 deletions(-)

diff --git a/doc/templates/index.html b/doc/templates/index.html
index 4679ae4..e7e5667 100644
--- a/doc/templates/index.html
+++ b/doc/templates/index.html
@@ -24,30 +24,33 @@
   <a name="interfaces"></a>
   <h3>Interfaces</h3>
   <ul>
-  #for ($chapter, $interfaces) in $spec.group_by_chapters()
-   #if $chapter is not None
-    <li class="chapter">$chapter.short_name</li>
-    $chapter.get_docstring()
-    <ul>
-   #end if
-   #for $interface in $interfaces
-    #if $interface.causes_havoc
-     <li class="causes-havoc">
-    #elif $interface.deprecated
-     <li class="deprecated">
+  #def output($items)
+   #for $item in $items
+    #if $item.__class__.__name__ == 'Section'
+     <li class="chapter">$item.short_name</li>
+     $item.get_docstring()
+     <ul>
+      $output($item.items)
+     </ul>
     #else
-     <li>
-    #end if
-     <a href="$interface.get_url()">$interface.name</a>
-     #if $interface.causes_havoc
-      (unstable)
-     #elif $interface.deprecated
-      (deprecated)
+     #if $item.causes_havoc
+      <li class="causes-havoc">
+     #elif $item.deprecated
+      <li class="deprecated">
+     #else
+      <li>
      #end if
-    </li>
+      <a href="$item.get_url()">$item.name</a>
+      #if $item.causes_havoc
+       (unstable)
+      #elif $item.deprecated
+       (deprecated)
+      #end if
+     </li>
+    #end if
    #end for
-   #if $chapter: </ul>
-  #end for
+  #end def
+  $output($spec.items)
   </ul>
 
   <a name="other"></a>
diff --git a/tools/specparser.py b/tools/specparser.py
index 0caab84..4ad4226 100644
--- a/tools/specparser.py
+++ b/tools/specparser.py
@@ -24,7 +24,6 @@
 
 import sys
 import xml.dom.minidom
-from itertools import groupby
 
 import xincludator
 
@@ -217,10 +216,6 @@ class Base(object):
     def __repr__(self):
         return '%s(%s)' % (self.__class__.__name__, self.name)
 
-class Chapter(Base):
-    def get_root_namespace(self):
-        return None
-
 class PossibleError(Base):
     def __init__(self, parent, namespace, dom):
         super(PossibleError, self).__init__(parent, namespace, dom)
@@ -396,19 +391,6 @@ class External(object):
     def __repr__(self):
         return '%s(%s)' % (self.__class__.__name__, self.name)
 
-def get_chapter_node (dom):
-    """Walk up the DOM tree until we hit either tp:chapter (at which point
-       we return the chapter node) or tp:spec (at which point we return None).
-    """
-
-    if dom.parentNode.namespaceURI == XMLNS_TP:
-        if dom.parentNode.localName == 'chapter':
-            return dom.parentNode
-        elif dom.parentNode.localName == 'spec':
-            return None
-
-    return get_chapter_node(dom.parentNode)
-
 class Interface(Base):
     def __init__(self, parent, namespace, dom):
         super(Interface, self).__init__(parent, namespace, dom)
@@ -437,9 +419,6 @@ class Interface(Base):
         self.requires = map(lambda n: n.getAttribute('interface'),
                              getChildrenByName(dom, XMLNS_TP, 'requires'))
 
-        # find out if this interface is part of a chapter
-        self.chapter = get_chapter_node(dom)
-
     def get_interface(self):
         return self
 
@@ -649,7 +628,43 @@ class Flags(EnumLike):
                         dom.getElementsByTagNameNS(XMLNS_TP, 'flag'))
         self.flags = self.values # in case you're looking for it
 
-class Spec(object):
+class SectionBase(object):
+    """A SectionBase is an abstract base class for any type of node that can
+       contain a <tp:section>, which means the top-level Spec object, or any
+       Section object.
+
+       It should not be instantiated directly.
+    """
+
+    def __init__(self, dom):
+
+        self.items = []
+
+        def recurse(nodes):
+            # iterate through the list of child nodes
+            for node in nodes:
+                if node.nodeType != node.ELEMENT_NODE: continue
+
+                if node.tagName == 'node':
+                    # recurse into this level for interesting items
+                    recurse(node.childNodes)
+                elif node.namespaceURI == XMLNS_TP and \
+                     node.localName == 'section':
+                    self.items.append(Section(self, None, node))
+                elif node.tagName == 'interface':
+                    self.items.append(Interface(self, None, node))
+
+        recurse(dom.childNodes)
+
+class Section(Base, SectionBase):
+    def __init__(self, parent, namespace, dom):
+        Base.__init__(self, parent, namespace, dom)
+        SectionBase.__init__(self, dom)
+
+    def get_root_namespace(self):
+        return None
+
+class Spec(SectionBase):
     def __init__(self, dom):
         # build a dictionary of errors in this spec
         try:
@@ -666,9 +681,16 @@ class Spec(object):
                         dom.getElementsByTagNameNS(XMLNS_TP, 'generic-types')),
                 [])
 
+        # create a top-level section for this Spec
+        SectionBase.__init__(self, dom.documentElement)
+
         # build a list of interfaces in this spec
-        self.interfaces = build_list(self, Interface, None,
-                                 dom.getElementsByTagName('interface'))
+        self.interfaces = []
+        def recurse(items):
+            for item in items:
+                if isinstance(item, Section): recurse(item.items)
+                elif isinstance(item, Interface): self.interfaces.append(item)
+        recurse(self.items)
 
         # build a giant dictionary of everything (interfaces, methods, signals
         # and properties); also build a dictionary of types
@@ -718,19 +740,6 @@ class Spec(object):
     def get_spec(self):
         return self
 
-    def group_by_chapters(self):
-        """Group consecutive interfaces that are part of the same chapter.
-        """
-        spec = self.get_spec()
-
-        def chapter(dom):
-            # ignore None elements
-            if dom is not None: return Chapter(spec, None, dom)
-            else: return None
-
-        return [ (chapter(c), list(i))
-            for (c, i) in groupby(self.interfaces, key=lambda i: i.chapter) ]
-
     def lookup(self, name, namespace=None):
         key = build_name(namespace, name)
         return self.everything[key]
-- 
1.5.6.5




More information about the telepathy-commits mailing list