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")
38 def handle_by_name(self, handleType, handleName):
42 raise NotImplementedError("Abstract property called")
44 def _get_channels(self):
45 return [(c._object_path, c.get_props()) for c in self._channels]
47 def _check_basic_properties(self, props):
48 # ChannelType must be present and must be a string.
49 if telepathy.interfaces.CHANNEL_INTERFACE + '.ChannelType' not in props or \
50 not isinstance(props[telepathy.interfaces.CHANNEL_INTERFACE + '.ChannelType'],
52 raise telepathy.errors.InvalidArgument('ChannelType is required')
54 def check_valid_type_if_exists(prop, fun):
55 p = telepathy.interfaces.CHANNEL_INTERFACE + '.' + prop
56 if p in props and not fun(props[p]):
57 raise telepathy.errors.InvalidArgument('Invalid %s' % prop)
59 # Allow TargetHandleType to be missing, but not to be otherwise broken.
60 check_valid_type_if_exists('TargetHandleType',
61 lambda p: p > 0 and p < (2**32)-1)
63 # Allow TargetType to be missing, but not to be otherwise broken.
64 check_valid_type_if_exists('TargetHandle',
65 lambda p: p > 0 and p < (2**32)-1)
66 if props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandle') == 0:
67 raise telepathy.errors.InvalidArgument("TargetHandle may not be 0")
69 # Allow TargetID to be missing, but not to be otherwise broken.
70 check_valid_type_if_exists('TargetID',
71 lambda p: isinstance(p, dbus.String))
73 # Disallow InitiatorHandle, InitiatorID and Requested.
74 check_valid_type_if_exists('InitiatorHandle', lambda p: False)
75 check_valid_type_if_exists('InitiatorID', lambda p: False)
76 check_valid_type_if_exists('Requested', lambda p: False)
78 type = props[telepathy.interfaces.CHANNEL_INTERFACE + '.ChannelType']
79 handle_type = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandleType',
80 telepathy.constants.HANDLE_TYPE_NONE)
81 handle = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandle', 0)
83 return (type, handle_type, handle)
85 def _validate_handle(self, props):
86 target_handle_type = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandleType',
87 telepathy.constants.HANDLE_TYPE_NONE)
88 target_handle = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandle', None)
89 target_id = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetID', None)
91 # Handle type 0 cannot have a handle.
92 if target_handle_type == telepathy.constants.HANDLE_TYPE_NONE and target_handle != None:
93 raise telepathy.errors.InvalidArgument('When TargetHandleType is NONE, ' +
94 'TargetHandle must be omitted')
96 # Handle type 0 cannot have a TargetID.
97 if target_handle_type == telepathy.constants.HANDLE_TYPE_NONE and target_id != None:
98 raise telepathy.errors.InvalidArgument('When TargetHandleType is NONE, TargetID ' +
101 if target_handle_type != telepathy.constants.HANDLE_TYPE_NONE:
102 if target_handle == None and target_id == None:
103 raise telepathy.errors.InvalidArgument('When TargetHandleType is not NONE, ' +
104 'either TargetHandle or TargetID must also be given')
106 if target_handle != None and target_id != None:
107 raise telepathy.errors.InvalidArgument('TargetHandle and TargetID must not ' +
110 self.check_handle_type(target_handle_type)
113 def _alter_properties(self, props):
114 target_handle_type = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandleType',
115 telepathy.constants.HANDLE_TYPE_NONE)
116 target_handle = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandle', None)
117 target_id = props.get(telepathy.interfaces.CHANNEL_INTERFACE + '.TargetID', None)
119 altered_properties = props.copy()
121 if target_handle_type != telepathy.constants.HANDLE_TYPE_NONE:
122 if target_handle == None:
123 # Turn TargetID into TargetHandle.
124 target_handle = self.handle_by_name(target_handle_type, target_id)
125 altered_properties[telepathy.interfaces.CHANNEL_INTERFACE + '.TargetHandle'] = \
128 # Check the supplied TargetHandle is valid
129 self.check_handle(target_handle_type, target_handle)
131 target_id = self._handles[target_handle_type,\
132 target_handle].get_name()
133 altered_properties[telepathy.interfaces.CHANNEL_INTERFACE + '.TargetID'] = \
136 altered_properties[telepathy.interfaces.CHANNEL_INTERFACE + '.Requested'] = True
138 return altered_properties
140 @dbus.service.method(telepathy.interfaces.CONNECTION_INTERFACE_REQUESTS,
141 in_signature='a{sv}', out_signature='oa{sv}',
142 async_callbacks=('_success', '_error'))
143 def CreateChannel(self, request, _success, _error):
144 _moduleLogger.info("CreateChannel")
145 type, handle_type, handle = self._check_basic_properties(request)
146 self._validate_handle(request)
147 props = self._alter_properties(request)
149 channel = self._channel_manager.channel_for_props(props, signal=False)
151 # Remove mutable properties
154 iface, name = prop.rsplit('.', 1) # a bit of a hack
155 if name in channel._immutable_properties:
156 if channel._immutable_properties[name] != iface:
164 _success(channel._object_path, props)
166 # CreateChannel MUST return *before* NewChannels is emitted.
167 # @bug On older python-telepathy, it doesn't exist
168 self.signal_new_channels([channel])
170 @dbus.service.method(telepathy.interfaces.CONNECTION_INTERFACE_REQUESTS,
171 in_signature='a{sv}', out_signature='boa{sv}',
172 async_callbacks=('_success', '_error'))
173 def EnsureChannel(self, request, _success, _error):
174 _moduleLogger.info("EnsureChannel")
175 type, handle_type, handle = self._check_basic_properties(request)
176 self._validate_handle(request)
177 props = self._alter_properties(request)
179 yours = not self._channel_manager.channel_exists(props)
181 channel = self._channel_manager.channel_for_props(props, signal=False)
183 _success(yours, channel._object_path, props)
185 # @bug On older python-telepathy, it doesn't exist
186 self.signal_new_channels([channel])