/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« back to all changes in this revision

Viewing changes to mandos

  • Committer: Teddy Hogeborn
  • Date: 2012-03-08 21:57:33 UTC
  • mto: This revision was merged to the branch mainline in revision 562.
  • Revision ID: teddy@recompile.se-20120308215733-8pz2o2lbuc19e9uc
Add D-Bus annotations support to methods, signals and properties.

* mandos (dbus_annotations): New; decorator to add annotations.
  (DBusObjectWithProperties._get_all_dbus_things): Bug fix: return
                                                   normal name if no
                                                   "_dbus_name"
                                                   attribute.
  (DBusObjectWithProperties.Introspect): Add annotation tags.
  (AlternateDBusNamesMetaclass.__new__): Copy annotations.
  

Show diffs side-by-side

added added

removed removed

Lines of Context:
791
791
    return decorator
792
792
 
793
793
 
 
794
def dbus_annotations(annotations):
 
795
    """Decorator to annotate D-Bus methods, signals or properties
 
796
    Usage:
 
797
    
 
798
    @dbus_service_property("org.example.Interface", signature="b",
 
799
                           access="r")
 
800
    @dbus_annotations({{"org.freedesktop.DBus.Deprecated": "true",
 
801
                        "org.freedesktop.DBus.Property."
 
802
                        "EmitsChangedSignal": "false"})
 
803
    def Property_dbus_property(self):
 
804
        return dbus.Boolean(False)
 
805
    """
 
806
    def decorator(func):
 
807
        func._dbus_annotations = annotations
 
808
        return func
 
809
    return decorator
 
810
 
 
811
 
794
812
class DBusPropertyException(dbus.exceptions.DBusException):
795
813
    """A base class for D-Bus property-related exceptions
796
814
    """
831
849
    def _get_all_dbus_things(self, thing):
832
850
        """Returns a generator of (name, attribute) pairs
833
851
        """
834
 
        return ((athing.__get__(self)._dbus_name,
 
852
        return ((getattr(athing.__get__(self), "_dbus_name",
 
853
                         name),
835
854
                 athing.__get__(self))
836
855
                for cls in self.__class__.__mro__
837
856
                for name, athing in
936
955
                            if prop._dbus_interface
937
956
                            == if_tag.getAttribute("name")):
938
957
                    if_tag.appendChild(tag)
 
958
                # Add annotation tags
 
959
                for typ in ("method", "signal", "property"):
 
960
                    for tag in if_tag.getElementsByTagName(typ):
 
961
                        annots = dict()
 
962
                        for name, prop in (self.
 
963
                                           _get_all_dbus_things(typ)):
 
964
                            if (name == tag.getAttribute("name")
 
965
                                and prop._dbus_interface
 
966
                                == if_tag.getAttribute("name")):
 
967
                                annots.update(getattr
 
968
                                              (prop,
 
969
                                               "_dbus_annotations",
 
970
                                               {}))
 
971
                        for name, value in annots.iteritems():
 
972
                            ann_tag = document.createElement(
 
973
                                "annotation")
 
974
                            ann_tag.setAttribute("name", name)
 
975
                            ann_tag.setAttribute("value", value)
 
976
                            tag.appendChild(ann_tag)
939
977
                # Add interface annotation tags
940
978
                for annotation, value in dict(
941
979
                    itertools.chain(
944
982
                          self._get_all_dbus_things("interface")
945
983
                          if name == if_tag.getAttribute("name")
946
984
                          ))).iteritems():
947
 
                    attr_tag = document.createElement("annotation")
948
 
                    attr_tag.setAttribute("name", annotation)
949
 
                    attr_tag.setAttribute("value", value)
950
 
                    if_tag.appendChild(attr_tag)
 
985
                    ann_tag = document.createElement("annotation")
 
986
                    ann_tag.setAttribute("name", annotation)
 
987
                    ann_tag.setAttribute("value", value)
 
988
                    if_tag.appendChild(ann_tag)
951
989
                # Add the names to the return values for the
952
990
                # "org.freedesktop.DBus.Properties" methods
953
991
                if (if_tag.getAttribute("name")
1026
1064
                                nonmethod_func.func_name,
1027
1065
                                nonmethod_func.func_defaults,
1028
1066
                                nonmethod_func.func_closure)))
 
1067
                    # Copy annotations, if any
 
1068
                    try:
 
1069
                        new_function._dbus_annotations = (
 
1070
                            dict(attribute._dbus_annotations))
 
1071
                    except AttributeError:
 
1072
                        pass
1029
1073
                    # Define a creator of a function to call both the
1030
1074
                    # old and new functions, so both the old and new
1031
1075
                    # signals gets sent when the function is called
1059
1103
                                        attribute.func_name,
1060
1104
                                        attribute.func_defaults,
1061
1105
                                        attribute.func_closure)))
 
1106
                    # Copy annotations, if any
 
1107
                    try:
 
1108
                        attr[attrname]._dbus_annotations = (
 
1109
                            dict(attribute._dbus_annotations))
 
1110
                    except AttributeError:
 
1111
                        pass
1062
1112
                # Is this a D-Bus property?
1063
1113
                elif getattr(attribute, "_dbus_is_property", False):
1064
1114
                    # Create a new, but exactly alike, function
1078
1128
                                        attribute.func_name,
1079
1129
                                        attribute.func_defaults,
1080
1130
                                        attribute.func_closure)))
 
1131
                    # Copy annotations, if any
 
1132
                    try:
 
1133
                        attr[attrname]._dbus_annotations = (
 
1134
                            dict(attribute._dbus_annotations))
 
1135
                    except AttributeError:
 
1136
                        pass
1081
1137
                # Is this a D-Bus interface?
1082
1138
                elif getattr(attribute, "_dbus_is_interface", False):
1083
1139
                    # Create a new, but exactly alike, function