477
486
return now < (self.last_checked_ok + self.timeout)
480
class ClientDBus(Client, dbus.service.Object):
489
def dbus_service_property(dbus_interface, signature=u"v",
490
access=u"readwrite", byte_arrays=False):
491
"""Decorators for marking methods of a DBusObjectWithProperties to
492
become properties on the D-Bus.
494
The decorated method will be called with no arguments by "Get"
495
and with one argument by "Set".
497
The parameters, where they are supported, are the same as
498
dbus.service.method, except there is only "signature", since the
499
type from Get() and the type sent to Set() is the same.
502
func._dbus_is_property = True
503
func._dbus_interface = dbus_interface
504
func._dbus_signature = signature
505
func._dbus_access = access
506
func._dbus_name = func.__name__
507
if func._dbus_name.endswith(u"_dbus_property"):
508
func._dbus_name = func._dbus_name[:-14]
509
func._dbus_get_args_options = {u'byte_arrays': byte_arrays }
514
class DBusPropertyException(dbus.exceptions.DBusException):
515
"""A base class for D-Bus property-related exceptions
517
def __unicode__(self):
518
return unicode(str(self))
521
class DBusPropertyAccessException(DBusPropertyException):
522
"""A property's access permissions disallows an operation.
527
class DBusPropertyNotFound(DBusPropertyException):
528
"""An attempt was made to access a non-existing property.
533
class DBusObjectWithProperties(dbus.service.Object):
534
"""A D-Bus object with properties.
536
Classes inheriting from this can use the dbus_service_property
537
decorator to expose methods as D-Bus properties. It exposes the
538
standard Get(), Set(), and GetAll() methods on the D-Bus.
542
def _is_dbus_property(obj):
543
return getattr(obj, u"_dbus_is_property", False)
545
def _get_all_dbus_properties(self):
546
"""Returns a generator of (name, attribute) pairs
548
return ((prop._dbus_name, prop)
550
inspect.getmembers(self, self._is_dbus_property))
552
def _get_dbus_property(self, interface_name, property_name):
553
"""Returns a bound method if one exists which is a D-Bus
554
property with the specified name and interface.
556
for name in (property_name,
557
property_name + u"_dbus_property"):
558
prop = getattr(self, name, None)
560
or not self._is_dbus_property(prop)
561
or prop._dbus_name != property_name
562
or (interface_name and prop._dbus_interface
563
and interface_name != prop._dbus_interface)):
567
raise DBusPropertyNotFound(self.dbus_object_path + u":"
568
+ interface_name + u"."
571
@dbus.service.method(dbus.PROPERTIES_IFACE, in_signature=u"ss",
573
def Get(self, interface_name, property_name):
574
"""Standard D-Bus property Get() method, see D-Bus standard.
576
prop = self._get_dbus_property(interface_name, property_name)
577
if prop._dbus_access == u"write":
578
raise DBusPropertyAccessException(property_name)
580
if not hasattr(value, u"variant_level"):
582
return type(value)(value, variant_level=value.variant_level+1)
584
@dbus.service.method(dbus.PROPERTIES_IFACE, in_signature=u"ssv")
585
def Set(self, interface_name, property_name, value):
586
"""Standard D-Bus property Set() method, see D-Bus standard.
588
prop = self._get_dbus_property(interface_name, property_name)
589
if prop._dbus_access == u"read":
590
raise DBusPropertyAccessException(property_name)
591
if prop._dbus_get_args_options[u"byte_arrays"]:
592
value = dbus.ByteArray(''.join(unichr(byte)
596
@dbus.service.method(dbus.PROPERTIES_IFACE, in_signature=u"s",
597
out_signature=u"a{sv}")
598
def GetAll(self, interface_name):
599
"""Standard D-Bus property GetAll() method, see D-Bus
602
Note: Will not include properties with access="write".
605
for name, prop in self._get_all_dbus_properties():
607
and interface_name != prop._dbus_interface):
608
# Interface non-empty but did not match
610
# Ignore write-only properties
611
if prop._dbus_access == u"write":
614
if not hasattr(value, u"variant_level"):
617
all[name] = type(value)(value, variant_level=
618
value.variant_level+1)
619
return dbus.Dictionary(all, signature=u"sv")
621
@dbus.service.method(dbus.INTROSPECTABLE_IFACE,
623
path_keyword='object_path',
624
connection_keyword='connection')
625
def Introspect(self, object_path, connection):
626
"""Standard D-Bus method, overloaded to insert property tags.
628
xmlstring = dbus.service.Object.Introspect(self, object_path,
630
document = xml.dom.minidom.parseString(xmlstring)
632
def make_tag(document, name, prop):
633
e = document.createElement(u"property")
634
e.setAttribute(u"name", name)
635
e.setAttribute(u"type", prop._dbus_signature)
636
e.setAttribute(u"access", prop._dbus_access)
638
for if_tag in document.getElementsByTagName(u"interface"):
639
for tag in (make_tag(document, name, prop)
641
in self._get_all_dbus_properties()
642
if prop._dbus_interface
643
== if_tag.getAttribute(u"name")):
644
if_tag.appendChild(tag)
645
xmlstring = document.toxml(u"utf-8")
650
class ClientDBus(Client, DBusObjectWithProperties):
481
651
"""A Client class using D-Bus
614
# GetAllProperties - method
615
@dbus.service.method(_interface, out_signature=u"a{sv}")
616
def GetAllProperties(self):
618
return dbus.Dictionary({
619
dbus.String(u"name"):
620
dbus.String(self.name, variant_level=1),
621
dbus.String(u"fingerprint"):
622
dbus.String(self.fingerprint, variant_level=1),
623
dbus.String(u"host"):
624
dbus.String(self.host, variant_level=1),
625
dbus.String(u"created"):
626
self._datetime_to_dbus(self.created,
628
dbus.String(u"last_enabled"):
629
(self._datetime_to_dbus(self.last_enabled,
631
if self.last_enabled is not None
632
else dbus.Boolean(False, variant_level=1)),
633
dbus.String(u"enabled"):
634
dbus.Boolean(self.enabled, variant_level=1),
635
dbus.String(u"last_checked_ok"):
636
(self._datetime_to_dbus(self.last_checked_ok,
638
if self.last_checked_ok is not None
639
else dbus.Boolean (False, variant_level=1)),
640
dbus.String(u"timeout"):
641
dbus.UInt64(self.timeout_milliseconds(),
643
dbus.String(u"interval"):
644
dbus.UInt64(self.interval_milliseconds(),
646
dbus.String(u"checker"):
647
dbus.String(self.checker_command,
649
dbus.String(u"checker_running"):
650
dbus.Boolean(self.checker is not None,
652
dbus.String(u"object_path"):
653
dbus.ObjectPath(self.dbus_object_path,
657
# IsStillValid - method
658
@dbus.service.method(_interface, out_signature=u"b")
659
def IsStillValid(self):
660
return self.still_valid()
662
784
# PropertyChanged - signal
663
785
@dbus.service.signal(_interface, signature=u"sv")
664
786
def PropertyChanged(self, property, value):
680
# SetChecker - method
681
@dbus.service.method(_interface, in_signature=u"s")
682
def SetChecker(self, checker):
683
"D-Bus setter method"
684
self.checker_command = checker
686
self.PropertyChanged(dbus.String(u"checker"),
687
dbus.String(self.checker_command,
691
@dbus.service.method(_interface, in_signature=u"s")
692
def SetHost(self, host):
693
"D-Bus setter method"
696
self.PropertyChanged(dbus.String(u"host"),
697
dbus.String(self.host, variant_level=1))
699
# SetInterval - method
700
@dbus.service.method(_interface, in_signature=u"t")
701
def SetInterval(self, milliseconds):
702
self.interval = datetime.timedelta(0, 0, 0, milliseconds)
704
self.PropertyChanged(dbus.String(u"interval"),
705
(dbus.UInt64(self.interval_milliseconds(),
709
@dbus.service.method(_interface, in_signature=u"ay",
711
def SetSecret(self, secret):
712
"D-Bus setter method"
713
self.secret = str(secret)
715
# SetTimeout - method
716
@dbus.service.method(_interface, in_signature=u"t")
717
def SetTimeout(self, milliseconds):
718
self.timeout = datetime.timedelta(0, 0, 0, milliseconds)
720
self.PropertyChanged(dbus.String(u"timeout"),
721
(dbus.UInt64(self.timeout_milliseconds(),
724
802
# Enable - method
725
803
@dbus.service.method(_interface)
726
804
def Enable(self):
744
822
def StopChecker(self):
745
823
self.stop_checker()
826
@dbus_service_property(_interface, signature=u"s", access=u"read")
827
def name_dbus_property(self):
828
return dbus.String(self.name)
830
# fingerprint - property
831
@dbus_service_property(_interface, signature=u"s", access=u"read")
832
def fingerprint_dbus_property(self):
833
return dbus.String(self.fingerprint)
836
@dbus_service_property(_interface, signature=u"s",
838
def host_dbus_property(self, value=None):
839
if value is None: # get
840
return dbus.String(self.host)
843
self.PropertyChanged(dbus.String(u"host"),
844
dbus.String(value, variant_level=1))
847
@dbus_service_property(_interface, signature=u"s", access=u"read")
848
def created_dbus_property(self):
849
return dbus.String(self._datetime_to_dbus(self.created))
851
# last_enabled - property
852
@dbus_service_property(_interface, signature=u"s", access=u"read")
853
def last_enabled_dbus_property(self):
854
if self.last_enabled is None:
855
return dbus.String(u"")
856
return dbus.String(self._datetime_to_dbus(self.last_enabled))
859
@dbus_service_property(_interface, signature=u"b",
861
def enabled_dbus_property(self, value=None):
862
if value is None: # get
863
return dbus.Boolean(self.enabled)
869
# last_checked_ok - property
870
@dbus_service_property(_interface, signature=u"s",
872
def last_checked_ok_dbus_property(self, value=None):
873
if value is not None:
876
if self.last_checked_ok is None:
877
return dbus.String(u"")
878
return dbus.String(self._datetime_to_dbus(self
882
@dbus_service_property(_interface, signature=u"t",
884
def timeout_dbus_property(self, value=None):
885
if value is None: # get
886
return dbus.UInt64(self.timeout_milliseconds())
887
self.timeout = datetime.timedelta(0, 0, 0, value)
889
self.PropertyChanged(dbus.String(u"timeout"),
890
dbus.UInt64(value, variant_level=1))
891
if getattr(self, u"disable_initiator_tag", None) is None:
894
gobject.source_remove(self.disable_initiator_tag)
895
self.disable_initiator_tag = None
897
_timedelta_to_milliseconds((self
903
# The timeout has passed
906
self.disable_initiator_tag = (gobject.timeout_add
907
(time_to_die, self.disable))
909
# interval - property
910
@dbus_service_property(_interface, signature=u"t",
912
def interval_dbus_property(self, value=None):
913
if value is None: # get
914
return dbus.UInt64(self.interval_milliseconds())
915
self.interval = datetime.timedelta(0, 0, 0, value)
917
self.PropertyChanged(dbus.String(u"interval"),
918
dbus.UInt64(value, variant_level=1))
919
if getattr(self, u"checker_initiator_tag", None) is None:
921
# Reschedule checker run
922
gobject.source_remove(self.checker_initiator_tag)
923
self.checker_initiator_tag = (gobject.timeout_add
924
(value, self.start_checker))
925
self.start_checker() # Start one now, too
928
@dbus_service_property(_interface, signature=u"s",
930
def checker_dbus_property(self, value=None):
931
if value is None: # get
932
return dbus.String(self.checker_command)
933
self.checker_command = value
935
self.PropertyChanged(dbus.String(u"checker"),
936
dbus.String(self.checker_command,
939
# checker_running - property
940
@dbus_service_property(_interface, signature=u"b",
942
def checker_running_dbus_property(self, value=None):
943
if value is None: # get
944
return dbus.Boolean(self.checker is not None)
950
# object_path - property
951
@dbus_service_property(_interface, signature=u"o", access=u"read")
952
def object_path_dbus_property(self):
953
return self.dbus_object_path # is already a dbus.ObjectPath
956
@dbus_service_property(_interface, signature=u"ay",
957
access=u"write", byte_arrays=True)
958
def secret_dbus_property(self, value):
959
self.secret = str(value)