summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile.am2
-rw-r--r--configure.ac1
-rw-r--r--doc/templates/devhelp.devhelp218
-rw-r--r--doc/templates/errors.html60
-rw-r--r--doc/templates/fullindex.html60
-rw-r--r--doc/templates/generic-types.html59
-rw-r--r--doc/templates/index.html66
-rw-r--r--doc/templates/interface.html424
-rw-r--r--doc/templates/interfaces.html50
-rw-r--r--doc/templates/style.css224
-rw-r--r--extensions/Logger.xml (renamed from extensions/Telepathy_Logger.xml)39
-rw-r--r--extensions/Makefile.am42
-rw-r--r--extensions/all.xml129
-rw-r--r--extensions/extensions.c5
-rw-r--r--extensions/extensions.h15
-rwxr-xr-xtools/doc-generator.py104
-rw-r--r--tools/identity.xsl7
-rw-r--r--tools/specparser.py885
19 files changed, 2024 insertions, 168 deletions
diff --git a/.gitignore b/.gitignore
index 34330c8..472cc1e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,7 +50,7 @@ telepathy-logger/libtelepathy-logger.pc
telepathy-logger/libtelepathy-logger-uninstalled.pc
extensions/_gen/
-extensions/extensions.html
+extensions/doc/
tests/test-*[^ch]
tests/twisted/telepathy-logger-debug
tests/twisted/tools/org.freedesktop.Telepathy.Client.TelepathyLogger.service
diff --git a/Makefile.am b/Makefile.am
index 15a8471..fa54155 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = tools telepathy-logger data src tests doc
+SUBDIRS = tools extensions telepathy-logger data src tests doc
ACLOCAL_AMFLAGS = -I m4
diff --git a/configure.ac b/configure.ac
index 352362b..e6f99ea 100644
--- a/configure.ac
+++ b/configure.ac
@@ -221,6 +221,7 @@ AC_OUTPUT([
doc/Makefile
doc/reference/Makefile
doc/reference/libtelepathy-logger/Makefile
+ extensions/Makefile
src/Makefile
telepathy-logger/Makefile
telepathy-logger/libtelepathy-logger.pc
diff --git a/doc/templates/devhelp.devhelp2 b/doc/templates/devhelp.devhelp2
new file mode 100644
index 0000000..af327fa
--- /dev/null
+++ b/doc/templates/devhelp.devhelp2
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<book xmlns="http://www.devhelp.net/book" title="$spec.title" name="$name" link="index.html">
+ <chapters>
+#for $interface in $spec.interfaces
+ <sub name="$interface.name" link="$interface.get_url()"/>
+#end for
+ <sub name="Generic Types" link="generic-types.html"/>
+ <sub name="Errors" link="errors.html"/>
+ <sub name="Full Index" link="fullindex.html"/>
+ </chapters>
+ <functions>
+#for $obj in $spec.everything.values() + $spec.types.values() + $spec.errors.values()
+ <keyword type="$obj.devhelp_name" name="$obj.get_title()" link="$obj.get_url()" #slurp
+#if $obj.deprecated: deprecated="true" #slurp
+/>
+#end for
+ </functions>
+</book>
diff --git a/doc/templates/errors.html b/doc/templates/errors.html
new file mode 100644
index 0000000..907d660
--- /dev/null
+++ b/doc/templates/errors.html
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" "">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+ <head>
+ <title>Errors</title>
+ <link rel="stylesheet" href="style.css" type="text/css"/>
+ </head>
+ <body>
+ <div class="header">
+ <h1>Errors</h1>
+ <a href="index.html">Interface Index</a>
+ (<a href="interfaces.html">Compact</a>)
+ | <a href="#summary">Summary</a>
+ | <a href="#errors">Errors</a>
+ </div>
+ <div class="main">
+ <div class="summary">
+ <a name="summary"></a>
+ <h3>Errors</h3>
+ <table class="summary">
+ #for $error in $spec.errors.values()
+ #if $error.deprecated
+ <tr class="deprecated">
+ #else
+ <tr>
+ #end if
+ <td><a href="$error.get_url()">$error.short_name</a></td>
+ <td>
+ #if $error.deprecated: (deprecated)
+ </td>
+ </tr>
+ #end for
+ </table>
+ </div>
+
+ <div class="outset errors error">
+ <a name="errors"></a>
+ <h1>Errors</h1>
+ #for $error in $spec.errors.values()
+ <div class="inset error">
+ <a name="$error.name"></a>
+ <span class="permalink">(<a href="$error.get_url()">Permalink</a>)</span>
+ <h2>
+ $error.short_name
+ </h2>
+
+ <div class="indent">
+ <code>$error.name</code>
+ </div>
+
+ $error.get_added()
+ $error.get_deprecated()
+ $error.get_docstring()
+ </div>
+ #end for
+ </div>
+ </div>
+
+ </body>
+</html>
diff --git a/doc/templates/fullindex.html b/doc/templates/fullindex.html
new file mode 100644
index 0000000..2c465e1
--- /dev/null
+++ b/doc/templates/fullindex.html
@@ -0,0 +1,60 @@
+#from itertools import groupby
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" "">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+ <head>
+ <title>Full Index</title>
+ <link rel="stylesheet" href="style.css" type="text/css"/>
+ </head>
+
+#set $star = []
+#for $item in $spec.everything.values() + $spec.errors.values() + $spec.generic_types
+ #echo $star.append(($item.short_name, $item))
+ #slurp
+#end for
+#echo $star.sort(key = lambda t: t[0].title())
+#slurp
+## one use iterators...
+#set $groups = [ (l, list(g)) for l, g in (groupby($star, key = lambda t: t[0][0].upper())) ]
+#set $letters = set(map(lambda t: t[0], groups))
+
+ <body>
+ <div class="header">
+ <h1>Full Index</h1>
+ <a href="index.html">Interface Index</a>
+ (<a href="interfaces.html">Compact</a>)
+ #for $a in map(chr, xrange(ord('A'), ord('Z')+1))
+ #if $a in $letters
+ | <a href="#$a">$a</a>
+ #else
+ | $a
+ #end if
+ #end for
+ </div>
+
+ <div class="main">
+ <table class="summary">
+ #for l, g in $groups
+ <tr><th colspan="3"><a name="$l"></a>$l</th></tr>
+ #for $n in $g
+ #if $n[1].deprecated
+ <tr class="deprecated">
+ #else
+ <tr>
+ #end if
+ <td>
+ <a href="$n[1].get_url()" title="$n[1].get_title()">$n[0]</a>
+ #if $n[1].deprecated: (deprecated)
+ </td>
+ <td>$n[1].get_type_name()</td>
+ <td>
+ #if $n[1].parent.__class__.__name__ == 'Interface': $n[1].parent.name
+ </td>
+ </tr>
+ #end for
+ #end for
+ <table>
+ </div>
+
+ </body>
+</html>
diff --git a/doc/templates/generic-types.html b/doc/templates/generic-types.html
new file mode 100644
index 0000000..0bb209e
--- /dev/null
+++ b/doc/templates/generic-types.html
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" "">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+ <head>
+ <title>Generic Types</title>
+ <link rel="stylesheet" href="style.css" type="text/css"/>
+ </head>
+ <body>
+ <div class="header">
+ <h1>Generic Types</h1>
+ <a href="index.html">Interface Index</a>
+ (<a href="interfaces.html">Compact</a>)
+ | <a href="#summary">Summary</a>
+ | <a href="#types">Types</a>
+ </div>
+ <div class="main">
+ <div class="summary">
+ <a name="summary"></a>
+ <h3>Generic Types</h3>
+ <table class="summary">
+ #for $type in $spec.generic_types
+ #if $type.deprecated
+ <tr class="deprecated">
+ #else
+ <tr>
+ #end if
+ <td><a href="$type.get_url()">$type.short_name</a></td>
+ <td>$type.get_type_name()</td>
+ <td>$type.dbus_type</td>
+ <td>
+ #if $type.deprecated: (deprecated)
+ </td>
+ </tr>
+ #end for
+ </table>
+ </div>
+
+ <div class="outset types type">
+ <a name="types"></a>
+ <h1>Generic Types</h1>
+ #for $type in $spec.generic_types
+ <div class="inset type">
+ <a name="$type.name"></a>
+ <span class="permalink">$type.get_type_name() (<a href="$type.get_url()">Permalink</a>)</span>
+ <h2>
+ $type.short_name &mdash; $type.dbus_type
+ </h2>
+
+ $type.get_added()
+ $type.get_deprecated()
+ $type.get_docstring()
+ $type.get_breakdown()
+ </div>
+ #end for
+ </div>
+ </div>
+
+ </body>
+</html>
diff --git a/doc/templates/index.html b/doc/templates/index.html
new file mode 100644
index 0000000..efc38d4
--- /dev/null
+++ b/doc/templates/index.html
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" "">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+ <head>
+ <title>$spec.title &mdash v$spec.version</title>
+ <link rel="stylesheet" href="style.css" type="text/css"/>
+ </head>
+ <body>
+ <div class="header">
+ <h1>$spec.title</h1>
+ <a href="#interfaces">Interfaces</a>
+ (<a href="interfaces.html">Compact</a>)
+ | <a href="generic-types.html">Generic Types</a>
+ | <a href="errors.html">Errors</a>
+ | <a href="fullindex.html">Full Index</a>
+ </div>
+
+ <div class="main">
+ <h3 class="version">Version $spec.version</h3>
+ <p class="copyrights">
+ #echo '<br/>'.join($spec.copyrights)
+ </p>
+ $spec.license
+
+ <a name="interfaces"></a>
+ <h3>Interfaces</h3>
+ <ul>
+ #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
+ #if $item.causes_havoc
+ <li class="causes-havoc">
+ #elif $item.deprecated
+ <li class="deprecated">
+ #else
+ <li>
+ #end if
+ <a href="$item.get_url()">$item.name</a>
+ #if $item.causes_havoc
+ (unstable)
+ #elif $item.deprecated
+ (deprecated)
+ #end if
+ </li>
+ #end if
+ #end for
+ #end def
+ $output($spec.items)
+ </ul>
+
+ <a name="other"></a>
+ <h3>Other</h3>
+ <ul>
+ <li><a href="generic-types.html">Generic Types</a></li>
+ <li><a href="errors.html">Errors</a></li>
+ </ul>
+
+ </div>
+ </body>
+</html>
diff --git a/doc/templates/interface.html b/doc/templates/interface.html
new file mode 100644
index 0000000..79c35b2
--- /dev/null
+++ b/doc/templates/interface.html
@@ -0,0 +1,424 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" "">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+ <head>
+ <title>$interface.name</title>
+ <link rel="stylesheet" href="style.css" type="text/css"/>
+ </head>
+ <body>
+ <div class="header">
+ <h1>Interface $interface.name</h1>
+ <a href="index.html">Interface Index</a>
+ (<a href="interfaces.html">Compact</a>)
+ | <a href="#summary">Summary</a>
+ #if $interface.docstring: | <a href="#description">Description</a>
+ #if $interface.methods: | <a href="#methods">Methods</a>
+ #if $interface.signals: | <a href="#signals">Signals</a>
+ #if $interface.properties: | <a href="#properties">Properties</a>
+ #if $interface.tpproperties: | <a href="#tpproperties">Telepathy Properties</a>
+ #if $interface.contact_attributes: | <a href="#contact-attributes">Contact Attributes</a>
+ #if $interface.handler_capability_tokens: | <a href="#handler-capability-tokens">Handler Capability Tokens</a>
+ #if $interface.types: | <a href="#types">Types</a>
+ </div>
+ <div class="main">
+
+ #if $interface.methods or $interface.signals or $interface.properties or $interface.types or $interface.tpproperties
+ <div class="summary">
+ <a name="summary"></a>
+ #if $interface.methods
+ <h3>Methods</h3>
+ <table class="summary">
+ #for $method in $interface.methods
+ #if $method.deprecated
+ <tr class="deprecated">
+ #else
+ <tr>
+ #end if
+ <td><a href="$method.get_url()">$method.short_name</a></td>
+ <td>($method.get_in_args())</td>
+ <td>&#8594;</td>
+ <td>$method.get_out_args()</td>
+ <td>
+ #if $method.deprecated: (deprecated)
+ </td>
+ </tr>
+ #end for
+ </table>
+ #end if
+
+ #if $interface.signals
+ <h3>Signals</h3>
+ <table class="summary">
+ #for $signal in $interface.signals
+ #if $signal.deprecated
+ <tr class="deprecated">
+ #else
+ <tr>
+ #end if
+ <td><a href="$signal.get_url()">$signal.short_name</a></td>
+ <td>($signal.get_args())</td>
+ <td>
+ #if $signal.deprecated: (deprecated)
+ </td>
+ </tr>
+ #end for
+ </table>
+ #end if
+
+ #if $interface.properties
+ <h3>Properties</h3>
+ <table class="summary">
+ #for $property in $interface.properties
+ #if $property.deprecated
+ <tr class="deprecated">
+ #else
+ <tr>
+ #end if
+ <td><a href="$property.get_url()">$property.short_name</a></td>
+ <td>
+ $property.dbus_type
+ #if $property.type: (<a href="$property.get_type_url()" title="$property.get_type_title()">$property.get_type().short_name</a>)
+ </td>
+ <td>$property.get_access()</td>
+ <td>
+ #if $property.deprecated: (deprecated)
+ </td>
+ </tr>
+ #end for
+ </table>
+ #end if
+
+ #if $interface.tpproperties
+ <h3>Telepathy Properties</h3>
+ <table class="summary">
+ #for $property in $interface.tpproperties
+ <tr class="deprecated">
+ <td><a href="$property.get_url()">$property.short_name</a></td>
+ <td>
+ $property.dbus_type
+ #if $property.type: (<a href="$property.get_type_url()" title="$property.get_type_title()">$property.get_type().short_name</a>)
+ </td>
+ </tr>
+ #end for
+ </table>
+ #end if
+
+ #if $interface.contact_attributes
+ <h3>Contact Attributes</h3>
+ <table class="summary">
+ #for $token in $interface.contact_attributes
+ <tr class="contact-attribute">
+ <td><a href="$token.get_url()">$token.name</a></td>
+ <td>
+ $token.dbus_type
+ #if $token.type: (<a href="$token.get_type_url()" title="$token.get_type_title()">$token.get_type().short_name</a>)
+ </td>
+ </tr>
+ #end for
+ </table>
+ #end if
+
+ #if $interface.handler_capability_tokens
+ <h3>Handler Capability Tokens</h3>
+ <table class="summary">
+ #for $token in $interface.handler_capability_tokens
+ <tr class="handler-capability-token">
+ <td><a href="$token.get_url()">$token.name</a>
+ #if $token.is_family
+ (etc.)
+ #end if
+ </td>
+ <td>
+ </td>
+ </tr>
+ #end for
+ </table>
+ #end if
+
+ #if $interface.types
+ <h3>Types</h3>
+ <table class="summary">
+ #for $type in $interface.types
+ #if type.deprecated
+ <tr class="deprecated">
+ #else
+ <tr>
+ #end if
+ <td><a href="$type.get_url()">$type.short_name</a></td>
+ <td>$type.get_type_name()</td>
+ <td>$type.dbus_type</td>
+ <td>
+ #if $type.deprecated: (deprecated)
+ </td>
+ </tr>
+ #end for
+ </table>
+ #end if
+ </div>
+ #end if
+
+ #if $interface.causes_havoc
+ <div class="havoc"><span class="warning">WARNING:</span>
+ This interface is $interface.causes_havoc and is likely to cause havoc
+ to your API/ABI if bindings are generated. Do not include this interface
+ in libraries that care about compatibility.
+ </div>
+ #end if
+ $interface.get_added()
+ $interface.get_changed()
+ $interface.get_deprecated()
+
+ #if $interface.requires
+ <div class="requires">
+ Objects implementing this interface must also implement:
+ <ul>
+ #for $req in $interface.get_requires()
+ <li><a href="$req.get_url()" title="$req.get_title()">$req.name</a></li>
+ #end for
+ </ul>
+ </div>
+ #end if
+
+ #if $interface.docstring
+ <a name="description"></a>
+ <h3>Description</h3>
+ $interface.get_docstring()
+ #end if
+
+ #if $interface.methods
+ <div class="outset methods method">
+ <a name="methods"></a>
+ <h1>Methods</h1>
+ #for $method in $interface.methods
+ <div class="inset method">
+ <a name="$method.name"></a>
+ <span class="permalink">(<a href="$method.get_url()">Permalink</a>)</span>
+ <h2>$method.short_name ($method.get_in_args()) &#8594; $method.get_out_args()</h2>
+
+ $method.get_added()
+ $method.get_changed()
+ $method.get_deprecated()
+
+ #if $method.in_args
+ <div class="indent">
+ <h3>Parameters</h3>
+ <ul>
+ #for $arg in $method.in_args
+ <li>
+ $arg.short_name &mdash; $arg.dbus_type
+ #if $arg.get_type(): (<a href="$arg.get_type_url()" title="$arg.get_type_title()">$arg.get_type().short_name</a>)
+ </li>
+ $arg.get_added()
+ $arg.get_changed()
+ $arg.get_deprecated()
+ $arg.get_docstring()
+ #end for
+ </ul>
+ </div>
+ #end if
+
+ #if $method.out_args
+ <div class="indent">
+ <h3>Returns</h3>
+ <ul>
+ #for $arg in $method.out_args
+ <li>
+ $arg.short_name &mdash; $arg.dbus_type
+ #if $arg.get_type(): (<a href="$arg.get_type_url()" title="$arg.get_type_title()">$arg.get_type().short_name</a>)
+ </li>
+ $arg.get_added()
+ $arg.get_changed()
+ $arg.get_deprecated()
+ $arg.get_docstring()
+ #end for
+ </ul>
+ </div>
+ #end if
+
+ $method.get_docstring()
+
+ #if $method.possible_errors
+ <hr/>
+ <div class="indent">
+ <h3>Possible Errors</h3>
+ <ul>
+ #for $error in $method.possible_errors
+ <li><a href="$error.get_url()" title="$error.get_title()">$error.get_error().short_name</a></li>
+ $error.get_added()
+ $error.get_changed()
+ $error.get_deprecated()
+ $error.get_docstring()
+ #end for
+ </ul>
+ </div>
+ #end if
+ </div>
+ #end for
+ </div>
+ #end if
+
+ #if $interface.signals
+ <div class="outset signals signal">
+ <a name="signals"></a>
+ <h1>Signals</h1>
+ #for $signal in $interface.signals
+ <div class="inset signal">
+ <a name="$signal.name"></a>
+ <span class="permalink">(<a href="$signal.get_url()">Permalink</a>)</span>
+ <h2>$signal.short_name ($signal.get_args())</h2>
+
+ $signal.get_added()
+ $signal.get_changed()
+ $signal.get_deprecated()
+
+ #if $signal.args
+ <div class="indent">
+ <h3>Parameters</h3>
+ <ul>
+ #for $arg in $signal.args
+ <li>
+ $arg.short_name &mdash; $arg.dbus_type
+ #if $arg.get_type(): (<a href="$arg.get_type_url()" title="$arg.get_type_title()">$arg.get_type().short_name</a>)
+ </li>
+ $arg.get_added()
+ $arg.get_changed()
+ $arg.get_deprecated()
+ $arg.get_docstring()
+ #end for
+ </ul>
+ </div>
+ #end if
+
+ $signal.get_docstring()
+ </div>
+ #end for
+ </div>
+ #end if
+
+ #if $interface.properties
+ <div class="outset properties property">
+ <a name="properties"></a>
+ <h1>Properties</h1>
+ <div>
+ Accessed using the org.freedesktop.DBus.Properties interface.
+ </div>
+ #for $property in $interface.properties
+ <div class="inset property">
+ <a name="$property.name"></a>
+ <span class="permalink">(<a href="$property.get_url()">Permalink</a>)</span>
+ <h2>
+ $property.short_name &mdash; $property.dbus_type
+ #if $property.type: (<a href="$property.get_type_url()" title="$property.get_type_title()">$property.get_type().short_name</a>)
+ </h2>
+ <div class="access">$property.get_access()</div>
+
+ $property.get_added()
+ $property.get_changed()
+ $property.get_deprecated()
+ $property.get_docstring()
+ </div>
+ #end for
+ </div>
+ #end if
+
+ #if $interface.tpproperties
+ <div class="outset tpproperties tpproperty">
+ <a name="tpproperties"></a>
+ <h1>Telepathy Properties</h1>
+ <div>
+ Accessed using the org.freedesktop.Telepathy.Properties interface.
+ </div>
+ #for $property in $interface.tpproperties
+ <div class="inset tpproperty">
+ <a name="$property.name"></a>
+ <span class="permalink">(<a href="$property.get_url()">Permalink</a>)</span>
+ <h2>
+ $property.short_name &mdash; $property.dbus_type
+ #if $property.type: (<a href="$property.get_type_url()" title="$property.get_type_title()">$property.get_type().short_name</a>)
+ </h2>
+ $property.get_added()
+ $property.get_changed()
+ $property.get_deprecated()
+ $property.get_docstring()
+ </div>
+ #end for
+ </div>
+ #end if
+
+ #if $interface.contact_attributes
+ <div class="outset contact-attributes">
+ <a name="contact-attributes"></a>
+ <h1>Contact Attributes</h1>
+ <div>
+ Attributes that a contact can have, accessed with the
+ org.freedesktop.Telepathy.Connection.Interface.Contacts interface.
+ </div>
+ #for $token in $interface.contact_attributes
+ <div class="inset contact-attribute">
+ <a name="$token.name"></a>
+ <span class="permalink">(<a href="$token.get_url()">Permalink</a>)</span>
+ <h2>
+ $token.name &mdash; $token.dbus_type
+ #if $token.type: (<a href="$token.get_type_url()" title="$token.get_type_title()">$token.get_type().short_name</a>)
+ </h2>
+ $token.get_added()
+ $token.get_changed()
+ $token.get_deprecated()
+ $token.get_docstring()
+ </div>
+ #end for
+ </div>
+ #end if
+
+ #if $interface.handler_capability_tokens
+ <div class="outset handler-capability-tokens">
+ <a name="handler-capability-tokens"></a>
+ <h1>Handler Capability Tokens</h1>
+ <div>
+ Tokens representing capabilities that a Client.Handler can have.
+ </div>
+ #for $token in $interface.handler_capability_tokens
+ <div class="inset handler-capability-token">
+ <a name="$token.name"></a>
+ <span class="permalink">(<a href="$token.get_url()">Permalink</a>)</span>
+ <h2>
+ $token.name
+ #if $token.is_family
+ (etc.)
+ #end if
+ </h2>
+ $token.get_added()
+ $token.get_changed()
+ $token.get_deprecated()
+ $token.get_docstring()
+ </div>
+ #end for
+ </div>
+ #end if
+
+ #if $interface.types
+ <div class="outset types type">
+ <a name="types"></a>
+ <h1>Types</h1>
+ #for $type in $interface.types
+ <div class="inset type">
+ <a name="$type.name"></a>
+ <span class="permalink">$type.get_type_name() (<a href="$type.get_url()">Permalink</a>)</span>
+ <h2>
+ $type.short_name &mdash; $type.dbus_type
+ </h2>
+
+ $type.get_added()
+ $type.get_changed()
+ $type.get_deprecated()
+ $type.get_docstring()
+ $type.get_breakdown()
+ </div>
+ #end for
+ </div>
+ #end if
+
+ </div>
+
+ </body>
+</html>
diff --git a/doc/templates/interfaces.html b/doc/templates/interfaces.html
new file mode 100644
index 0000000..a93334c
--- /dev/null
+++ b/doc/templates/interfaces.html
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" "">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+ <head>
+ <title>$spec.title &mdash v$spec.version</title>
+ <link rel="stylesheet" href="style.css" type="text/css"/>
+ </head>
+ <body>
+ <div class="header">
+ <h1>$spec.title</h1>
+ <a href="index.html">Full</a>
+ | <a href="generic-types.html">Generic Types</a>
+ | <a href="errors.html">Errors</a>
+ | <a href="fullindex.html">Full Index</a>
+ </div>
+
+ <div class="main">
+ <b>Version $spec.version</b>
+
+ <a name="interfaces"></a>
+ <h3>Interfaces</h3>
+ <ul>
+ #for $interface in $spec.interfaces
+ #if $interface.causes_havoc
+ <li class="causes-havoc">
+ #elif $interface.deprecated
+ <li class="deprecated">
+ #else
+ <li>
+ #end if
+ <a href="$interface.get_url()">$interface.name</a>
+ #if $interface.causes_havoc
+ (unstable)
+ #elif $interface.deprecated
+ (deprecated)
+ #end if
+ </li>
+ #end for
+ </ul>
+
+ <a name="other"></a>
+ <h3>Other</h3>
+ <ul>
+ <li><a href="generic-types.html">Generic Types</a></li>
+ <li><a href="errors.html">Errors</a></li>
+ </ul>
+
+ </div>
+ </body>
+</html>
diff --git a/doc/templates/style.css b/doc/templates/style.css
new file mode 100644
index 0000000..964d88b
--- /dev/null
+++ b/doc/templates/style.css
@@ -0,0 +1,224 @@
+html, body,
+h1, h2 {
+ margin: 0;
+ padding: 0;
+}
+
+h3 {
+ margin-top: 2pt;
+ margin-bottom: 2pt;
+}
+
+ul {
+ margin: 1ex;
+ margin-left: 1.5em;
+ padding: 0;
+}
+
+hr {
+ border-style: none;
+ color: #cccccc;
+ background-color: #cccccc;
+ height: 1px;
+}
+
+div.header {
+ position: fixed;
+ height: 4em;
+ background-color: white;
+ width: 100%;
+ margin: 0;
+ padding: 0.5ex;
+ border-bottom: 1px solid black;
+ top: 0;
+ left: 0;
+ z-index: 1;
+}
+
+div.header h1 {
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+
+div.main {
+ margin-top: 5em;
+ margin-left: 1ex;
+ margin-right: 1ex;
+ margin-bottom: 1ex;
+}
+
+div.main a[name] {
+ position: relative;
+ top: -4.5em;
+}
+
+div.outset {
+ padding: 1ex;
+ margin-top: 1ex;
+ margin-bottom: 1ex;
+}
+
+div.inset {
+ background-color: white;
+ margin-top: 1ex;
+ margin-bottom: 1ex;
+ padding: 0.5ex;
+}
+
+div.indent {
+ margin-left: 1em;
+}
+
+div.methods {
+ background-color: #fcaf3e;
+}
+
+div.method {
+ border: 1px solid #f57900;
+}
+
+div.signals {
+ background-color: #729fcf;
+}
+
+div.signal {
+ border: 1px solid #3465a4;
+}
+
+div.properties {
+ background-color: #ad7fa8;
+}
+
+div.property {
+ border: 1px solid #75507b;
+}
+
+div.tpproperties {
+ background-color: #999999;
+}
+
+div.tpproperty {
+ border: 1px solid #333333;
+}
+
+div.contact-attributes {
+ background-color: #ccccff;
+ border: 1px solid #9999cc;
+}
+
+div.contact-attribute {
+ border: 1px solid #9999cc;
+}
+
+div.handler-capability-tokens {
+ background-color: #339933;
+ border: 1px solid #228822;
+}
+
+div.handler-capability-token {
+ border: 1px solid #228822;
+}
+
+div.types {
+ background-color: #e9b96e;
+}
+
+div.type {
+ border: 1px solid #c17d11;
+}
+
+div.errors {
+ background-color: #ef2929;
+}
+
+div.error {
+ border: 1px solid #cc0000;
+}
+
+div.access {
+ font-weight: bold;
+ margin-left: 1ex;
+}
+
+div.summary {
+ padding: 0.5ex;
+ background-color: #eeeeec;
+ border: 1px solid #d3d7cf;
+}
+
+table.summary {
+ margin: 1ex;
+ font-size: small;
+}
+
+table.summary td {
+ padding-right: 1ex;
+}
+
+li.chapter {
+ margin-top: 1ex;
+ font-weight: bold;
+}
+
+li.causes-havoc {
+ font-style: italic;
+}
+
+li.deprecated,
+li.deprecated a,
+table.summary tr.deprecated td,
+table.summary tr.deprecated td a {
+ color: gray;
+}
+
+div.requires,
+div.docstring {
+ margin: 1ex;
+}
+
+div.added {
+ border-left: 2px solid #4e9a06;
+ margin: 1ex;
+ padding-left: 1ex;
+}
+
+div.added span.version {
+ color: #4e9a06;
+ font-weight: bold;
+}
+
+div.changed {
+ border-left: 2px solid #8f5902;
+ margin: 1ex;
+ padding-left: 1ex;
+}
+
+div.changed span.version {
+ color: #8f5902;
+ font-weight: bold;
+}
+
+div.deprecated,
+div.havoc {
+ border-left: 2px solid #a40000;
+ margin: 1ex;
+ padding-left: 1ex;
+}
+
+div.deprecated span.version,
+span.warning {
+ color: #a40000;
+ font-weight: bold;
+}
+
+div.rationale {
+ border-left: 2px solid gray;
+ margin: 1ex;
+ padding-left: 1ex;
+}
+
+span.permalink {
+ float: right;
+ font-size: x-small;
+}
diff --git a/extensions/Telepathy_Logger.xml b/extensions/Logger.xml
index 648f698..b63198b 100644
--- a/extensions/Telepathy_Logger.xml
+++ b/extensions/Logger.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" ?>
-<node name="/Telepathy_Logger"
+<node name="/Logger"
xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
<tp:copyright>Copyright © 2009 Collabora Ltd.</tp:copyright>
<tp:license xmlns="http://www.w3.org/1999/xhtml">
@@ -17,11 +17,17 @@ Lesser General Public License for more details.</p>
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</p>
</tp:license>
- <interface name="org.freedesktop.Telepathy.TelepathyLoggerService.DRAFT"
+ <interface name="org.freedesktop.Telepathy.Logger.DRAFT"
tp:causes-havoc="experimental">
<tp:added version="0.1">(as a draft)</tp:added>
- <tp:struct name="Chat_Message_Field" array-name="Chat_Message_Field_List">
+ <tp:docstring>
+ <!-- FIXME -->
+ An interface for requesting information from the Telepathy Logger
+ service.
+ </tp:docstring>
+
+ <tp:struct name="Chat_Message" array-name="Chat_Message_List">
<tp:member type="s" name="Sender">
<tp:docstring>
The identifier of the contact who originated this message.
@@ -41,33 +47,32 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</
<p>It represents a single message, received or sent.</p>
<p>The receiver is implicit in the request: if the sender is the user,
the receiver is the identifier in chat_id paramenter, if the sender is
- not the user, the user is consequently the receiver of the message<p>
+ not the user, the user is consequently the receiver of the message</p>
</tp:docstring>
</tp:struct>
- <method name="LastChats"
- tp:name-for-bindings="LastChats">
- <arg direction="in" name="Account" type="o" tp:type="Contact_Handle[]">
+ <method name="GetRecentMessages"
+ tp:name-for-bindings="Get_Recent_Messages">
+ <arg direction="in" name="Account" type="o" tp:type="Account">
<tp:docstring>
- An array of handles representing contacts.
+ <!-- FIXME -->
</tp:docstring>
</arg>
- <arg direction="in" name="Identifier" type="s"
- tp:type="Contact_Info_Map">
+ <arg direction="in" name="Identifier" type="s">
<tp:docstring>
- A dictionary mapping contact handles to information, whose keys are
- the subset of the requested list of handles for which information was
- cached.
+ <!-- FIXME -->
</tp:docstring>
</arg>
+ <arg direction="in" name="Is_Chatroom" type="b" />
+ <arg direction="in" name="Lines" type="u" />
+ <arg direction="out" name="Messages" type="a(ssu)"
+ tp:type="Chat_Message[]" />
<tp:docstring>
- Request the last Lines entries of logs for the specified couple Account+Identifier.
+ Request the last Lines entries of logs for the specified couple
+ Account+Identifier.
</tp:docstring>
</method>
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- An interface for requesting informatiosn about the Telepathy Logger entries.
- </tp:docstring>
</interface>
</node>
<!-- vim:set sw=2 sts=2 et ft=xml: -->
diff --git a/extensions/Makefile.am b/extensions/Makefile.am
index 61ba12d..bac6ce9 100644
--- a/extensions/Makefile.am
+++ b/extensions/Makefile.am
@@ -2,15 +2,16 @@ tools_dir = $(top_srcdir)/tools
EXTRA_DIST = \
all.xml \
- Telepathy_Logger.xml
+ Logger.xml \
+ $(NULL)
-noinst_LTLIBRARIES = libtelepathy-logger-extensions.la
+noinst_LTLIBRARIES = libtpl-extensions.la
-libtelepathy_logger_extensions_la_SOURCES = \
+libtpl_extensions_la_SOURCES = \
extensions.c \
extensions.h
-nodist_libtelepathy_logger_extensions_la_SOURCES = \
+nodist_libtpl_extensions_la_SOURCES = \
_gen/signals-marshal.c \
_gen/signals-marshal.h \
_gen/signals-marshal.list \
@@ -24,13 +25,12 @@ nodist_libtelepathy_logger_extensions_la_SOURCES = \
BUILT_SOURCES = \
_gen/all.xml \
- $(nodist_libtelepathy_logger_extensions_la_SOURCES) \
- extensions.html
+ $(nodist_libtpl_extensions_la_SOURCES)
CLEANFILES = $(BUILT_SOURCES)
-AM_CFLAGS = $(ERROR_CFLAGS) @DBUS_CFLAGS@ @GLIB_CFLAGS@ @TP_GLIB_CFLAGS@ @HANDLE_LEAK_DEBUG_CFLAGS@
-AM_LDFLAGS = @DBUS_LIBS@ @GLIB_LIBS@ @TP_GLIB_LIBS@
+AM_CFLAGS = $(ERROR_CFLAGS) @LIBTPL_CFLAGS@ @HANDLE_LEAK_DEBUG_CFLAGS@
+AM_LDFLAGS = @LIBTPL_LIBS@
# Generated stuff
@@ -39,24 +39,22 @@ XSLTPROCFLAGS = --nonet --novalid
_gen/all.xml: all.xml $(wildcard *.xml) Makefile.am
@$(mkdir_p) _gen
- $(AM_V_GEN)$(PYTHON) $(tools_dir)/xincludator.py \
- $< > $@.tmp && mv $@.tmp $@
-
-extensions.html: _gen/all.xml $(tools_dir)/doc-generator.xsl Makefile.am
- $(AM_V_GEN)$(XSLTPROC) $(XSLTPROCFLAGS) \
- --param "allow-undefined-interfaces" "true()" \
- $(tools_dir)/doc-generator.xsl \
+ $(AM_V_GEN)$(XSLTPROC) $(XSLTPROCFLAGS) --xinclude $(tools_dir)/identity.xsl \
$< > $@
+doc/index.html: _gen/all.xml $(tools_dir)/specparser.py $(tools_dir)/doc-generator.py Makefile.am
+ $(AM_V_GEN)$(PYTHON) $(tools_dir)/doc-generator.py all.xml doc/ \
+ telepathy-spec org.freedesktop.Telepathy
+
_gen/svc.c _gen/svc.h: _gen/all.xml $(tools_dir)/glib-ginterface-gen.py \
Makefile.am
$(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-ginterface-gen.py \
- --filename=_gen/svc --signal-marshal-prefix=_gabble_ext \
+ --filename=_gen/svc --signal-marshal-prefix=_tpl_ext \
--include='<telepathy-glib/dbus.h>' \
--include='"_gen/signals-marshal.h"' \
--allow-unstable \
--not-implemented-func='tp_dbus_g_method_return_not_implemented' \
- $< Gabble_Svc_
+ $< Tpl_Svc_
_gen/signals-marshal.list: _gen/all.xml \
$(tools_dir)/glib-signals-marshal-gen.py \
@@ -64,23 +62,23 @@ _gen/signals-marshal.list: _gen/all.xml \
$(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-signals-marshal-gen.py $< > $@
_gen/signals-marshal.h: _gen/signals-marshal.list Makefile.am
- $(AM_V_GEN)$(GLIB_GENMARSHAL) --header --prefix=_gabble_ext_marshal $< > $@
+ $(AM_V_GEN)$(GLIB_GENMARSHAL) --header --prefix=_tpl_ext_marshal $< > $@
_gen/signals-marshal.c: _gen/signals-marshal.list Makefile.am
$(AM_V_GEN){ echo '#include "_gen/signals-marshal.h"' && \
- $(GLIB_GENMARSHAL) --body --prefix=_gabble_ext_marshal $< ; } > $@
+ $(GLIB_GENMARSHAL) --body --prefix=_tpl_ext_marshal $< ; } > $@
_gen/enums.h: _gen/all.xml $(tools_dir)/c-constants-gen.py \
Makefile.am
- $(AM_V_GEN)$(PYTHON) $(tools_dir)/c-constants-gen.py Gabble $< > $@
+ $(AM_V_GEN)$(PYTHON) $(tools_dir)/c-constants-gen.py Tpl $< > $@
_gen/interfaces.h _gen/interfaces-body.h: _gen/all.xml \
$(tools_dir)/glib-interfaces-gen.py \
Makefile.am
$(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-interfaces-gen.py \
- Gabble _gen/interfaces-body.h _gen/interfaces.h $<
+ Tpl _gen/interfaces-body.h _gen/interfaces.h $<
_gen/gtypes.h _gen/gtypes-body.h: _gen/all.xml \
$(tools_dir)/glib-gtypes-generator.py Makefile.am
$(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-gtypes-generator.py \
- $< _gen/gtypes Gabble
+ $< _gen/gtypes Tpl
diff --git a/extensions/all.xml b/extensions/all.xml
index a750472..6c7af8e 100644
--- a/extensions/all.xml
+++ b/extensions/all.xml
@@ -23,135 +23,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA</p>
</tp:license>
<tp:generic-types>
- <tp:external-type name="Room_Handle" type="u"
+ <tp:external-type name="Account" type="o"
from="Telepathy specification"/>
- <tp:external-type name="Handle_Type" type="u"
- from="Telepathy specification"/>
- <tp:external-type name="Contact_Handle" type="u"
- from="Telepathy specification"/>
- <tp:external-type name="DBus_Unique_Name" type="s"
- from="Telepathy specification"/>
-</tp:generic-types>
-
-<xi:include href="Telepathy_Logger.xml"/>
-
-<tp:generic-types>
- <tp:external-type name="Contact_Handle" type="u"
- from="Telepathy specification"/>
- <tp:external-type name="DBus_Interface" type="s"
- from="Telepathy specification"/>
- <tp:external-type name="DBus_Qualified_Member" type="s"
- from="Telepathy specification"/>
- <tp:external-type name="Qualified_Property_Value_Map" type="a{sv}"
- from="Telepathy specification"/>
- <tp:external-type name="DBus_Error_Name" type="s"
- from="Telepathy specification"/>
- <tp:external-type name="DBus_Well_Known_Name" type="s"
- from="Telepathy specification"/>
- <tp:external-type name="Handler_Capability_Token" type="s"
- from="Telepathy specification"/>
-
- <!-- for localisation -->
- <tp:external-type name="Rich_Presence_Access_Control_Type" type="u"
- from="Telepathy specification"/>
- <tp:external-type name="Rich_Presence_Access_Control" type="(uv)"
- from="Telepathy specification"/>
- <tp:external-type name="Unix_Timestamp64" type="t"
- from="Telepathy specification"/>
- <tp:external-type name="Unix_Timestamp" type="u"
- from="Telepathy specification"/>
- <tp:external-type name="String_String_Map" type="a{ss}"
- from="Telepathy specification"/>
-
- <tp:external-type name="String_Variant_Map" type="a{sv}"
- from="Telepathy specification"/>
-
- <!-- use types from Connection_Interface_Requests -->
- <tp:external-type name="Channel_Class" type="a{sv}"
- from="Telepathy specification"/>
-
- <!-- use types from Channel_Type_Tubes -->
- <tp:external-type name="Socket_Address_Type" type="u"
- from="Telepathy specification"/>
- <tp:external-type name="Socket_Access_Control" type="u"
- from="Telepathy specification"/>
- <tp:external-type name="Supported_Socket_Map" type="a{uau}"
- from="Telepathy specification"/>
- <tp:external-type name="DBus_Tube_Member" type="(us)"
- from="Telepathy specification"/>
-
- <!-- use types from Connection_Interface_Contact_Capabilities -->
- <tp:external-type name="Requestable_Channel_Class" type="(a{sv}as)"
- from="Telepathy specification"/>
-
- <tp:external-type name="Connection_Status" type="u"
- from="Telepathy specification"/>
-
- <!-- use types from Channel_Type_Streamed_Media.xml -->
- <tp:enum name="Media_Stream_Type" type="u"
- array-name="Media_Stream_Type_List">
- <tp:enumvalue suffix="Audio" value="0">
- <tp:docstring>An audio stream</tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="Video" value="1">
- <tp:docstring>A video stream</tp:docstring>
- </tp:enumvalue>
- </tp:enum>
-
- <!-- use types from generic-types.xml -->
- <tp:struct name="Socket_Address_IP" array-name="Socket_Address_IP_List">
- <tp:docstring>An IP address and port.</tp:docstring>
- <tp:member type="s" name="Address">
- <tp:docstring>Either a dotted-quad IPv4 address literal as for
- <tp:type>Socket_Address_IPv4</tp:type>, or an RFC2373 IPv6 address
- as for <tp:type>Socket_Address_IPv6</tp:type>.
- </tp:docstring>
- </tp:member>
- <tp:member type="q" name="Port">
- <tp:docstring>The TCP or UDP port number.</tp:docstring>
- </tp:member>
- </tp:struct>
-
- <tp:struct name="Socket_Address_IPv4">
- <tp:docstring>An IPv4 address and port.</tp:docstring>
- <tp:member type="s" name="Address">
- <tp:docstring>A dotted-quad IPv4 address literal: four ASCII decimal
- numbers, each between 0 and 255 inclusive, e.g.
- "192.168.0.1".</tp:docstring>
- </tp:member>
- <tp:member type="q" name="Port">
- <tp:docstring>The TCP or UDP port number.</tp:docstring>
- </tp:member>
- </tp:struct>
-
- <tp:struct name="Socket_Address_IPv6">
- <tp:docstring>An IPv6 address and port.</tp:docstring>
- <tp:member type="s" name="Address">
- <tp:docstring>An IPv6 address literal as specified by RFC2373
- section 2.2, e.g. "2001:DB8::8:800:200C:4171".</tp:docstring>
- </tp:member>
- <tp:member type="q" name="Port">
- <tp:docstring>The TCP or UDP port number.</tp:docstring>
- </tp:member>
- </tp:struct>
-
- <tp:enum name="Media_Stream_State" type="u">
- <tp:enumvalue suffix="Disconnected" value="0">
- <tp:docstring>The stream is disconnected.</tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="Connecting" value="1">
- <tp:docstring>The stream is trying to connect.</tp:docstring>
- </tp:enumvalue>
- <tp:enumvalue suffix="Connected" value="2">
- <tp:docstring>The stream is connected.</tp:docstring>
- </tp:enumvalue>
- </tp:enum>
-
- <tp:simple-type name="Handle" type="u" array-name="Handle_List">
- <tp:docstring>An unsigned 32-bit integer representing a
- handle</tp:docstring>
- </tp:simple-type>
</tp:generic-types>
+<xi:include href="Logger.xml"/>
</tp:spec>
diff --git a/extensions/extensions.c b/extensions/extensions.c
new file mode 100644
index 0000000..c81d126
--- /dev/null
+++ b/extensions/extensions.c
@@ -0,0 +1,5 @@
+#include "extensions.h"
+
+/* auto-generated stubs */
+#include "_gen/gtypes-body.h"
+#include "_gen/interfaces-body.h"
diff --git a/extensions/extensions.h b/extensions/extensions.h
new file mode 100644
index 0000000..bf8f36d
--- /dev/null
+++ b/extensions/extensions.h
@@ -0,0 +1,15 @@
+#ifndef _TPL_EXTENSIONS_H
+#define _TPL_EXTENSIONS_H
+
+#include "extensions/_gen/enums.h"
+#include "extensions/_gen/svc.h"
+
+G_BEGIN_DECLS
+
+#include "extensions/_gen/gtypes.h"
+#include "extensions/_gen/interfaces.h"
+
+G_END_DECLS
+
+#endif /* _GABBLE_EXTENSIONS_H */
+
diff --git a/tools/doc-generator.py b/tools/doc-generator.py
new file mode 100755
index 0000000..5fc19ce
--- /dev/null
+++ b/tools/doc-generator.py
@@ -0,0 +1,104 @@
+#!/usr/bin/env python
+#
+# doc-generator.py
+#
+# Generates HTML documentation from the parsed spec using Cheetah templates.
+#
+# Copyright (C) 2009 Collabora Ltd.
+#
+# 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.1 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.
+#
+# Authors: Davyd Madeley <davyd.madeley@collabora.co.uk>
+#
+
+import sys
+import os
+import os.path
+import shutil
+
+try:
+ from Cheetah.Template import Template
+except ImportError, e:
+ print >> sys.stderr, e
+ print >> sys.stderr, "Install `python-cheetah'?"
+ sys.exit(-1)
+
+import specparser
+
+program, spec_file, output_path, project, namespace = sys.argv
+
+template_path = os.path.join(os.path.dirname(program), '../doc/templates')
+
+# make the output path
+try:
+ os.mkdir(output_path)
+except OSError:
+ pass
+# copy in the CSS
+shutil.copy(os.path.join(template_path, 'style.css'), output_path)
+
+def load_template(filename):
+ try:
+ file = open(os.path.join(template_path, filename))
+ template_def = file.read()
+ file.close()
+ except IOError, e:
+ print >> sys.stderr, "Could not load template file `%s'" % filename
+ print >> sys.stderr, e
+ sys.exit(-1)
+
+ return template_def
+
+spec = specparser.parse(spec_file, namespace)
+
+# write out HTML files for each of the interfaces
+
+# Not using render_template here to avoid recompiling it n times.
+namespace = {}
+template_def = load_template('interface.html')
+t = Template(template_def, namespaces = [namespace])
+for interface in spec.interfaces:
+ namespace['interface'] = interface
+
+ # open the output file
+ out = open(os.path.join(output_path, '%s.html' % interface.name), 'w')
+ print >> out, unicode(t).encode('utf-8')
+ out.close()
+
+def render_template(name, namespaces, target=None):
+ if target is None:
+ target = name
+
+ namespace = { 'spec': spec }
+ template_def = load_template(name)
+ t = Template(template_def, namespaces=namespaces)
+ out = open(os.path.join(output_path, target), 'w')
+ print >> out, unicode(t).encode('utf-8')
+ out.close()
+
+namespaces = { 'spec': spec }
+
+render_template('generic-types.html', namespaces)
+render_template('errors.html', namespaces)
+render_template('interfaces.html', namespaces)
+render_template('fullindex.html', namespaces)
+
+dh_namespaces = { 'spec': spec, 'name': project }
+render_template('devhelp.devhelp2', dh_namespaces,
+ target=('%s.devhelp2' % project))
+
+# write out the TOC last, because this is the file used as the target in the
+# Makefile.
+render_template('index.html', namespaces)
diff --git a/tools/identity.xsl b/tools/identity.xsl
new file mode 100644
index 0000000..6630f84
--- /dev/null
+++ b/tools/identity.xsl
@@ -0,0 +1,7 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+ <xsl:template match="@*|node()">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()"/>
+ </xsl:copy>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tools/specparser.py b/tools/specparser.py
new file mode 100644
index 0000000..16b770e
--- /dev/null
+++ b/tools/specparser.py
@@ -0,0 +1,885 @@
+#
+# specparser.py
+#
+# Reads in a spec document and generates pretty data structures from it.
+#
+# Copyright (C) 2009 Collabora Ltd.
+#
+# 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.1 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.
+#
+# Authors: Davyd Madeley <davyd.madeley@collabora.co.uk>
+#
+
+import sys
+import xml.dom.minidom
+
+import xincludator
+
+XMLNS_TP = 'http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0'
+
+class UnknownAccess(Exception): pass
+class UnknownDirection(Exception): pass
+class UnknownType(Exception): pass
+class UnnamedItem(Exception): pass
+class UntypedItem(Exception): pass
+class UnsupportedArray(Exception): pass
+class BadNameForBindings(Exception): pass
+
+def getText(dom):
+ try:
+ if dom.childNodes[0].nodeType == dom.TEXT_NODE:
+ return dom.childNodes[0].data
+ else:
+ return ''
+ except IndexError:
+ return ''
+
+def getChildrenByName(dom, namespace, name):
+ return filter(lambda n: n.nodeType == n.ELEMENT_NODE and \
+ n.namespaceURI == namespace and \
+ n.localName == name,
+ dom.childNodes)
+
+def build_name(namespace, name):
+ """Returns a name by appending `name' to the namespace of this object.
+ """
+ return '.'.join(
+ filter(lambda n: n is not None and n != '',
+ [namespace, name.replace(' ', '')])
+ )
+
+class Base(object):
+ """The base class for any type of XML node in the spec that implements the
+ 'name' attribute.
+
+ Don't instantiate this class directly.
+ """
+ devhelp_name = ""
+
+ def __init__(self, parent, namespace, dom):
+ self.short_name = name = dom.getAttribute('name')
+ self.namespace = namespace
+ self.name = build_name(namespace, name)
+ self.parent = parent
+
+ try:
+ self.docstring = getChildrenByName(dom, XMLNS_TP, 'docstring')[0]
+ except IndexError:
+ self.docstring = None
+
+ try:
+ self.added = getChildrenByName(dom, XMLNS_TP, 'added')[0]
+ except IndexError:
+ self.added = None
+
+ try:
+ self.deprecated = getChildrenByName(dom, XMLNS_TP, 'deprecated')[0]
+ except IndexError:
+ self.deprecated = None
+
+ self.changed = getChildrenByName(dom, XMLNS_TP, 'changed')
+
+ self.validate()
+
+ def validate(self):
+ if self.short_name == '':
+ raise UnnamedItem("Node %s of %s has no name" % (
+ self.__class__.__name__, self.parent))
+
+ def get_type_name(self):
+ return self.__class__.__name__
+
+ def get_spec(self):
+ return self.parent.get_spec()
+
+ def get_root_namespace(self):
+ return self.get_interface().name
+
+ def get_interface(self):
+ return self.parent.get_interface()
+
+ def get_url(self):
+ return "%s#%s" % (self.get_interface().get_url(), self.name)
+
+ def _get_generic_with_ver(self, nnode, htmlclass, txt):
+ if nnode is None:
+ return ''
+ else:
+ # make a copy of this node, turn it into a HTML <div> tag
+ node = nnode.cloneNode(True)
+ node.tagName = 'div'
+ node.baseURI = None
+ node.setAttribute('class', htmlclass)
+
+ try:
+ node.removeAttribute('version')
+
+ span = xml.dom.minidom.parseString(
+ ('<span class="version">%s\n</span>' % txt) %
+ nnode.getAttribute('version')).firstChild
+ node.insertBefore(span, node.firstChild)
+ except xml.dom.NotFoundErr:
+ print >> sys.stderr, \
+ 'WARNING: %s was %s, but gives no version' % (self, htmlclass)
+
+ self._convert_to_html(node)
+
+ return node.toxml().encode('ascii', 'xmlcharrefreplace')
+
+ def get_added(self):
+ return self._get_generic_with_ver(self.added, 'added',
+ "Added in %s.")
+
+ def get_deprecated(self):
+ return self._get_generic_with_ver(self.deprecated, 'deprecated',
+ "Deprecated since %s.")
+
+ def get_changed(self):
+ return '\n'.join(map(lambda n:
+ self._get_generic_with_ver(n, 'changed', "Changed in %s."),
+ self.changed))
+
+ def get_docstring(self):
+ """Get the docstring for this node, but do node substitution to
+ rewrite types, interfaces, etc. as links.
+ """
+ if self.docstring is None:
+ return ''
+ else:
+ # make a copy of this node, turn it into a HTML <div> tag
+ node = self.docstring.cloneNode(True)
+ node.tagName = 'div'
+ node.baseURI = None
+ node.setAttribute('class', 'docstring')
+
+ self._convert_to_html(node)
+
+ return node.toxml().encode('ascii', 'xmlcharrefreplace')
+
+ def _convert_to_html(self, node):
+ spec = self.get_spec()
+ namespace = self.get_root_namespace()
+
+ # rewrite <tp:rationale>
+ for n in node.getElementsByTagNameNS(XMLNS_TP, 'rationale'):
+ n.tagName = 'div'
+ n.namespaceURI = None
+ n.setAttribute('class', 'rationale')
+
+ # rewrite <tp:type>
+ for n in node.getElementsByTagNameNS(XMLNS_TP, 'type'):
+ t = spec.lookup_type(getText(n))
+ n.tagName = 'a'
+ n.namespaceURI = None
+ n.setAttribute('href', t.get_url())
+
+ # rewrite <tp:member-ref>
+ for n in node.getElementsByTagNameNS(XMLNS_TP, 'member-ref'):
+ key = getText(n)
+ try:
+ o = spec.lookup(key, namespace=namespace)
+ except KeyError:
+ print >> sys.stderr, \
+ "WARNING: Key '%s' not known in namespace '%s'" % (
+ key, namespace)
+ continue
+
+ n.tagName = 'a'
+ n.namespaceURI = None
+ n.setAttribute('href', o.get_url())
+ n.setAttribute('title', o.get_title())
+
+ # rewrite <tp:dbus-ref>
+ for n in node.getElementsByTagNameNS(XMLNS_TP, 'dbus-ref'):
+ namespace = n.getAttribute('namespace')
+ key = getText(n)
+ try:
+ o = spec.lookup(key, namespace=namespace)
+ except KeyError:
+ print >> sys.stderr, \
+ "WARNING: Key '%s' not known in namespace '%s'" % (
+ key, namespace)
+ continue
+
+ n.tagName = 'a'
+ n.namespaceURI = None
+ n.setAttribute('href', o.get_url())
+ n.setAttribute('title', o.get_title())
+
+ def get_title(self):
+ return '%s %s' % (self.get_type_name(), self.name)
+
+ def __repr__(self):
+ return '%s(%s)' % (self.__class__.__name__, self.name)
+
+class DBusConstruct(Base):
+ """Base class for signals, methods and properties."""
+
+ def __init__(self, parent, namespace, dom):
+ super(DBusConstruct, self).__init__(parent, namespace, dom)
+
+ self.name_for_bindings = dom.getAttributeNS(XMLNS_TP,
+ 'name-for-bindings')
+
+ if not self.name_for_bindings:
+ raise BadNameForBindings('%s has no name-for-bindings'
+ % self)
+
+ if self.name_for_bindings.replace('_', '') != self.short_name:
+ raise BadNameForBindings('%s name-for-bindings = %s does not '
+ 'match short_name = %s' % (self, self.name_for_bindings,
+ self.short_name))
+
+class PossibleError(Base):
+ def __init__(self, parent, namespace, dom):
+ super(PossibleError, self).__init__(parent, namespace, dom)
+
+ def get_error(self):
+ spec = self.get_spec()
+ try:
+ return spec.errors[self.name]
+ except KeyError:
+ return External(self.name)
+
+ def get_url(self):
+ return self.get_error().get_url()
+
+ def get_title(self):
+ return self.get_error().get_title()
+
+ def get_docstring(self):
+ d = super(PossibleError, self).get_docstring()
+ if d == '':
+ return self.get_error().get_docstring()
+ else:
+ return d
+
+class Method(DBusConstruct):
+ devhelp_name = "function"
+
+ def __init__(self, parent, namespace, dom):
+ super(Method, self).__init__(parent, namespace, dom)
+
+ args = build_list(self, Arg, self.name,
+ 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)
+
+ for arg in args:
+ if arg.direction == Arg.DIRECTION_IN or \
+ arg.direction == Arg.DIRECTION_OUT:
+ continue
+
+ print >> sys.stderr, "WARNING: '%s' of method '%s' does not specify a suitable direction" % (arg, self)
+
+ self.possible_errors = build_list(self, PossibleError, None,
+ dom.getElementsByTagNameNS(XMLNS_TP, 'error'))
+
+ def get_in_args(self):
+ return ', '.join(map(lambda a: a.spec_name(), self.in_args))
+
+ def get_out_args(self):
+ if len(self.out_args) > 0:
+ return ', '.join(map(lambda a: a.spec_name(), self.out_args))
+ else:
+ return 'nothing'
+
+class Typed(Base):
+ """The base class for all typed nodes (i.e. Arg and Property).
+
+ Don't instantiate this class directly.
+ """
+
+ def __init__(self, parent, namespace, dom):
+ super(Typed, self).__init__(parent, namespace, dom)
+
+ self.type = dom.getAttributeNS(XMLNS_TP, 'type')
+ self.dbus_type = dom.getAttribute('type')
+
+ # check we have a dbus type
+ if self.dbus_type == '':
+ raise UntypedItem("Node referred to by '%s' has no type" % dom.toxml())
+ def get_type(self):
+ return self.get_spec().lookup_type(self.type)
+
+ def get_type_url(self):
+ t = self.get_type()
+ if t is None: return ''
+ else: return t.get_url()
+
+ def get_type_title(self):
+ t = self.get_type()
+ if t is None: return ''
+ else: return t.get_title()
+
+ def spec_name(self):
+ return '%s: %s' % (self.dbus_type, self.short_name)
+
+ def __repr__(self):
+ return '%s(%s:%s)' % (self.__class__.__name__, self.name, self.dbus_type)
+
+class Property(DBusConstruct, Typed):
+ ACCESS_READ = 1
+ ACCESS_WRITE = 2
+
+ ACCESS_READWRITE = ACCESS_READ | ACCESS_WRITE
+
+ def __init__(self, parent, namespace, dom):
+ super(Property, self).__init__(parent, namespace, dom)
+
+ access = dom.getAttribute('access')
+ if access == 'read':
+ self.access = self.ACCESS_READ
+ elif access == 'write':
+ self.access = self.ACCESS_WRITE
+ elif access == 'readwrite':
+ self.access = self.ACCESS_READWRITE
+ else:
+ raise UnknownAccess("Unknown access '%s' on %s" % (access, self))
+
+ def get_access(self):
+ if self.access & self.ACCESS_READ and self.access & self.ACCESS_WRITE:
+ return 'Read/Write'
+ elif self.access & self.ACCESS_READ:
+ return 'Read only'
+ elif self.access & self.ACCESS_WRITE:
+ return 'Write only'
+
+class AwkwardTelepathyProperty(Typed):
+ def get_type_name(self):
+ return 'Telepathy Property'
+
+class Arg(Typed):
+ DIRECTION_IN, DIRECTION_OUT, DIRECTION_UNSPECIFIED = range(3)
+
+ def __init__(self, parent, namespace, dom):
+ super(Arg, self).__init__(parent, namespace, dom)
+
+ direction = dom.getAttribute('direction')
+ if direction == 'in':
+ self.direction = self.DIRECTION_IN
+ elif direction == 'out':
+ self.direction = self.DIRECTION_OUT
+ elif direction == '':
+ self.direction = self.DIRECTION_UNSPECIFIED
+ else:
+ raise UnknownDirection("Unknown direction '%s' on %s" % (
+ direction, self.parent))
+
+class Signal(DBusConstruct):
+ def __init__(self, parent, namespace, dom):
+ super(Signal, self).__init__(parent, namespace, dom)
+
+ self.args = build_list(self, Arg, self.name,
+ dom.getElementsByTagName('arg'))
+
+ for arg in self.args:
+ if arg.direction == Arg.DIRECTION_UNSPECIFIED:
+ continue
+
+ print >> sys.stderr, "WARNING: '%s' of signal '%s' does not specify a suitable direction" % (arg, self)
+
+ def get_args(self):
+ return ', '.join(map(lambda a: a.spec_name(), self.args))
+
+class External(object):
+ """External objects are objects that are referred to in another spec.
+
+ We have to attempt to look them up if at all possible.
+ """
+
+ def __init__(self, name):
+ self.name = self.short_name = name
+
+ def get_url(self):
+ return None
+
+ def get_title(self):
+ return 'External %s' % self.name
+
+ def get_docstring(self):
+ return None
+
+ def __repr__(self):
+ return '%s(%s)' % (self.__class__.__name__, self.name)
+
+class Interface(Base):
+ def __init__(self, parent, namespace, dom, spec_namespace):
+ super(Interface, self).__init__(parent, namespace, dom)
+
+ # If you're writing a spec with more than one top-level namespace, you
+ # probably want to replace spec_namespace with a list.
+ if self.name.startswith(spec_namespace + "."):
+ self.short_name = self.name[len(spec_namespace) + 1:]
+ else:
+ self.short_name = self.name
+
+ # build lists of methods, etc., in this interface
+ self.methods = build_list(self, Method, self.name,
+ dom.getElementsByTagName('method'))
+ self.properties = build_list(self, Property, self.name,
+ dom.getElementsByTagName('property'))
+ self.signals = build_list(self, Signal, self.name,
+ dom.getElementsByTagName('signal'))
+ self.tpproperties = build_list(self, AwkwardTelepathyProperty,
+ self.name, dom.getElementsByTagNameNS(XMLNS_TP, 'property'))
+ self.handler_capability_tokens = build_list(self,
+ HandlerCapabilityToken, self.name,
+ dom.getElementsByTagNameNS(XMLNS_TP,
+ 'handler-capability-token'))
+ self.contact_attributes = build_list(self, ContactAttribute, self.name,
+ dom.getElementsByTagNameNS(XMLNS_TP, 'contact-attribute'))
+
+ # build a list of types in this interface
+ self.types = parse_types(self, dom, self.name)
+
+ # find out if this interface causes havoc
+ self.causes_havoc = dom.getAttributeNS(XMLNS_TP, 'causes-havoc')
+ if self.causes_havoc == '': self.causes_havoc = None
+
+ # find out what we're required to also implement
+ self.requires = map(lambda n: n.getAttribute('interface'),
+ getChildrenByName(dom, XMLNS_TP, 'requires'))
+
+ def get_interface(self):
+ return self
+
+ def get_requires(self):
+ spec = self.get_spec()
+
+ def lookup(r):
+ try:
+ return spec.lookup(r)
+ except KeyError:
+ return External(r)
+
+ return map(lookup, self.requires)
+
+ def get_url(self):
+ return '%s.html' % self.name
+
+class Error(Base):
+ def get_url(self):
+ return 'errors.html#%s' % self.name
+
+ def get_root_namespace(self):
+ return self.namespace
+
+class DBusList(object):
+ """Stores a list of a given DBusType. Provides some basic validation to
+ determine whether or not the type is sane.
+ """
+ def __init__(self, child):
+ self.child = child
+
+ if isinstance(child, DBusType):
+ self.ultimate = child
+ self.depth = 1
+
+ if self.child.array_name == '':
+ raise UnsupportedArray("Type '%s' does not support being "
+ "used in an array" % self.child.name)
+ else:
+ self.name = build_name(self.child.namespace,
+ self.child.array_name)
+ self.short_name = self.child.array_name
+
+ elif isinstance(child, DBusList):
+ self.ultimate = child.ultimate
+ self.depth = child.depth + 1
+ self.name = self.child.name + '_List'
+ self.short_name = self.child.short_name + '_List'
+
+ # check that our child can operate at this depth
+ maxdepth = int(self.ultimate.array_depth)
+ if self.depth > maxdepth:
+ raise TypeError("Type '%s' has exceeded its maximum depth (%i)" % (self, maxdepth))
+
+ else:
+ raise TypeError("DBusList can contain only a DBusType or DBusList not '%s'" % child)
+
+ self.dbus_type = 'a' + self.child.dbus_type
+
+ def get_url(self):
+ return self.ultimate.get_url()
+
+ def get_title(self):
+ return "Array of %s" % self.child.get_title()
+
+ def __repr__(self):
+ return 'Array(%s)' % self.child
+
+class DBusType(Base):
+ """The base class for all D-Bus types referred to in the spec.
+
+ Don't instantiate this class directly.
+ """
+
+ devhelp_name = "typedef"
+
+ def __init__(self, parent, namespace, dom):
+ super(DBusType, self).__init__(parent, namespace, dom)
+
+ self.dbus_type = dom.getAttribute('type')
+ self.array_name = dom.getAttribute('array-name')
+ self.array_depth = dom.getAttribute('array-depth')
+
+ def get_root_namespace(self):
+ return self.namespace
+
+ def get_breakdown(self):
+ return ''
+
+ def get_url(self):
+ if isinstance(self.parent, Interface):
+ html = self.parent.get_url()
+ else:
+ html = 'generic-types.html'
+
+ return '%s#%s' % (html, self.name)
+
+class SimpleType(DBusType):
+ def get_type_name(self):
+ return 'Simple Type'
+
+class ExternalType(DBusType):
+ def __init__(self, parent, namespace, dom):
+ super(ExternalType, self).__init__(parent, namespace, dom)
+
+ # FIXME: until we are able to cross reference external types to learn
+ # about their array names, we're just going to assume they work like
+ # this
+ self.array_name = self.short_name + '_List'
+
+ def get_type_name(self):
+ return 'External Type'
+
+class StructLike(DBusType):
+ """Base class for all D-Bus types that look kind of like Structs
+
+ Don't instantiate this class directly.
+ """
+
+ class StructMember(Typed):
+ def get_root_namespace(self):
+ return self.parent.get_root_namespace()
+
+ def __init__(self, parent, namespace, dom):
+ super(StructLike, self).__init__(parent, namespace, dom)
+
+ self.members = build_list(self, StructLike.StructMember, None,
+ dom.getElementsByTagNameNS(XMLNS_TP, 'member'))
+
+ def get_breakdown(self):
+ str = ''
+ str += '<ul>\n'
+ for member in self.members:
+ # attempt to lookup the member up in the type system
+ t = member.get_type()
+
+ str += '<li>%s &mdash; %s' % (member.name, member.dbus_type)
+ if t: str += ' (<a href="%s" title="%s">%s</a>)' % (
+ t.get_url(), t.get_title(), t.short_name)
+ str += '</li>\n'
+ str += member.get_docstring()
+ str += '</ul>\n'
+
+ return str
+
+class Mapping(StructLike):
+ def __init__(self, parent, namespace, dom):
+ super(Mapping, self).__init__(parent, namespace, dom)
+
+ # rewrite the D-Bus type
+ self.dbus_type = 'a{%s}' % ''.join(map(lambda m: m.dbus_type, self.members))
+
+class Struct(StructLike):
+
+ devhelp_name = "struct"
+
+ def __init__(self, parent, namespace, dom):
+ super(Struct, self).__init__(parent, namespace, dom)
+
+ # rewrite the D-Bus type
+ self.dbus_type = '(%s)' % ''.join(map(lambda m: m.dbus_type, self.members))
+
+class EnumLike(DBusType):
+ """Base class for all D-Bus types that look kind of like Enums
+
+ Don't instantiate this class directly.
+ """
+ class EnumValue(Base):
+ def __init__(self, parent, namespace, dom):
+ super(EnumLike.EnumValue, self).__init__(parent, namespace, dom)
+
+ # rewrite self.name
+ self.short_name = dom.getAttribute('suffix')
+ self.name = build_name(namespace, self.short_name)
+
+ self.value = dom.getAttribute('value')
+
+ super(EnumLike.EnumValue, self).validate()
+
+ def validate(self):
+ pass
+
+ def get_root_namespace(self):
+ return self.parent.get_root_namespace()
+
+ def get_breakdown(self):
+ str = ''
+ str += '<ul>\n'
+ for value in self.values:
+ # attempt to lookup the member.name as a type in the type system
+ str += '<li>%s (%s)</li>\n' % (value.short_name, value.value)
+ str += value.get_added()
+ str += value.get_changed()
+ str += value.get_deprecated()
+ str += value.get_docstring()
+ str += '</ul>\n'
+
+ return str
+
+class Enum(EnumLike):
+
+ devhelp_name = "enum"
+
+ def __init__(self, parent, namespace, dom):
+ super(Enum, self).__init__(parent, namespace, dom)
+
+ self.values = build_list(self, EnumLike.EnumValue, self.name,
+ dom.getElementsByTagNameNS(XMLNS_TP, 'enumvalue'))
+
+class Flags(EnumLike):
+ def __init__(self, parent, namespace, dom):
+ super(Flags, self).__init__(parent, namespace, dom)
+
+ self.values = build_list(self, EnumLike.EnumValue, self.name,
+ dom.getElementsByTagNameNS(XMLNS_TP, 'flag'))
+ self.flags = self.values # in case you're looking for it
+
+class TokenBase(Base):
+
+ devhelp_name = "macro" # it's a constant, which is near enough...
+ separator = '/'
+
+ def __init__(self, parent, namespace, dom):
+ super(TokenBase, self).__init__(parent, namespace, dom)
+ self.name = namespace + '/' + self.short_name
+
+class ContactAttribute(TokenBase, Typed):
+
+ def get_type_name(self):
+ return 'Contact Attribute'
+
+class HandlerCapabilityToken(TokenBase):
+
+ def get_type_name(self):
+ return 'Handler Capability Token'
+
+ def __init__(self, parent, namespace, dom):
+ super(HandlerCapabilityToken, self).__init__(parent, namespace, dom)
+
+ is_family = dom.getAttribute('is-family')
+ assert is_family in ('yes', 'no', '')
+ self.is_family = (is_family == 'yes')
+
+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, spec_namespace):
+
+ 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,
+ spec_namespace))
+ elif node.tagName == 'interface':
+ self.items.append(Interface(self, None, node,
+ spec_namespace))
+
+ recurse(dom.childNodes)
+
+class Section(Base, SectionBase):
+ def __init__(self, parent, namespace, dom, spec_namespace):
+ Base.__init__(self, parent, namespace, dom)
+ SectionBase.__init__(self, dom, spec_namespace)
+
+ def get_root_namespace(self):
+ return None
+
+class Spec(SectionBase):
+ def __init__(self, dom, spec_namespace):
+ # build a dictionary of errors in this spec
+ try:
+ errorsnode = dom.getElementsByTagNameNS(XMLNS_TP, 'errors')[0]
+ self.errors = build_dict(self, Error,
+ errorsnode.getAttribute('namespace'),
+ errorsnode.getElementsByTagNameNS(XMLNS_TP, 'error'))
+ except IndexError:
+ self.errors = {}
+
+ # build a list of generic types
+ self.generic_types = reduce (lambda a, b: a + b,
+ map(lambda l: parse_types(self, l),
+ dom.getElementsByTagNameNS(XMLNS_TP, 'generic-types')),
+ [])
+
+ # create a top-level section for this Spec
+ SectionBase.__init__(self, dom.documentElement, spec_namespace)
+
+ # build a list of interfaces in this spec
+ 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
+ self.everything = {}
+ self.types = {}
+
+ for type in self.generic_types: self.types[type.short_name] = type
+
+ for interface in self.interfaces:
+ self.everything[interface.name] = interface
+
+ for method in interface.methods:
+ self.everything[method.name] = method
+ for signal in interface.signals:
+ self.everything[signal.name] = signal
+ for property in interface.properties:
+ self.everything[property.name] = property
+ for property in interface.tpproperties:
+ self.everything[property.name] = property
+ for token in interface.contact_attributes:
+ self.everything[token.name] = token
+ for token in interface.handler_capability_tokens:
+ self.everything[token.name] = token
+
+ for type in interface.types:
+ self.types[type.short_name] = type
+
+ # get some extra bits for the HTML
+ node = dom.getElementsByTagNameNS(XMLNS_TP, 'spec')[0]
+ self.title = getText(getChildrenByName(node, XMLNS_TP, 'title')[0])
+
+ try:
+ self.version = getText(getChildrenByName(node, XMLNS_TP, 'version')[0])
+ except IndexError:
+ self.version = None
+
+ self.copyrights = map(getText,
+ getChildrenByName(node, XMLNS_TP, 'copyright'))
+
+ try:
+ license = getChildrenByName(node, XMLNS_TP, 'license')[0]
+ license.tagName = 'div'
+ license.namespaceURI = None
+ license.setAttribute('class', 'license')
+ self.license = license.toxml()
+ except IndexError:
+ self.license = ''
+
+ # FIXME: we need to check all args for type correctness
+
+ def get_spec(self):
+ return self
+
+ def lookup(self, name, namespace=None):
+ key = build_name(namespace, name)
+ return self.everything[key]
+
+ def lookup_type(self, type_):
+ if type_.endswith('[]'):
+ return DBusList(self.lookup_type(type_[:-2]))
+
+ if type_ == '': return None
+ elif type_ in self.types:
+ return self.types[type_]
+
+ raise UnknownType("Type '%s' is unknown" % type_)
+
+ def __repr__(self):
+ return '%s(%s)' % (self.__class__.__name__, self.title)
+
+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.
+
+ e.g. 'org.freedesktop.Telepathy.Channel' : Interface(Channel)
+
+ Works for any Python object inheriting from 'Base' whose XML node
+ implements the 'name' attribute.
+ """
+
+ def build_tuple(node):
+ o = type_(parent, namespace, node)
+ return(o.name, o)
+
+ return dict(build_tuple(n) for n in nodes)
+
+def build_list(parent, type_, namespace, nodes):
+ return map(lambda node: type_(parent, namespace, node), nodes)
+
+def parse_types(parent, dom, namespace = 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'),
+ (ExternalType, 'external-type'),
+ ]
+
+ types = []
+
+ for (type_, tagname) in t:
+ types += build_list(parent, type_, namespace,
+ dom.getElementsByTagNameNS(XMLNS_TP, tagname))
+
+ return types
+
+def parse(filename, spec_namespace):
+ dom = xml.dom.minidom.parse(filename)
+ xincludator.xincludate(dom, filename)
+
+ spec = Spec(dom, spec_namespace)
+
+ return spec
+
+if __name__ == '__main__':
+ parse(sys.argv[1])