diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/specparser.py | 79 |
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" |