/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: 2015-08-10 08:25:01 UTC
  • Revision ID: teddy@recompile.se-20150810082501-rb7w2dre1flqiqe2
Refactor D-Bus annotation class out from D-Bus properties class.

* mandos (DBusObjectWithAnnotations): New; factored out D-Bus
                                      annotations code from
                                      DBusObjectWithProperties class.
  (DBusObjectWithProperties): Inherit from DBusObjectWithAnnotations.
  (main/MandosDBusService): - '' -
  (main/MandosDBusService._foo): Removed interface annotation for
                                 "o.f.D.Property.EmitsChangedSignal";
                                 this object has no properties.

Show diffs side-by-side

added added

removed removed

Lines of Context:
842
842
                           access="r")
843
843
    def Property_dbus_property(self):
844
844
        return dbus.Boolean(False)
 
845
    
 
846
    See also the DBusObjectWithAnnotations class.
845
847
    """
846
848
    
847
849
    def decorator(func):
869
871
    pass
870
872
 
871
873
 
872
 
class DBusObjectWithProperties(dbus.service.Object):
873
 
    """A D-Bus object with properties.
 
874
class DBusObjectWithAnnotations(dbus.service.Object):
 
875
    """A D-Bus object with annotations.
874
876
    
875
 
    Classes inheriting from this can use the dbus_service_property
876
 
    decorator to expose methods as D-Bus properties.  It exposes the
877
 
    standard Get(), Set(), and GetAll() methods on the D-Bus.
 
877
    Classes inheriting from this can use the dbus_annotations
 
878
    decorator to add annotations to methods or signals.
878
879
    """
879
880
    
880
881
    @staticmethod
896
897
                for name, athing in
897
898
                inspect.getmembers(cls, self._is_dbus_thing(thing)))
898
899
    
 
900
    @dbus.service.method(dbus.INTROSPECTABLE_IFACE,
 
901
                         out_signature = "s",
 
902
                         path_keyword = 'object_path',
 
903
                         connection_keyword = 'connection')
 
904
    def Introspect(self, object_path, connection):
 
905
        """Overloading of standard D-Bus method.
 
906
        
 
907
        Inserts annotation tags on methods and signals.
 
908
        """
 
909
        xmlstring = dbus.service.Object.Introspect(self, object_path,
 
910
                                                   connection)
 
911
        try:
 
912
            document = xml.dom.minidom.parseString(xmlstring)
 
913
            
 
914
            for if_tag in document.getElementsByTagName("interface"):
 
915
                # Add annotation tags
 
916
                for typ in ("method", "signal"):
 
917
                    for tag in if_tag.getElementsByTagName(typ):
 
918
                        annots = dict()
 
919
                        for name, prop in (self.
 
920
                                           _get_all_dbus_things(typ)):
 
921
                            if (name == tag.getAttribute("name")
 
922
                                and prop._dbus_interface
 
923
                                == if_tag.getAttribute("name")):
 
924
                                annots.update(getattr(
 
925
                                    prop, "_dbus_annotations", {}))
 
926
                        for name, value in annots.items():
 
927
                            ann_tag = document.createElement(
 
928
                                "annotation")
 
929
                            ann_tag.setAttribute("name", name)
 
930
                            ann_tag.setAttribute("value", value)
 
931
                            tag.appendChild(ann_tag)
 
932
                # Add interface annotation tags
 
933
                for annotation, value in dict(
 
934
                    itertools.chain.from_iterable(
 
935
                        annotations().items()
 
936
                        for name, annotations
 
937
                        in self._get_all_dbus_things("interface")
 
938
                        if name == if_tag.getAttribute("name")
 
939
                        )).items():
 
940
                    ann_tag = document.createElement("annotation")
 
941
                    ann_tag.setAttribute("name", annotation)
 
942
                    ann_tag.setAttribute("value", value)
 
943
                    if_tag.appendChild(ann_tag)
 
944
                # Fix argument name for the Introspect method itself
 
945
                if (if_tag.getAttribute("name")
 
946
                                == dbus.INTROSPECTABLE_IFACE):
 
947
                    for cn in if_tag.getElementsByTagName("method"):
 
948
                        if cn.getAttribute("name") == "Introspect":
 
949
                            for arg in cn.getElementsByTagName("arg"):
 
950
                                if (arg.getAttribute("direction")
 
951
                                    == "out"):
 
952
                                    arg.setAttribute("name",
 
953
                                                     "xml_data")
 
954
            xmlstring = document.toxml("utf-8")
 
955
            document.unlink()
 
