1 # Copyright 2015 The Chromium OS Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 import dbus 6 import dbus.service 7 8 9 class NoSuchPropertyException(Exception): 10 """Raised when someone requests a property that has not been registered.""" 11 pass 12 13 14 class DBusPropertyExposer(dbus.service.Object): 15 """Exports the org.freedesktop.DBus.Properties interface.""" 16 17 def __init__(self, bus, path, interface_name): 18 super(DBusPropertyExposer, self).__init__(bus, path) 19 self.interface_name = interface_name 20 self._properties = dict() 21 22 23 def register_property(self, property_name, property_getter): 24 """Subclasses should call this function for each exposed property. 25 26 @param property_name: string name of property to expose. 27 @param property_getter: function that takes no arguments and returns 28 a value for the property, in its proper DBus typing. 29 30 """ 31 self._properties[property_name] = property_getter 32 33 34 def on_property_changed(self, property_name): 35 """Subclasses should call this function when property values change. 36 37 @param property_name: string name of property that changed. 38 39 """ 40 self.PropertiesChanged(dbus.String(self.interface_name), 41 self.property_getter(), 42 dbus.Array([], 's')) 43 44 45 def property_getter(self): 46 """Method suitable for giving to the ObjectManager. 47 48 @return map of DBus strings to variants. 49 50 """ 51 results = dbus.Dictionary(dict(), 'sv') 52 for property_name, property_getter in self._properties.iteritems(): 53 results[dbus.String(property_name)] = property_getter() 54 return results 55 56 57 @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, 58 in_signature='ss', out_signature='v') 59 def Get(self, interface_name, requested_property_name): 60 """Implements org.freedesktop.DBus.Properties.Get(). 61 62 @param interface_name: string interface to get properties of. 63 @param requested_property_name: string, self explanatory. 64 @return variant value of the given property. 65 66 """ 67 if interface_name != self.interface_name: 68 return '' 69 for property_name, property_getter in self._properties.iteritems(): 70 if property_name == requested_property_name: 71 return property_getter() 72 raise NoSuchPropertyException('Could not find property %s' % 73 requested_property_name) 74 75 76 @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, 77 in_signature='s', out_signature='a{sv}') 78 def GetAll(self, interface_name): 79 """Implements org.freedesktop.DBus.Properties.GetAll(). 80 81 @param interface_name: string interface to get properties of. 82 @return dict which maps property names to values. 83 84 """ 85 results = dbus.Dictionary(dict(), 'sv') 86 if interface_name != self.interface_name: 87 return results 88 for property_name, property_getter in self._properties.iteritems(): 89 results[dbus.String(property_name)] = property_getter() 90 return results 91 92 93 @dbus.service.signal(dbus_interface=dbus.PROPERTIES_IFACE, 94 signature='sa{sv}as') 95 def PropertiesChanged(self, interface_name, properties, invalid_properties): 96 """Implementation of DBus interface signal. 97 98 org.freedesktop.DBus.Properties.PropertiesChanged ( 99 STRING interface_name, 100 DICT<STRING,VARIANT> changed_properties, 101 ARRAY<STRING> invalidated_properties); 102 103 @param interface_name: See above. 104 @param properties: See above. 105 @param invalid_properties: See above. 106 107 """ 108