From 7ebb6c3f8cc7d5c9c0eba63a12ef859dc5241b9a Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 5 Apr 2010 21:43:36 -0500 Subject: [PATCH] Updating telepathy-python --- src/channel_manager.py | 85 ++++++++++++++++++++++++++++++-------------- src/tp/channel.py | 88 +++++++++++++++++++--------------------------- src/tp/channelmanager.py | 78 ++++++++++++++++++++++++++++++++-------- src/tp/conn.py | 17 +++++---- src/tp/handle.py | 8 ++++- 5 files changed, 175 insertions(+), 101 deletions(-) diff --git a/src/channel_manager.py b/src/channel_manager.py index 592a59c..1f732e1 100644 --- a/src/channel_manager.py +++ b/src/channel_manager.py @@ -16,47 +16,78 @@ class ChannelManager(tp.ChannelManager): def __init__(self, connection): tp.ChannelManager.__init__(self, connection) - fixed = { - telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_CONTACT_LIST - } - self._implement_channel_class( + classes = [ + ( + { + telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_CONTACT_LIST, + telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_LIST), + }, + [ + telepathy.CHANNEL_INTERFACE + '.TargetHandle', + telepathy.CHANNEL_INTERFACE + '.TargetID', + ], + ), + ] + self.implement_channel_classes( telepathy.CHANNEL_TYPE_CONTACT_LIST, self._get_list_channel, - fixed, - [] + classes, ) - fixed = { - telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_TEXT, - telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_CONTACT) - } - self._implement_channel_class( + classes = [ + ( + { + telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_TEXT, + telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_CONTACT) + }, + [ + telepathy.CHANNEL_INTERFACE + '.TargetHandle', + telepathy.CHANNEL_INTERFACE + '.TargetID', + ], + ), + ] + self.implement_channel_classes( telepathy.CHANNEL_TYPE_TEXT, self._get_text_channel, - fixed, - [] + classes, ) - fixed = { - telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_FILE_TRANSFER, - telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_CONTACT) - } - self._implement_channel_class( + classes = [ + ( + { + telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_FILE_TRANSFER, + telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_CONTACT) + }, + [ + telepathy.CHANNEL_INTERFACE + '.TargetHandle', + telepathy.CHANNEL_INTERFACE + '.TargetID', + ], + ), + ] + self.implement_channel_classes( telepathy.CHANNEL_TYPE_FILE_TRANSFER, self._get_file_transfer_channel, - fixed, - [] + classes, ) - fixed = { - telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_STREAMED_MEDIA, - telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_CONTACT) - } - self._implement_channel_class( + classes = [ + ( + { + telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_STREAMED_MEDIA, + telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_CONTACT) + }, + [ + telepathy.CHANNEL_INTERFACE + '.TargetHandle', + telepathy.CHANNEL_INTERFACE + '.TargetID', + telepathy.CHANNEL_TYPE_STREAMED_MEDIA + '.InitialAudio', + telepathy.CHANNEL_TYPE_STREAMED_MEDIA + '.InitialVideo', + ], + ), + ] + self.implement_channel_classes( telepathy.CHANNEL_TYPE_STREAMED_MEDIA, self._get_media_channel, - fixed, - [telepathy.CHANNEL_INTERFACE + '.TargetHandle'] + classes, ) def _get_list_channel(self, props): diff --git a/src/tp/channel.py b/src/tp/channel.py index 55ac675..80b4e3b 100644 --- a/src/tp/channel.py +++ b/src/tp/channel.py @@ -21,7 +21,8 @@ import dbus import dbus.service from telepathy.constants import (CONNECTION_HANDLE_TYPE_NONE, - CHANNEL_TEXT_MESSAGE_TYPE_NORMAL) + CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, + HANDLE_TYPE_NONE) from telepathy.errors import InvalidArgument @@ -42,9 +43,11 @@ from telepathy._generated.Channel import Channel as _Channel from properties import DBusProperties +from handle import NoneHandle + class Channel(_Channel, DBusProperties): - def __init__(self, connection, manager, props): + def __init__(self, connection, manager, props, object_path=None): """ Initialise the base channel object. @@ -54,7 +57,8 @@ class Channel(_Channel, DBusProperties): """ self._conn = connection self._chan_manager = manager - object_path = self._conn.get_channel_path() + + object_path = self._conn.get_channel_path(object_path) _Channel.__init__(self, self._conn._name, object_path) self._type = props[CHANNEL_INTERFACE + '.ChannelType'] @@ -62,9 +66,15 @@ class Channel(_Channel, DBusProperties): self._immutable_properties = dict() - self._handle = self._conn.get_handle_by_id( - props[CHANNEL_INTERFACE + '.TargetHandleType'], - props[CHANNEL_INTERFACE + '.TargetHandle']) + tht = props.get(CHANNEL_INTERFACE + '.TargetHandleType', HANDLE_TYPE_NONE) + + if tht == HANDLE_TYPE_NONE: + self._handle = NoneHandle() + else: + self._handle = self._conn.get_handle_by_id( + props[CHANNEL_INTERFACE + '.TargetHandleType'], + props[CHANNEL_INTERFACE + '.TargetHandle']) + self._interfaces = set() DBusProperties.__init__(self) @@ -72,8 +82,8 @@ class Channel(_Channel, DBusProperties): {'ChannelType': lambda: dbus.String(self.GetChannelType()), 'Interfaces': lambda: dbus.Array(self.GetInterfaces(), signature='s'), 'TargetHandle': lambda: dbus.UInt32(self._handle.get_id()), - 'TargetHandleType': lambda: dbus.UInt32(self._get_handle_type()), - 'TargetID': lambda: dbus.String(self._get_target_id()), + 'TargetHandleType': lambda: dbus.UInt32(self._handle.get_type()), + 'TargetID': lambda: dbus.String(self._handle.get_name()), 'Requested': lambda: self._requested}) self._add_immutables({ @@ -88,19 +98,9 @@ class Channel(_Channel, DBusProperties): def _add_immutables(self, props): self._immutable_properties.update(props) - def _get_handle_type(self): - if self._handle: - return self._handle.get_type() - else: - return CONNECTION_HANDLE_TYPE_NONE - - def _get_target_id(self): - if self._handle: - return self._handle.get_name() - else: - return '' - def get_props(self): + """Despite its name, this function actually only returns immutable channel + properties.""" props = dict() for prop, iface in self._immutable_properties.items(): props[iface + '.' + prop] = \ @@ -123,10 +123,7 @@ class Channel(_Channel, DBusProperties): """ Returns the handle type and number if this channel represents a communication with a particular contact, room or server-stored list, or zero if it is transient and defined only by its contents. """ - if self._handle: - return self._handle.get_type(), self._handle - else: - return (CONNECTION_HANDLE_TYPE_NONE, 0) + return (self._handle.get_type(), self._handle.get_id()) @dbus.service.method(CHANNEL_INTERFACE, in_signature='', out_signature='as') def GetInterfaces(self): @@ -144,30 +141,15 @@ from telepathy._generated.Channel_Type_Contact_List \ class ChannelTypeContactList(Channel, _ChannelTypeContactListIface): __doc__ = _ChannelTypeContactListIface.__doc__ - def __init__(self, connection, manager, props): - """ - Initialise the channel. - - Parameters: - connection - the parent Telepathy Connection object - """ - Channel.__init__(self, connection, manager, props) - - -from telepathy._generated.Channel_Type_File_Transfer \ - import ChannelTypeFileTransfer as _ChannelTypeFileTransferIface - -class ChannelTypeFileTransfer(Channel, _ChannelTypeFileTransferIface): - __doc__ = _ChannelTypeFileTransferIface.__doc__ - - def __init__(self, connection, manager, props): + def __init__(self, connection, manager, props, object_path=None): """ Initialise the channel. Parameters: connection - the parent Telepathy Connection object """ - Channel.__init__(self, connection, manager, props) + Channel.__init__(self, connection, manager, props, + object_path=object_path) from telepathy._generated.Channel_Type_File_Transfer \ @@ -176,14 +158,15 @@ from telepathy._generated.Channel_Type_File_Transfer \ class ChannelTypeFileTransfer(Channel, _ChannelTypeFileTransferIface): __doc__ = _ChannelTypeFileTransferIface.__doc__ - def __init__(self, connection, manager, props): + def __init__(self, connection, manager, props, object_path=None): """ Initialise the channel. Parameters: connection - the parent Telepathy Connection object """ - Channel.__init__(self, connection, manager, props) + Channel.__init__(self, connection, manager, props, + object_path=object_path) from telepathy._generated.Channel_Type_Streamed_Media \ @@ -192,14 +175,15 @@ from telepathy._generated.Channel_Type_Streamed_Media \ class ChannelTypeStreamedMedia(Channel, _ChannelTypeStreamedMediaIface): __doc__ = _ChannelTypeStreamedMediaIface.__doc__ - def __init__(self, connection, manager, props): + def __init__(self, connection, manager, props, object_path=None): """ Initialise the channel. Parameters: connection - the parent Telepathy Connection object """ - Channel.__init__(self, connection, manager, props) + Channel.__init__(self, connection, manager, props, + object_path=object_path) from telepathy._generated.Channel_Type_Room_List \ @@ -208,18 +192,19 @@ from telepathy._generated.Channel_Type_Room_List \ class ChannelTypeRoomList(Channel, _ChannelTypeRoomListIface): __doc__ = _ChannelTypeRoomListIface.__doc__ - def __init__(self, connection, manager, props): + def __init__(self, connection, manager, props, object_path=None): """ Initialise the channel. Parameters: connection - the parent Telepathy Connection object """ - Channel.__init__(self, connection, manager, props) + Channel.__init__(self, connection, manager, props, + object_path=object_path) self._listing_rooms = False self._rooms = {} - self._add_immutables(self, {'Server': CHANNEL_TYPE_ROOM_LIST}) + self._add_immutables({'Server': CHANNEL_TYPE_ROOM_LIST}) @dbus.service.method(CHANNEL_TYPE_ROOM_LIST, in_signature='', out_signature='b') def GetListingRooms(self): @@ -236,14 +221,15 @@ from telepathy._generated.Channel_Type_Text \ class ChannelTypeText(Channel, _ChannelTypeTextIface): __doc__ = _ChannelTypeTextIface.__doc__ - def __init__(self, connection, manager, props): + def __init__(self, connection, manager, props, object_path=None): """ Initialise the channel. Parameters: connection - the parent Telepathy Connection object """ - Channel.__init__(self, connection, manager, props) + Channel.__init__(self, connection, manager, props, + object_path=object_path) self._pending_messages = {} self._message_types = [CHANNEL_TEXT_MESSAGE_TYPE_NORMAL] diff --git a/src/tp/channelmanager.py b/src/tp/channelmanager.py index 4497c49..d5e2bce 100644 --- a/src/tp/channelmanager.py +++ b/src/tp/channelmanager.py @@ -16,23 +16,32 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +import warnings + from telepathy.errors import NotImplemented from telepathy.interfaces import (CHANNEL_INTERFACE, - CHANNEL_TYPE_CONTACT_LIST) + CHANNEL_TYPE_CONTACT_LIST) + +from telepathy.constants import HANDLE_TYPE_NONE + +from handle import NoneHandle class ChannelManager(object): def __init__(self, connection): self._conn = connection - self._requestable_channel_classes = dict() + self._requestable_channels = dict() self._channels = dict() + self._fixed_properties = dict() self._available_properties = dict() + self._requestables = dict() + def close(self): """Close channel manager and all the existing channels.""" - for channel_type in self._requestable_channel_classes: + for channel_type in self._requestable_channels: for channels in self._channels[channel_type].values(): for channel in channels: if channel._type == CHANNEL_TYPE_CONTACT_LIST: @@ -42,7 +51,7 @@ class ChannelManager(object): def remove_channel(self, channel): "Remove channel from the channel manager" - for channel_type in self._requestable_channel_classes: + for channel_type in self._requestable_channels: for handle, channels in self._channels[channel_type].items(): if channel in channels : channels.remove(channel) @@ -52,10 +61,15 @@ class ChannelManager(object): properties""" type = props[CHANNEL_INTERFACE + '.ChannelType'] requested = props[CHANNEL_INTERFACE + '.Requested'] - target_handle = int(props[CHANNEL_INTERFACE + '.TargetHandle']) - target_handle_type = int(props[CHANNEL_INTERFACE + '.TargetHandleType']) - handle = self._conn._handles[target_handle_type, target_handle] + target_handle_type = \ + props.get(CHANNEL_INTERFACE + '.TargetHandleType', HANDLE_TYPE_NONE) + + if target_handle_type == HANDLE_TYPE_NONE: + handle = NoneHandle() + else: + target_handle = props[CHANNEL_INTERFACE + '.TargetHandle'] + handle = self._conn._handles[target_handle_type, target_handle] return (type, requested, handle) @@ -84,14 +98,14 @@ class ChannelManager(object): """Create a new channel with theses properties""" type, _, handle = self._get_type_requested_handle(props) - if type not in self._requestable_channel_classes: + if type not in self._requestable_channels: raise NotImplemented('Unknown channel type "%s"' % type) - channel = self._requestable_channel_classes[type]( + channel = self._requestable_channels[type]( props, **args) self._conn.add_channels([channel], signal=signal) - if type in self._channels: + if handle.get_type() != HANDLE_TYPE_NONE and type in self._channels: self._channels[type].setdefault(handle, []).append(channel) return channel @@ -105,20 +119,54 @@ class ChannelManager(object): else: return self.create_channel_for_props(props, signal, **args) + # Should use implement_channel_classes instead. def _implement_channel_class(self, type, make_channel, fixed, available): - """Notify channel manager a channel with these properties can be created""" - self._requestable_channel_classes[type] = make_channel + """Implement channel types in the channel manager, and add one channel + class that is retrieved in RequestableChannelClasses. + + self.implement_channel_classes should be used instead, as it allows + implementing multiple channel classes.""" + warnings.warn('deprecated in favour of implement_channel_classes', + DeprecationWarning) + + self._requestable_channels[type] = make_channel self._channels.setdefault(type, {}) self._fixed_properties[type] = fixed self._available_properties[type] = available + # Use this function instead of _implement_channel_class. + def implement_channel_classes(self, type, make_channel, classes): + """Implement channel types in the channel manager, and add channel + classes that are retrieved in RequestableChannelClasses. + + @type: the channel type + @make_channel: a function to call which returns a Channel object + @classes: a list of channel classes. E.g. + + [ ( { '...ChannelType': '...Text', '...TargetHandleType': HANDLE_TYPE_CONTACT }, + ['...TargetHandle'] ) + ] + + See the spec for more documentation on the + Requestable_Channel_Class struct. + """ + self._requestable_channels[type] = make_channel + self._channels.setdefault(type, {}) + + self._requestables[type] = classes + def get_requestable_channel_classes(self): """Return all the channel types that can be created""" retval = [] - for channel_type in self._requestable_channel_classes: - retval.append((self._fixed_properties[channel_type], - self._available_properties[channel_type])) + for channel_type in self._requestable_channels: + retval.extend(self._requestables.get(channel_type, [])) + + # _implement_channel_class was used. + if channel_type in self._fixed_properties: + retval.append((self._fixed_properties[channel_type], + self._available_properties.get(channel_type, []))) + return retval diff --git a/src/tp/conn.py b/src/tp/conn.py index b761ce0..02305c4 100644 --- a/src/tp/conn.py +++ b/src/tp/conn.py @@ -200,9 +200,12 @@ class Connection(_Connection, DBusProperties): def set_self_handle(self, handle): self._self_handle = handle - def get_channel_path(self): - ret = '%s/channel%d' % (self._object_path, self._next_channel_id) - self._next_channel_id += 1 + def get_channel_path(self, suffix): + if not suffix: + ret = '%s/channel%d' % (self._object_path, self._next_channel_id) + self._next_channel_id += 1 + else: + ret = '%s/%s' % (self._object_path, suffix) return ret def add_channels(self, channels, signal=True): @@ -321,7 +324,7 @@ class Connection(_Connection, DBusProperties): self.check_connected() ret = [] for channel in self._channels: - chan = (channel._object_path, channel._type, channel._get_handle_type(), channel._handle) + chan = (channel._object_path, channel._type, channel._handle.get_type(), channel._handle.get_id()) ret.append(chan) return ret @@ -428,7 +431,7 @@ class ConnectionInterfaceRequests( # Allow TargetHandleType to be missing, but not to be otherwise broken. check_valid_type_if_exists('TargetHandleType', - lambda p: p > 0 and p < (2**32)-1) + lambda p: p >= 0 and p <= LAST_HANDLE_TYPE) # Allow TargetType to be missing, but not to be otherwise broken. check_valid_type_if_exists('TargetHandle', @@ -459,9 +462,9 @@ class ConnectionInterfaceRequests( target_id = props.get(CHANNEL_INTERFACE + '.TargetID', None) # Handle type 0 cannot have a handle. - if target_handle_type == HANDLE_TYPE_NONE and target_handle != None: + if target_handle_type == HANDLE_TYPE_NONE and target_handle not in (None, 0): raise InvalidArgument('When TargetHandleType is NONE, ' + - 'TargetHandle must be omitted') + 'TargetHandle must be omitted or 0') # Handle type 0 cannot have a TargetID. if target_handle_type == HANDLE_TYPE_NONE and target_id != None: diff --git a/src/tp/handle.py b/src/tp/handle.py index a7771b0..ec31b9a 100644 --- a/src/tp/handle.py +++ b/src/tp/handle.py @@ -1,6 +1,6 @@ # telepathy-python - Base classes defining the interfaces of the Telepathy framework # -# Copyright (C) 2005,2006 Collabora Limited +# Copyright (C) 2005,2006,2009,2010 Collabora Limited # Copyright (C) 2005,2006 Nokia Corporation # # This library is free software; you can redistribute it and/or @@ -17,6 +17,8 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +from telepathy.constants import HANDLE_TYPE_NONE + class Handle(object): def __init__(self, id, handle_type, name): self._id = id @@ -43,3 +45,7 @@ class Handle(object): def __ne__(self, other): return not self.__eq__(other) + +class NoneHandle(Handle): + def __init__(self): + Handle.__init__(self, 0, HANDLE_TYPE_NONE, '') -- 1.7.9.5