956
        except (AttributeError, xml.dom.DOMException,
 
957
                xml.parsers.expat.ExpatError) as error:
 
958
            logger.error("Failed to override Introspection method",
 
959
                         exc_info=error)
 
960
        return xmlstring
 
961
 
 
962
 
 
963
class DBusObjectWithProperties(DBusObjectWithAnnotations):
 
964
    """A D-Bus object with properties.
 
965
    
 
966
    Classes inheriting from this can use the dbus_service_property
 
967
    decorator to expose methods as D-Bus properties.  It exposes the
 
968
    standard Get(), Set(), and GetAll() methods on the D-Bus.
 
969
    """
 
970
    
899
971
    def _get_dbus_property(self, interface_name, property_name):
900
972
        """Returns a bound method if one exists which is a D-Bus
901
973
        property with the specified name and interface.
986
1058
        
987
1059
        Inserts property tags and interface annotation tags.
988
1060
        """
989
 
        xmlstring = dbus.service.Object.Introspect(self, object_path,
990
 
                                                   connection)
 
1061
        xmlstring = DBusObjectWithAnnotations.Introspect(self,
 
1062
                                                         object_path,
 
1063
                                                         connection)
991
1064
        try:
992
1065
            document = xml.dom.minidom.parseString(xmlstring)
993
1066
            
1006
1079
                            if prop._dbus_interface
1007
1080
                            == if_tag.getAttribute("name")):
1008
1081
                    if_tag.appendChild(tag)
1009
 
                # Add annotation tags
1010
 
                for typ in ("method", "signal", "property"):
1011
 
                    for tag in if_tag.getElementsByTagName(typ):
1012
 
                        annots = dict()
1013
 
                        for name, prop in (self.
1014
 
                                           _get_all_dbus_things(typ)):
1015
 
                            if (name == tag.getAttribute("name")
1016
 
                                and prop._dbus_interface
1017
 
                                == if_tag.getAttribute("name")):
1018
 
                                annots.update(getattr(
1019
 
                                    prop, "_dbus_annotations", {}))
1020
 
                        for name, value in annots.items():
1021
 
                            ann_tag = document.createElement(
1022
 
                                "annotation")
1023
 
                            ann_tag.setAttribute("name", name)
1024
 
                            ann_tag.setAttribute("value", value)
1025
 
                            tag.appendChild(ann_tag)
1026
 
                # Add interface annotation tags
1027
 
                for annotation, value in dict(
1028
 
                    itertools.chain.from_iterable(
1029
 
                        annotations().items()
1030
 
                        for name, annotations
1031
 
                        in self._get_all_dbus_things("interface")
1032
 
                        if name == if_tag.getAttribute("name")
1033
 
                        )).items():
1034
 
                    ann_tag = document.createElement("annotation")
1035
 
                    ann_tag.setAttribute("name", annotation)
1036
 
                    ann_tag.setAttribute("value", value)
1037
 
                    if_tag.appendChild(ann_tag)
 
1082
                # Add annotation tags for properties
 
1083
                for tag in if_tag.getElementsByTagName("property"):
 
1084
                    annots = dict()
 
1085
                    for name, prop in self._get_all_dbus_things(
 
1086
                            "property"):
 
1087
                        if (name == tag.getAttribute("name")
 
1088
                            and prop._dbus_interface
 
1089
                            == if_tag.getAttribute("name")):
 
1090
                            annots.update(getattr(
 
1091
                                prop, "_dbus_annotations", {}))
 
1092
                    for name, value in annots.items():
 
1093
                        ann_tag = document.createElement(
 
1094
                            "annotation")
 
1095
                        ann_tag.setAttribute("name", name)
 
1096
                        ann_tag.setAttribute("value", value)
 
1097
                        tag.appendChild(ann_tag)
1038
1098
                # Add the names to the return values for the
1039
1099
                # "org.freedesktop.DBus.Properties" methods
1040
1100
                if (if_tag.getAttribute("name")
1376
1436
        if exitstatus >= 0:
1377
1437
            # Emit D-Bus signal
1378
1438
            self.CheckerCompleted(dbus.Int16(exitstatus),
1379
 
                                  dbus.Int64(0),
 
1439
                                  # This is specific to GNU libC
 
1440
                                  dbus.Int64(exitstatus << 8),
1380
1441
                                  dbus.String(command))
1381
1442
        else:
1382
1443
            # Emit D-Bus signal
1383
1444
            self.CheckerCompleted(dbus.Int16(-1),
1384
1445
                                  dbus.Int64(
1385
 
                                      self.last_checker_signal),
 
1446
                                      # This is specific to GNU libC
 
1447
                                      (exitstatus << 8)
 
1448
                                      | self.last_checker_signal),
1386
1449
                                  dbus.String(command))
