From 06129f45ef6adfb3403fc5a4bf8268bac8e77226 Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Thu, 5 Nov 2009 15:57:43 +0100 Subject: [PATCH] Let contact instances know their corresponding account. contact.account and gc_contact.account contains the account name of the owning account. There is still code around in many placed which tries to workaround this missing information. Such code has to be migrated on per-need basis. --- src/common/contacts.py | 43 +++++++++++++++--------- src/dialogs.py | 2 +- src/filetransfers_window.py | 2 +- src/groupchat_control.py | 2 +- src/gui_interface.py | 16 ++++----- src/roster_window.py | 14 ++++---- src/search_window.py | 2 +- src/session.py | 2 +- test/unit/test_contacts.py | 67 +++++++++++++++++++++++++++++++++---- 9 files changed, 108 insertions(+), 42 deletions(-) diff --git a/src/common/contacts.py b/src/common/contacts.py index b50f80d70..ff42163a3 100644 --- a/src/common/contacts.py +++ b/src/common/contacts.py @@ -29,16 +29,23 @@ ## import common.gajim - - from common import caps - -class CommonContact(object): +class XMPPEntity(object): + '''Base representation of entities in XMPP''' - def __init__(self, jid, resource, show, status, name, our_chatstate, + def __init__(self, jid, account, resource): + self.jid = jid + self.resource = resource + self.account = account + +class CommonContact(XMPPEntity): + + def __init__(self, jid, account, resource, show, status, name, our_chatstate, composing_xep, chatstate, client_caps=None): + XMPPEntity.__init__(self, jid, account, resource) + self.jid = jid self.resource = resource self.show = show @@ -99,12 +106,12 @@ class CommonContact(object): class Contact(CommonContact): '''Information concerning each contact''' - def __init__(self, jid='', name='', groups=[], show='', status='', sub='', + def __init__(self, jid, account, name='', groups=[], show='', status='', sub='', ask='', resource='', priority=0, keyID='', client_caps=None, our_chatstate=None, chatstate=None, last_status_time=None, msg_id = None, composing_xep=None, mood={}, tune={}, activity={}): - CommonContact.__init__(self, jid, resource, show, status, name, + CommonContact.__init__(self, jid, account, resource, show, status, name, our_chatstate, composing_xep, chatstate, client_caps=client_caps) self.contact_name = '' # nick choosen by contact @@ -184,11 +191,11 @@ class Contact(CommonContact): class GC_Contact(CommonContact): '''Information concerning each groupchat contact''' - def __init__(self, room_jid='', name='', show='', status='', role='', + def __init__(self, room_jid, account, name='', show='', status='', role='', affiliation='', jid='', resource='', our_chatstate=None, composing_xep=None, chatstate=None): - CommonContact.__init__(self, jid, resource, show, status, name, + CommonContact.__init__(self, jid, account, resource, show, status, name, our_chatstate, composing_xep, chatstate) self.room_jid = room_jid @@ -233,7 +240,7 @@ class Contacts: del self._gc_contacts[account] del self._metacontacts_tags[account] - def create_contact(self, jid='', name='', groups=[], show='', status='', + def create_contact(self, jid, account, name='', groups=[], show='', status='', sub='', ask='', resource='', priority=0, keyID='', client_caps=None, our_chatstate=None, chatstate=None, last_status_time=None, composing_xep=None, mood={}, tune={}, activity={}): @@ -244,21 +251,23 @@ class Contacts: if group not in groups_unique: groups_unique.append(group) - return Contact(jid=jid, name=name, groups=groups_unique, show=show, - status=status, sub=sub, ask=ask, resource=resource, priority=priority, + return Contact(jid=jid, account=account, name=name, groups=groups_unique, + show=show, status=status, sub=sub, ask=ask, resource=resource, priority=priority, keyID=keyID, client_caps=client_caps, our_chatstate=our_chatstate, chatstate=chatstate, last_status_time=last_status_time, composing_xep=composing_xep, mood=mood, tune=tune, activity=activity) def copy_contact(self, contact): - return self.create_contact(jid=contact.jid, name=contact.name, - groups=contact.groups, show=contact.show, status=contact.status, + return self.create_contact(jid=contact.jid, account=contact.account, + name=contact.name, groups=contact.groups, show=contact.show, status=contact.status, sub=contact.sub, ask=contact.ask, resource=contact.resource, priority=contact.priority, keyID=contact.keyID, client_caps=contact.client_caps, our_chatstate=contact.our_chatstate, chatstate=contact.chatstate, last_status_time=contact.last_status_time) def add_contact(self, account, contact): + assert account == contact.account # migration check + # No such account before ? if account not in self._contacts: self._contacts[account] = {contact.jid : [contact]} @@ -623,16 +632,18 @@ class Contacts: def contact_from_gc_contact(self, gc_contact): '''Create a Contact instance from a GC_Contact instance''' jid = gc_contact.get_full_jid() - return Contact(jid=jid, resource=gc_contact.resource, + return Contact(jid=jid, account=gc_contact.account, resource=gc_contact.resource, name=gc_contact.name, groups=[], show=gc_contact.show, status=gc_contact.status, sub='none', client_caps=gc_contact.client_caps) - def create_gc_contact(self, room_jid='', name='', show='', status='', + def create_gc_contact(self, room_jid, account, name='', show='', status='', role='', affiliation='', jid='', resource=''): return GC_Contact(room_jid, name, show, status, role, affiliation, jid, resource) def add_gc_contact(self, account, gc_contact): + assert account == gc_contact.account # migration check + # No such account before ? if account not in self._gc_contacts: self._contacts[account] = {gc_contact.room_jid : {gc_contact.name: \ diff --git a/src/dialogs.py b/src/dialogs.py index 3233855ea..d9cf91328 100644 --- a/src/dialogs.py +++ b/src/dialogs.py @@ -1888,7 +1888,7 @@ class SubscriptionRequestWindow: if self.jid in gajim.interface.instances[self.account]['infos']: gajim.interface.instances[self.account]['infos'][self.jid].window.present() else: - contact = gajim.contacts.create_contact(jid=self.jid, name='', + contact = gajim.contacts.create_contact(jid=self.jid, account=self.account, name='', groups=[], show='', status='', sub='', ask='', resource='', priority=5, keyID='', our_chatstate=None, chatstate=None) gajim.interface.instances[self.account]['infos'][self.jid] = \ diff --git a/src/filetransfers_window.py b/src/filetransfers_window.py index 2b3642da7..cae4549e6 100644 --- a/src/filetransfers_window.py +++ b/src/filetransfers_window.py @@ -284,7 +284,7 @@ _('Connection with peer cannot be established.')) if contact.find('/') == -1: return (jid, resource) = contact.split('/', 1) - contact = gajim.contacts.create_contact(jid=jid, resource=resource) + contact = gajim.contacts.create_contact(jid=jid, account=account, resource=resource) file_name = os.path.split(file_path)[1] file_props = self.get_send_file_props(account, contact, file_path, file_name, file_desc) diff --git a/src/groupchat_control.py b/src/groupchat_control.py index aad08ff67..24097300f 100644 --- a/src/groupchat_control.py +++ b/src/groupchat_control.py @@ -1463,7 +1463,7 @@ class GroupchatControl(ChatControlBase): self.draw_all_roles() iter_ = model.append(role_iter, (None, nick, 'contact', name, None)) if not nick in gajim.contacts.get_nick_list(self.account, self.room_jid): - gc_contact = gajim.contacts.create_gc_contact(room_jid=self.room_jid, + gc_contact = gajim.contacts.create_gc_contact(room_jid=self.room_jid, account=self.account, name=nick, show=show, status=status, role=role, affiliation=affiliation, jid=j, resource=resource) gajim.contacts.add_gc_contact(self.account, gc_contact) diff --git a/src/gui_interface.py b/src/gui_interface.py index 3f8a50036..8a153405d 100644 --- a/src/gui_interface.py +++ b/src/gui_interface.py @@ -344,7 +344,7 @@ class Interface: # Ignore offline presence of unknown self resource if new_show < 2: return - contact1 = gajim.contacts.create_contact(jid=ji, + contact1 = gajim.contacts.create_contact(jid=ji, account=account, name=gajim.nicks[account], groups=['self_contact'], show=array[1], status=status_message, sub='both', ask='none', priority=priority, keyID=keyID, resource=resource, @@ -612,8 +612,8 @@ class Interface: keyID = attached_keys[attached_keys.index(jid) + 1] name = jid.split('@', 1)[0] name = name.split('%', 1)[0] - contact1 = gajim.contacts.create_contact(jid=jid, name=name, - groups=[], show='online', status='online', + contact1 = gajim.contacts.create_contact(jid=jid, account=account, + name=name, groups=[], show='online', status='online', ask='to', resource=array[1], keyID=keyID) gajim.contacts.add_contact(account, contact1) self.roster.add_contact(jid, account) @@ -1213,8 +1213,8 @@ class Interface: if sub == 'remove': return # Add new contact to roster - contact = gajim.contacts.create_contact(jid=jid, name=name, - groups=groups, show='offline', sub=sub, ask=ask) + contact = gajim.contacts.create_contact(jid=jid, account=account, + name=name, groups=groups, show='offline', sub=sub, ask=ask) gajim.contacts.add_contact(account, contact) self.roster.add_contact(jid, account) else: @@ -1353,7 +1353,7 @@ class Interface: 'attached_gpg_keys').split() if jid in attached_keys: keyID = attached_keys[attached_keys.index(jid) + 1] - contact = gajim.contacts.create_contact(jid=jid, name='', + contact = gajim.contacts.create_contact(jid=jid, account=account, name='', groups=[_('Not in Roster')], show='not in roster', status='', sub='none', keyID=keyID) gajim.contacts.add_contact(account, contact) @@ -2567,7 +2567,7 @@ class Interface: account): # Join new groupchat if minimize: - contact = gajim.contacts.create_contact(jid=room_jid, name=nick) + contact = gajim.contacts.create_contact(jid=room_jid, account=account, name=nick) gc_control = GroupchatControl(None, contact, account) gajim.interface.minimized_controls[account][room_jid] = gc_control self.roster.add_groupchat(room_jid, account) @@ -2590,7 +2590,7 @@ class Interface: def new_room(self, room_jid, nick, account, is_continued=False): # Get target window, create a control, and associate it with the window - contact = gajim.contacts.create_contact(jid=room_jid, name=nick) + contact = gajim.contacts.create_contact(jid=room_jid, account=account, name=nick) mw = self.msg_win_mgr.get_window(contact.jid, account) if not mw: mw = self.msg_win_mgr.create_window(contact, account, diff --git a/src/roster_window.py b/src/roster_window.py index 9181c0e5b..a50021a6c 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -808,7 +808,7 @@ class RosterWindow: else: name = jid.split('@')[0] # New groupchat - contact = gajim.contacts.create_contact(jid=jid, name=name, + contact = gajim.contacts.create_contact(jid=jid, account=account, name=name, groups=[_('Groupchats')], show=show, status=status, sub='none') gajim.contacts.add_contact(account, contact) self.add_contact(jid, account) @@ -843,7 +843,7 @@ class RosterWindow: Return the added contact instance.''' contact = gajim.contacts.get_contact_with_highest_priority(account, jid) if contact is None: - contact = gajim.contacts.create_contact(jid=jid, name=jid, + contact = gajim.contacts.create_contact(jid=jid, account=account, name=jid, groups=[_('Transports')], show='offline', status='offline', sub='from') gajim.contacts.add_contact(account, contact) @@ -984,7 +984,7 @@ class RosterWindow: 'attached_gpg_keys').split() if jid in attached_keys: keyID = attached_keys[attached_keys.index(jid) + 1] - contact = gajim.contacts.create_contact(jid=jid, name=nick, + contact = gajim.contacts.create_contact(jid=jid, account=account, name=nick, groups=[_('Not in Roster')], show='not in roster', status='', sub='none', resource=resource, keyID=keyID) gajim.contacts.add_contact(account, contact) @@ -1774,7 +1774,7 @@ class RosterWindow: if gajim.jid_is_transport(jid): array[jid]['groups'] = [_('Transports')] - contact1 = gajim.contacts.create_contact(jid=ji, name=name, + contact1 = gajim.contacts.create_contact(jid=ji, account=account, name=name, groups=array[jid]['groups'], show=show, status=status, sub=array[jid]['subscription'], ask=array[jid]['ask'], resource=resource, keyID=keyID) @@ -1921,7 +1921,7 @@ class RosterWindow: 'attached_gpg_keys').split() if jid in attached_keys: keyID = attached_keys[attached_keys.index(jid) + 1] - contact = gajim.contacts.create_contact(jid=jid, name=nickname, + contact = gajim.contacts.create_contact(jid=jid, account=account, name=nickname, groups=groups, show='requested', status='', ask='none', sub='subscribe', keyID=keyID) gajim.contacts.add_contact(account, contact) @@ -2511,7 +2511,7 @@ class RosterWindow: account_name = account if gajim.account_is_connected(account): account_name += ' (%s/%s)' % (repr(nbr_on), repr(nbr_total)) - contact = gajim.contacts.create_contact(jid=jid, name=account_name, + contact = gajim.contacts.create_contact(jid=jid, account=account, name=account_name, show=connection.get_status(), sub='', status=connection.status, resource=connection.server_resource, priority=connection.priority, mood=connection.mood, @@ -5102,7 +5102,7 @@ class RosterWindow: service_discovery_menuitem.connect('activate', self.on_service_disco_menuitem_activate, account) hostname = gajim.config.get_per('accounts', account, 'hostname') - contact = gajim.contacts.create_contact(jid=hostname) # Fake contact + contact = gajim.contacts.create_contact(jid=hostname, account=account) # Fake contact execute_command_menuitem.connect('activate', self.on_execute_command, contact, account) diff --git a/src/search_window.py b/src/search_window.py index 3f7f40bd0..e383e7c4f 100644 --- a/src/search_window.py +++ b/src/search_window.py @@ -110,7 +110,7 @@ class SearchWindow: if jid in gajim.interface.instances[self.account]['infos']: gajim.interface.instances[self.account]['infos'][jid].window.present() else: - contact = gajim.contacts.create_contact(jid = jid, name='', groups=[], + contact = gajim.contacts.create_contact(jid=jid, account=self.account, name='', groups=[], show='', status='', sub='', ask='', resource='', priority=0, keyID='', our_chatstate=None, chatstate=None) gajim.interface.instances[self.account]['infos'][jid] = \ diff --git a/src/session.py b/src/session.py index dec454c18..9143e22a2 100644 --- a/src/session.py +++ b/src/session.py @@ -506,7 +506,7 @@ class ChatControlSession(stanza_session.EncryptedStanzaSession): contact = gajim.contacts.get_contact(account, self.jid, resource) if not contact: - contact = gajim.contacts.create_contact(jid=jid, + contact = gajim.contacts.create_contact(jid=jid, account=account, resource=resource, show=self.conn.get_status()) gajim.interface.new_chat(contact, account, resource=resource, diff --git a/test/unit/test_contacts.py b/test/unit/test_contacts.py index 401f35620..623fec1ad 100644 --- a/test/unit/test_contacts.py +++ b/test/unit/test_contacts.py @@ -6,7 +6,7 @@ import unittest import lib lib.setup_env() -from common.contacts import CommonContact, Contact, GC_Contact +from common.contacts import CommonContact, Contact, GC_Contact, Contacts from common.xmpp import NS_MUC from common import caps @@ -14,9 +14,9 @@ from common import caps class TestCommonContact(unittest.TestCase): def setUp(self): - self.contact = CommonContact(jid='', resource='', show='', status='', - name='', our_chatstate=None, composing_xep=None, chatstate=None, - client_caps=None) + self.contact = CommonContact(jid='', account="", resource='', show='', + status='', name='', our_chatstate=None, composing_xep=None, + chatstate=None, client_caps=None) def test_default_client_supports(self): ''' @@ -31,21 +31,76 @@ class TestCommonContact(unittest.TestCase): self.assertTrue(self.contact.supports(NS_MUC), msg="Must not backtrace on simple check for supported feature") + + class TestContact(TestCommonContact): def setUp(self): TestCommonContact.setUp(self) - self.contact = Contact() + self.contact = Contact(jid="test@gajim.org", account="account") + def test_attributes_available(self): + '''This test supports the migration from the old to the new contact + domain model by smoke testing that no attribute values are lost''' + + attributes = ["jid", "resource", "show", "status", "name", "our_chatstate", + "composing_xep", "chatstate", "client_caps", "priority", "sub"] + for attr in attributes: + self.assertTrue(hasattr(self.contact, attr), msg="expected: " + attr) + class TestGC_Contact(TestCommonContact): def setUp(self): TestCommonContact.setUp(self) - self.contact = GC_Contact() + self.contact = GC_Contact("confernce@gajim.org", "account") + + def test_attributes_available(self): + '''This test supports the migration from the old to the new contact + domain model by asserting no attributes have been lost''' + + attributes = ["jid", "resource", "show", "status", "name", "our_chatstate", + "composing_xep", "chatstate", "client_caps", "role", "room_jid"] + for attr in attributes: + self.assertTrue(hasattr(self.contact, attr), msg="expected: " + attr) +class TestContacts(unittest.TestCase): + + def setUp(self): + self.contacts = Contacts() + + def test_create_add_get_contact(self): + jid = 'test@gajim.org' + account = "account" + + contact = self.contacts.create_contact(jid=jid, account=account) + self.contacts.add_contact(account, contact) + + retrieved_contact = self.contacts.get_contact(account, jid) + self.assertEqual(contact, retrieved_contact, "Contact must be known") + + self.contacts.remove_contact(account, contact) + + retrieved_contact = self.contacts.get_contact(account, jid) + self.assertNotEqual(contact, retrieved_contact, + msg="Contact must not be known any longer") + + + def test_copy_contact(self): + jid = 'test@gajim.org' + account = "account" + + contact = self.contacts.create_contact(jid=jid, account=account) + copy = self.contacts.copy_contact(contact) + self.assertFalse(contact is copy, msg="Must not be the same") + + # Not yet implemented to remain backwart compatible + # self.assertEqual(contact, copy, msg="Must be equal") + + + if __name__ == "__main__": unittest.main() \ No newline at end of file