[Telepathy-commits] [telepathy-pinocchio/master] refactor some objects and methods for readability and simplicity
Travis Reitter
travis.reitter at collabora.co.uk
Wed Aug 13 17:31:30 PDT 2008
---
pinocchio/channel/contact_list.py | 8 +-
pinocchio/common.py | 30 +++++---
pinocchio/connection/__init__.py | 1 -
pinocchio/server/__init__.py | 147 ++++++++++++-------------------------
4 files changed, 71 insertions(+), 115 deletions(-)
diff --git a/pinocchio/channel/contact_list.py b/pinocchio/channel/contact_list.py
index 6185f6c..bda8b52 100644
--- a/pinocchio/channel/contact_list.py
+++ b/pinocchio/channel/contact_list.py
@@ -25,7 +25,7 @@ import pinocchio as pin
class ContactList(tp.server.ChannelTypeContactList,
tp.server.ChannelInterfaceGroup):
"""
- Set of all contacts
+ Set of contacts corresponding to a Telepathy ContactList channel.
Implements DBus interface org.freedesktop.Telepathy.Channel.Interface.Group
"""
@@ -37,14 +37,16 @@ class ContactList(tp.server.ChannelTypeContactList,
self._connection = connection
self.account_id = account_id
- contacts_disk = pin.server.ContactList(connection, channel_handle_obj)
+ contacts_disk = pin.server.StoredContactList(connection,
+ channel_handle_obj)
- handles_initial = contacts_disk.create_handles(connection)
+ handles_initial = contacts_disk.get_handle_objs()
for handle_obj in handles_initial:
connection._handles[tp.constants.HANDLE_TYPE_CONTACT,
handle_obj.get_id()] = handle_obj
# send initial member list as any other list change
+ # this stores these HandleContact objects in self._members
self.MembersChanged('', handles_initial, (), (), (), 0,
tp.constants.CHANNEL_GROUP_CHANGE_REASON_NONE)
diff --git a/pinocchio/common.py b/pinocchio/common.py
index f0cfb6f..a2f20b4 100644
--- a/pinocchio/common.py
+++ b/pinocchio/common.py
@@ -26,6 +26,7 @@ PROTO_DEFAULT = 'dummy'
ACCOUNT_DEFAULT = 'default at default'
CONTACTS_FILE_DEFAULT='contacts.xml'
+CONTACTS_FILE_MODIFIED='contacts-modified.xml'
# XXX: is there a better place to default to?
DATA_DIR_DEFAULT = '/var/lib/telepathy-pinocchio'
AVATAR_DIR_DEFAULT = os.path.join(DATA_DIR_DEFAULT, 'avatars')
@@ -40,11 +41,13 @@ def get_account_dir(account_id=None):
def get_contacts_file_abs(contacts_file=None, account_id=None):
"""Returns the absolute path for the contacts file (prepending the account's
- base data dir as necessary).
+ base data dir as necessary). Modified rosters are saved to disk as a
+ different name, so this function prefers them over the default file name.
Arguments:
- contacts_file -- given contacts file argument, or None to use the default
- (default: None)
+ contacts_file -- CONTACTS_FILE_DEFAULT to get the unmodified contacts file
+ CONTACTS_FILE_MODIFIED to get the modified contacst file
+ None to get the modified file if it exists, else default
account -- raw name of the account (default: ACCOUNT_DEFAULT)
Returns:
@@ -56,15 +59,22 @@ def get_contacts_file_abs(contacts_file=None, account_id=None):
account_dir = get_account_dir(account_id)
- if contacts_file == None:
- contacts_file = os.path.join(account_dir, CONTACTS_FILE_DEFAULT)
+ contacts_file_final = None
- # determine the absolute path for this file (based on the account's
- # personal data dir)
- if not os.path.isabs(contacts_file):
- contacts_file = os.path.join(account_dir, contacts_file)
+ if contacts_file in (CONTACTS_FILE_DEFAULT, CONTACTS_FILE_MODIFIED):
+ contacts_file_final = os.path.join(account_dir, CONTACTS_FILE_MODIFIED)
+ elif contacts_file == None:
+ # if contact list has been modified, it will be saved with this name
+ contacts_file_final = os.path.join(account_dir, CONTACTS_FILE_MODIFIED)
- return contacts_file
+ # otherwise, use the default file path
+ if not os.path.isfile(contacts_file_final):
+ contacts_file_final = os.path.join(account_dir,
+ CONTACTS_FILE_DEFAULT)
+ else:
+ raise ValueError, 'invalid contacts file argument'
+
+ return contacts_file_final
def image_filename_to_mime_type(file_path):
"""Get the MIME type for a given image file. The image's MIME type will be
diff --git a/pinocchio/connection/__init__.py b/pinocchio/connection/__init__.py
index d691c7d..ae91dfa 100644
--- a/pinocchio/connection/__init__.py
+++ b/pinocchio/connection/__init__.py
@@ -36,7 +36,6 @@ class Connection(tp.server.Connection,
_CONTACT_LIST_NAMES = ('subscribe', 'publish', 'hide', 'allow', 'deny')
- # TODO: this should probably include logging file destinations
_optional_parameters = {'password': 's', 'register': 'b'}
_mandatory_parameters = {'account': 's'}
_parameter_defaults = {'account': pin.common.ACCOUNT_DEFAULT}
diff --git a/pinocchio/server/__init__.py b/pinocchio/server/__init__.py
index 5a52b74..e1205a7 100644
--- a/pinocchio/server/__init__.py
+++ b/pinocchio/server/__init__.py
@@ -152,53 +152,11 @@ class HandleContact(tp.server.Handle):
def set_status_message(self, status_message):
self._extended_attrs['status_message'] = status_message
-class _Contact:
- """
- Internal representation of a Contact, based on XML representation.
- """
-
- def __init__(self, contact_xml):
- self.metadata = {}
-
- for key in ['alias', 'username', 'avatar_path']:
- try:
- value_tag = contact_xml.getElementsByTagName(key)[0]
- value = value_tag.firstChild.data
- except:
- value = ''
-
- self.metadata[key] = value
-
- def to_xml(self):
- """Returns xml.dom.minidom.Document representation of Contact.
-
- Internally, this XML is structured as:
-
- <contact>
- <attr_1>value_1</attr_1>
- ...
- <attr_n>value_n</attr_n>
- </contact>
- """
- impl = minidom.getDOMImplementation()
- xml_file = impl.createDocument(None, 'contact', None)
- root = xml_file.documentElement
-
- for attr_name in self.metadata.keys():
- # <attr_name>value</attr_name>
- attr = xml_file.createElement(attr_name)
- attr.appendChild(xml_file.createTextNode(self.metadata[attr_name]))
-
- root.appendChild(attr)
-
- return xml_file
-
-
-class ContactList:
+class StoredContactList:
def __init__(self, connection, channel_handle_obj):
"""
Arguments:
- connection -- connection this ContactList corresponds to
+ connection -- connection this StoredContactList corresponds to
channel_handle_obj -- handle object of the channel this list maps to
Exceptions:
@@ -211,13 +169,9 @@ class ContactList:
try:
contacts_file = open(self.connection._contacts_file, 'rU')
except:
- print 'Could not open contact list file. Falling back to default!'
-
- try:
- contacts_file = open(pin.common.get_contacts_file_abs (), 'rU')
- except:
- print 'Could not open default contact list'
- raise
+ print 'Could not open contact list file ', \
+ self.connection._contacts_file
+ raise
contacts_xml = minidom.parse(contacts_file)
contacts_file.close()
@@ -240,9 +194,46 @@ class ContactList:
lists = contact.getElementsByTagName('list')
for list in lists:
if list.firstChild.data == channel_name:
- self.contacts.append(_Contact(contact))
+ handle_contact = self.contact_xml_to_handle(contact,
+ connection)
+
+ self.contacts.append(handle_contact)
break
+ def get_handle_objs(self):
+ return self.contacts
+
+ def contact_xml_to_handle(self, contact_xml, connection):
+ handle_contact = None
+ extended_attrs = {}
+
+ try:
+ username_tag = contact_xml.getElementsByTagName('username')[0]
+ username = username_tag.firstChild.data
+ except:
+ raise ValueError, 'contact has no username'
+
+ CONTACT_HANDLE = tp.constants.HANDLE_TYPE_CONTACT
+ id, id_is_new = connection.get_handle_id_idempotent(CONTACT_HANDLE,
+ username)
+ # only create HandleContact objects as necessary (to avoid unwanted
+ # side-effects in the form of duplicate signals)
+ if id_is_new:
+ extended_attrs = {}
+ for attr in ('alias', 'avatar_path', 'status', 'status_message'):
+ try:
+ value_tag = contact_xml.getElementsByTagName(attr)[0]
+ extended_attrs[attr] = value_tag.firstChild.data
+ except:
+ pass
+
+ handle_contact = HandleContact(id, username, connection,
+ extended_attrs)
+ else:
+ handle_contact = connection._handles[CONTACT_HANDLE, id]
+
+ return handle_contact
+
def to_xml(self):
"""Returns xml.dom.minidom.Document representation of full Contact List.
@@ -271,7 +262,9 @@ class ContactList:
"""Write contact list to XML file on disk.
Arguments:
- file_src -- XML file containing contact list
+ file_dest -- XML file containing contact list (default:
+ ${ACCOUNT_DIR}/contacts-modified.xml)
+
Exceptions:
IOError -- failed to read contact list file
@@ -290,51 +283,3 @@ class ContactList:
contacts_file.write(xml_contents.encode('utf-8'))
contacts_file.close()
-
- def get_contact(self, username):
- """Returns an arbitrary contact matching the given username (if any), or
- None.
-
- Arguments:
- username -- string of username
-
- Returns:
- contact -- server._Contact for the contact in this list if matched
- """
- for (contact, name) in self.contacts.items():
- if name == username:
- return contact
-
- return None
-
- def create_handles(self, connection):
- """Returns a set of HandleContact objects for this list's contacts
- (creating new handles within the connection only as necessary).
-
- Arguments:
- connection -- telepathy.server.Connection to get/create handles within
- """
- CONTACT_HANDLE = tp.constants.HANDLE_TYPE_CONTACT
-
- handles = set()
- for contact in self.contacts:
- username = contact.metadata['username']
- id, id_is_new = connection.get_handle_id_idempotent(CONTACT_HANDLE,
- username)
-
- # only create HandleContact objects as necessary (to avoid unwanted
- # side-effects in the form of duplicate signals)
- if id_is_new:
- extended_attrs = {}
- for attr in ('alias', 'avatar_path', 'status',
- 'status_message'):
- if attr in contact.metadata:
- extended_attrs[attr] = contact.metadata[attr]
-
- handles.update((HandleContact(id, username, connection,
- extended_attrs),))
- else:
- handle_existing = connection._handles[CONTACT_HANDLE, id]
- handles.update((handle_existing,))
-
- return handles
--
1.5.6.3
More information about the Telepathy-commits
mailing list