1387
1450
        return ret
1388
1451
    
1465
1528
        self.checked_ok()
1466
1529
    
1467
1530
    # Enable - method
 
1531
    @dbus_annotations({"org.freedesktop.DBus.Deprecated": "true"})
1468
1532
    @dbus.service.method(_interface)
1469
1533
    def Enable(self):
1470
1534
        "D-Bus method"
1471
1535
        self.enable()
1472
1536
    
1473
1537
    # StartChecker - method
 
1538
    @dbus_annotations({"org.freedesktop.DBus.Deprecated": "true"})
1474
1539
    @dbus.service.method(_interface)
1475
1540
    def StartChecker(self):
1476
1541
        "D-Bus method"
1477
1542
        self.start_checker()
1478
1543
    
1479
1544
    # Disable - method
 
1545
    @dbus_annotations({"org.freedesktop.DBus.Deprecated": "true"})
1480
1546
    @dbus.service.method(_interface)
1481
1547
    def Disable(self):
1482
1548
        "D-Bus method"
1483
1549
        self.disable()
1484
1550
    
1485
1551
    # StopChecker - method
 
1552
    @dbus_annotations({"org.freedesktop.DBus.Deprecated": "true"})
1486
1553
    @dbus.service.method(_interface)
1487
1554
    def StopChecker(self):
1488
1555
        self.stop_checker()
1524
1591
        self.approval_duration = datetime.timedelta(0, 0, 0, value)
1525
1592
    
1526
1593
    # Name - property
 
1594
    @dbus_annotations(
 
1595
        {"org.freedesktop.DBus.Property.EmitsChangedSignal": "const"})
1527
1596
    @dbus_service_property(_interface, signature="s", access="read")
1528
1597
    def Name_dbus_property(self):
1529
1598
        return dbus.String(self.name)
1530
1599
    
1531
1600
    # Fingerprint - property
 
1601
    @dbus_annotations(
 
1602
        {"org.freedesktop.DBus.Property.EmitsChangedSignal": "const"})
1532
1603
    @dbus_service_property(_interface, signature="s", access="read")
1533
1604
    def Fingerprint_dbus_property(self):
1534
1605
        return dbus.String(self.fingerprint)
1543
1614
        self.host = str(value)
1544
1615
    
1545
1616
    # Created - property
 
1617
    @dbus_annotations(
 
1618
        {"org.freedesktop.DBus.Property.EmitsChangedSignal": "const"})
1546
1619
    @dbus_service_property(_interface, signature="s", access="read")
1547
1620
    def Created_dbus_property(self):
1548
1621
        return datetime_to_dbus(self.created)
1663
1736
            self.stop_checker()
1664
1737
    
1665
1738
    # ObjectPath - property
 
1739
    @dbus_annotations(
 
1740
        {"org.freedesktop.DBus.Property.EmitsChangedSignal": "const",
 
1741
         "org.freedesktop.DBus.Deprecated": "true"})
1666
1742
    @dbus_service_property(_interface, signature="o", access="read")
1667
1743
    def ObjectPath_dbus_property(self):
1668
1744
        return self.dbus_object_path # is already a dbus.ObjectPath
1669
1745
    
1670
1746
    # Secret = property
 
1747
    @dbus_annotations(
 
1748
        {"org.freedesktop.DBus.Property.EmitsChangedSignal":
 
1749
         "invalidates"})
1671
1750
    @dbus_service_property(_interface,
1672
1751
                           signature="ay",
1673
1752
                           access="write",
2734
2813
        
2735
2814
        @alternate_dbus_interfaces(
2736
2815
            { "se.recompile.Mandos": "se.bsnet.fukt.Mandos" })
2737
 
        class MandosDBusService(DBusObjectWithProperties):
 
2816
        class MandosDBusService(DBusObjectWithAnnotations):
2738
2817
            """A D-Bus proxy object"""
2739
2818
            
2740
2819
            def __init__(self):
2742
2821
            
2743
2822
            _interface = "se.recompile.Mandos"
2744
2823
            
2745
 
            @dbus_interface_annotations(_interface)
2746
 
            def _foo(self):
2747
 
                return {
2748
 
                    "org.freedesktop.DBus.Property.EmitsChangedSignal":
2749
 
                    "false" }
2750
 
            
2751
2824
            @dbus.service.signal(_interface, signature="o")
2752
2825
            def ClientAdded(self, objpath):
2753
2826
                "D-Bus signal"