8 _moduleLogger = logging.getLogger('requests')
12 telepathy._generated.Connection_Interface_Requests.ConnectionInterfaceRequests,
13 telepathy.server.properties.DBusProperties
16 HACK older python-telepathy doesn't provide an implementation but the new one does, ARGH
20 telepathy._generated.Connection_Interface_Requests.ConnectionInterfaceRequests.__init__(self)
21 telepathy.server.properties.DBusProperties.__init__(self)
23 self._implement_property_get(telepathy.interfaces.CONNECTION_INTERFACE_REQUESTS,
24 {'Channels': lambda: dbus.Array(self._get_channels(),
25 signature='(oa{sv})'),
26 'RequestableChannelClasses': lambda: dbus.Array(
27 self._channel_manager.get_requestable_channel_classes(),
28 signature='(a{sv}as)')})
31 def _channel_manager(self):
35 raise NotImplementedError("Abstract property called")
37 def _get_channels(self):
38 return [(c._object_path, c.get_props()) for c in self._channels]
40 def _check_basic_properties(self, props):
41 # ChannelType must be present and must be a string.
42 if telepathy.interfaces.CHANNEL_INTERFACE + '.ChannelType' not in props or \
43 not isinstance(props[telepathy.interfaces.CHANNEL_INTERFACE + '.ChannelType'],
45 raise telepathy.errors.InvalidArgument('ChannelType is required')
47 def check_valid_type_if_exists(prop, fun):
48 p = telepathy.interfaces.CHANNEL_INTERFACE + '.' + prop
49 if p in props and not fun(props[p]):
50 raise telepathy.errors.InvalidArgument('Invalid %s' % prop)
52 # Allow TargetHandleType to be missing, but not to be otherwise broken.
53 check_valid_type_if_exists('TargetHandleType',
54 lambda p: p > 0 and p < (2**32)-1)
56 # Allow TargetType to be missing, but not to be otherwise broken.
57 check_valid_type_if_exists('TargetHandle',
58 lambda p: p > 0 and p < (2**32)-1)
59 if props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandle') == 0:
60 raise telepathy.errors.InvalidArgument("TargetHandle may not be 0")
62 # Allow TargetID to be missing, but not to be otherwise broken.
63 check_valid_type_if_exists('TargetID',
64 lambda p: isinstance(p, dbus.String))
66 # Disallow InitiatorHandle, InitiatorID and Requested.
67 check_valid_type_if_exists('InitiatorHandle', lambda p: False)
68 check_valid_type_if_exists('InitiatorID', lambda p: False)
69 check_valid_type_if_exists('Requested', lambda p: False)
71 type = props[telepathy.interfaces.CHANNEL_INTERFACE + '.ChannelType']
72 handle_type = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandleType',
73 telepathy.constants.HANDLE_TYPE_NONE)
74 handle = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandle', 0)
76 return (type, handle_type, handle)
78 def _validate_handle(self, props):
79 target_handle_type = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandleType',
80 telepathy.constants.HANDLE_TYPE_NONE)
81 target_handle = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandle', None)
82 target_id = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetID', None)
84 # Handle type 0 cannot have a handle.
85 if target_handle_type == telepathy.constants.HANDLE_TYPE_NONE and target_handle != None:
86 raise telepathy.errors.InvalidArgument('When TargetHandleType is NONE, ' +
87 'TargetHandle must be omitted')
89 # Handle type 0 cannot have a TargetID.
90 if target_handle_type == telepathy.constants.HANDLE_TYPE_NONE and target_id != None:
91 raise telepathy.errors.InvalidArgument('When TargetHandleType is NONE, TargetID ' +
94 if target_handle_type != telepathy.constants.HANDLE_TYPE_NONE:
95 if target_handle == None and target_id == None:
96 raise telepathy.errors.InvalidArgument('When TargetHandleType is not NONE, ' +
97 'either TargetHandle or TargetID must also be given')
99 if target_handle != None and target_id != None:
100 raise telepathy.errors.InvalidArgument('TargetHandle and TargetID must not ' +
103 self.check_handle_type(target_handle_type)
106 def _alter_properties(self, props):
107 target_handle_type = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandleType',
108 telepathy.constants.HANDLE_TYPE_NONE)
109 target_handle = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandle', None)
110 target_id = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetID', None)
112 altered_properties = props.copy()
114 if target_handle_type != telepathy.constants.HANDLE_TYPE_NONE:
115 if target_handle == None:
116 # Turn TargetID into TargetHandle.
117 for handle in self._handles.itervalues():
118 if handle.get_name() == target_id and handle.get_type() == target_handle_type:
119 target_handle = handle.get_id()
120 if not target_handle:
121 raise telepathy.errors.InvalidHandle('TargetID %s not valid for type %d' %
122 target_id, target_handle_type)
124 altered_properties[telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandle'] = \
127 # Check the supplied TargetHandle is valid
128 self.check_handle(target_handle_type, target_handle)
130 target_id = self._handles[target_handle_type,\
131 target_handle].get_name()
132 altered_properties[telepathy.interfaces.CHANNEL_INTERFACE + '.TargetID'] = \
135 altered_properties[telepathy.interfaces.CHANNEL_INTERFACE + '.Requested'] = True
137 return altered_properties
139 @dbus.service.method(telepathy.interfaces.CONNECTION_INTERFACE_REQUESTS,
140 in_signature='a{sv}', out_signature='oa{sv}',
141 async_callbacks=('_success', '_error'))
142 def CreateChannel(self, request, _success, _error):
143 _moduleLogger.info("CreateChannel")
144 type, handle_type, handle = self._check_basic_properties(request)
145 self._validate_handle(request)
146 props = self._alter_properties(request)
148 channel = self._channel_manager.channel_for_props(props, signal=False)
150 # Remove mutable properties
153 iface, name = prop.rsplit('.', 1) # a bit of a hack
154 if name in channel._immutable_properties:
155 if channel._immutable_properties[name] != iface:
163 _success(channel._object_path, props)
165 # CreateChannel MUST return *before* NewChannels is emitted.
166 self.signal_new_channels([channel])
168 @dbus.service.method(telepathy.interfaces.CONNECTION_INTERFACE_REQUESTS,
169 in_signature='a{sv}', out_signature='boa{sv}',
170 async_callbacks=('_success', '_error'))
171 def EnsureChannel(self, request, _success, _error):
172 _moduleLogger.info("EnsureChannel")
173 type, handle_type, handle = self._check_basic_properties(request)
174 self._validate_handle(request)
175 props = self._alter_properties(request)
177 yours = not self._channel_manager.channel_exists(props)
179 channel = self._channel_manager.channel_for_props(props, signal=False)
181 _success(yours, channel._object_path, props)
183 self.signal_new_channels([channel])