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