Updating telepathy-python
authorEd Page <eopage@byu.net>
Tue, 6 Apr 2010 02:43:36 +0000 (21:43 -0500)
committerEd Page <eopage@byu.net>
Tue, 6 Apr 2010 02:43:36 +0000 (21:43 -0500)
src/channel_manager.py
src/tp/channel.py
src/tp/channelmanager.py
src/tp/conn.py
src/tp/handle.py

index 592a59c..1f732e1 100644 (file)
@@ -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):
index 55ac675..80b4e3b 100644 (file)
@@ -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]
index 4497c49..d5e2bce 100644 (file)
 # 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
index b761ce0..02305c4 100644 (file)
@@ -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:
index a7771b0..ec31b9a 100644 (file)
@@ -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, '')