summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/specparser.py79
1 files changed, 56 insertions, 23 deletions
diff --git a/tools/specparser.py b/tools/specparser.py
index 9ea9d41..29ee0b5 100644
--- a/tools/specparser.py
+++ b/tools/specparser.py
@@ -150,8 +150,8 @@ class Base(object):
if (child.nodeType == dom.TEXT_NODE and
child.data.strip() != ''):
raise BrokenHTML('Text found in node %s of %s, did you mean '
- 'to use <tp:docstring/>?' %
- (self.__class__.__name__, self.parent))
+ 'to use <tp:docstring/>? Offending text:\n\n%s' %
+ (self.__class__.__name__, self.parent, child.data.strip()))
elif child.nodeType == dom.ELEMENT_NODE:
if child.tagName in ('p', 'em', 'strong', 'ul', 'li', 'dl',
'a', 'tt', 'code'):
@@ -614,17 +614,41 @@ class Typed(Base):
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
-
+class HasEmitsChangedAnnotation(object):
EMITS_CHANGED_UNKNOWN = 0
EMITS_CHANGED_NONE = 1
EMITS_CHANGED_UPDATES = 2
EMITS_CHANGED_INVALIDATES = 3
+ # According to the D-Bus specification, EmitsChangedSignal defaults
+ # to true, but - realistically - this cannot be assumed for old specs.
+ # As a result, we treat the absence of the annotation as "unknown".
+ __MAPPING = { None: EMITS_CHANGED_UNKNOWN,
+ 'false': EMITS_CHANGED_NONE,
+ 'invalidates': EMITS_CHANGED_INVALIDATES,
+ 'true': EMITS_CHANGED_UPDATES,
+ }
+
+ __ANNOTATION = 'org.freedesktop.DBus.Property.EmitsChangedSignal'
+
+ def _get_emits_changed(self, dom):
+ emits_changed = getAnnotationByName(dom, self.__ANNOTATION)
+
+ try:
+ return self.__MAPPING[emits_changed]
+ except KeyError:
+ print >> sys.stderr, """
+WARNING: <annotation name='%s'/> has unknown value '%s'
+ (in %s)
+ """.strip() % (self.__ANNOTATION, emits_changed, self)
+ return self.EMITS_CHANGED_UNKNOWN;
+
+class Property(DBusConstruct, Typed, HasEmitsChangedAnnotation):
+ 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)
@@ -651,20 +675,12 @@ class Property(DBusConstruct, Typed):
self.requestable = requestable != ''
self.sometimes_requestable = requestable == 'sometimes'
- # According to the D-Bus specification, EmitsChangedSignal defaults
- # to true, but - realistically - this cannot be assumed for old specs.
- # As a result, we treat the absence of the annotation as "unknown".
- emits_changed = getAnnotationByName(dom, 'org.freedesktop.DBus.Property.EmitsChangedSignal')
- if emits_changed is None:
- emits_changed = getAnnotationByName(dom.parentNode, 'org.freedesktop.DBus.Property.EmitsChangedSignal')
- if emits_changed == 'true':
- self.emits_changed = self.EMITS_CHANGED_UPDATES;
- elif emits_changed == 'invalidates':
- self.emits_changed = self.EMITS_CHANGED_INVALIDATES;
- elif emits_changed == 'false':
- self.emits_changed = self.EMITS_CHANGED_NONE;
- else:
- self.emits_changed = self.EMITS_CHANGED_UNKNOWN;
+ self.emits_changed = self._get_emits_changed(dom)
+
+ if self.emits_changed == self.EMITS_CHANGED_UNKNOWN:
+ # If the <property> doesn't have the annotation, grab it from the
+ # interface.
+ self.emits_changed = parent.emits_changed
def get_access(self):
if self.access & self.ACCESS_READ and self.access & self.ACCESS_WRITE:
@@ -696,6 +712,14 @@ class Property(DBusConstruct, Typed):
return ''
class AwkwardTelepathyProperty(Typed):
+ def __init__(self, parent, namespace, dom):
+ Typed.__init__(self, parent, namespace, dom)
+
+ print >> sys.stderr, """
+WARNING: Old-style Telepathy properties are deprecated!
+ (<tp:property> in %s)
+ """.strip() % (parent)
+
def get_type_name(self):
return 'Telepathy Property'
@@ -753,7 +777,7 @@ class External(object):
def __repr__(self):
return '%s(%s)' % (self.__class__.__name__, self.name)
-class Interface(Base):
+class Interface(Base, HasEmitsChangedAnnotation):
def __init__(self, parent, namespace, dom, spec_namespace):
super(Interface, self).__init__(parent, namespace, dom)
@@ -787,6 +811,8 @@ class Interface(Base):
.replace('.Type.', '.T.')[1:]
)
+ self.emits_changed = self._get_emits_changed(dom)
+
# build lists of methods, etc., in this interface
self.methods = build_list(self, Method, self.name,
dom.getElementsByTagName('method'))
@@ -1039,6 +1065,13 @@ class Mapping(StructLike):
# rewrite the D-Bus type
self.dbus_type = 'a{%s}' % ''.join(map(lambda m: m.dbus_type, self.members))
+ # not sure why tp:mapping sometimes has a type attribute, but
+ # make sure it's right.
+ t = dom.getAttribute('type')
+ if t and self.dbus_type != t:
+ raise TypeMismatch('%r reports type is %s but actual type is %s'
+ % (self, t, self.dbus_type))
+
class Struct(StructLike):
devhelp_name = "struct"