Merge changes from refactoring branch back to default

This commit is contained in:
Stephan Erb 2009-11-11 23:38:17 +01:00
commit 641947719f
23 changed files with 638 additions and 416 deletions

View File

@ -2774,7 +2774,7 @@ class ChatControl(ChatControlBase):
contact = gajim.contacts.get_contact_with_highest_priority(
self.account, self.contact.jid)
if isinstance(contact, GC_Contact):
contact = gajim.contacts.contact_from_gc_contact(contact)
contact = contact.as_contact()
if contact:
self.contact = contact
self.draw_banner()

32
src/common/account.py Normal file
View File

@ -0,0 +1,32 @@
# -*- coding:utf-8 -*-
## src/common/contacts.py
##
## Copyright (C) 2009 Stephan Erb <steve-e AT h3c.de>
##
## This file is part of Gajim.
##
## Gajim is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
## by the Free Software Foundation; version 3 only.
##
## Gajim is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
##
class Account(object):
def __init__(self, name, contacts, gc_contacts):
self.name = name
self.contacts = contacts
self.gc_contacts = gc_contacts
def __repr__(self):
return self.name
def __hash__(self):
return self.name.__hash__()

View File

@ -40,13 +40,34 @@ from common.xmpp import NS_XHTML_IM, NS_RECEIPTS, NS_ESESSION, NS_CHATSTATES
# Features where we cannot safely assume that the other side supports them
FEATURE_BLACKLIST = [NS_CHATSTATES, NS_XHTML_IM, NS_RECEIPTS, NS_ESESSION]
# Query entry status codes
NEW = 0
QUERIED = 1
CACHED = 2 # got the answer
################################################################################
### Public API of this module
################################################################################
capscache = None
def initialize(logger):
''' Initializes the capscache global '''
''' Initializes this module '''
global capscache
capscache = CapsCache(logger)
def client_supports(client_caps, requested_feature):
lookup_item = client_caps.get_cache_lookup_strategy()
cache_item = lookup_item(capscache)
supported_features = cache_item.features
if requested_feature in supported_features:
return True
elif supported_features == [] and cache_item.status in (NEW, QUERIED):
# assume feature is supported, if we don't know yet, what the client
# is capable of
return requested_feature not in FEATURE_BLACKLIST
else:
return False
def compute_caps_hash(identities, features, dataforms=[], hash_method='sha-1'):
'''Compute caps hash according to XEP-0115, V1.5
@ -118,6 +139,10 @@ def compute_caps_hash(identities, features, dataforms=[], hash_method='sha-1'):
return base64.b64encode(hash_.digest())
################################################################################
### Internal classes of this module
################################################################################
class AbstractClientCaps(object):
'''
Base class representing a client and its capabilities as advertised by
@ -147,8 +172,8 @@ class AbstractClientCaps(object):
def _is_hash_valid(self, identities, features, dataforms):
''' To be implemented by subclassess '''
raise NotImplementedError()
class ClientCaps(AbstractClientCaps):
''' The current XEP-115 implementation '''
@ -167,7 +192,7 @@ class ClientCaps(AbstractClientCaps):
computed_hash = compute_caps_hash(identities, features,
dataforms=dataforms, hash_method=self._hash_method)
return computed_hash == self._hash
class OldClientCaps(AbstractClientCaps):
''' Old XEP-115 implemtation. Kept around for background competability. '''
@ -183,7 +208,7 @@ class OldClientCaps(AbstractClientCaps):
def _is_hash_valid(self, identities, features, dataforms):
return True
class NullClientCaps(AbstractClientCaps):
'''
@ -199,7 +224,7 @@ class NullClientCaps(AbstractClientCaps):
def _lookup_in_cache(self, caps_cache):
# lookup something which does not exist to get a new CacheItem created
cache_item = caps_cache[('dummy', '')]
assert cache_item.queried != 2
assert cache_item.status != CACHED
return cache_item
def _discover(self, connection, jid):
@ -236,12 +261,8 @@ class CapsCache(object):
self._identities = []
self._logger = logger
# not cached into db:
# have we sent the query?
# 0 == not queried
# 1 == queried
# 2 == got the answer
self.queried = 0
self.status = NEW
self._recently_seen = False
def _get_features(self):
return self._features
@ -283,19 +304,28 @@ class CapsCache(object):
self.features = features
self._logger.add_caps_entry(self.hash_method, self.hash,
identities, features)
self.status = CACHED
def update_last_seen(self):
if not self._recently_seen:
self._recently_seen = True
self._logger.update_caps_time(self.hash_method, self.hash)
self.__CacheItem = CacheItem
self.logger = logger
def initialize_from_db(self):
# get data from logger...
if self.logger is not None:
for hash_method, hash_, identities, features in \
self.logger.iter_caps_data():
x = self[(hash_method, hash_)]
x.identities = identities
x.features = features
x.queried = 2
self._remove_outdated_caps()
for hash_method, hash_, identities, features in \
self.logger.iter_caps_data():
x = self[(hash_method, hash_)]
x.identities = identities
x.features = features
x.status = CACHED
def _remove_outdated_caps(self):
'''Removes outdated values from the db'''
self.logger.clean_caps_table()
def __getitem__(self, caps):
if caps in self.__cache:
@ -315,13 +345,18 @@ class CapsCache(object):
lookup_cache_item = client_caps.get_cache_lookup_strategy()
q = lookup_cache_item(self)
if q.queried == 0:
if q.status == NEW:
# do query for bare node+hash pair
# this will create proper object
q.queried = 1
q.status = QUERIED
discover = client_caps.get_discover_strategy()
discover(connection, jid)
else:
q.update_last_seen()
################################################################################
### Caps network coding
################################################################################
class ConnectionCaps(object):
'''
@ -366,7 +401,7 @@ class ConnectionCaps(object):
client_caps = OldClientCaps(caps_hash, node)
else:
client_caps = ClientCaps(caps_hash, node, hash_method)
capscache.query_client_of_jid_if_unknown(self, jid, client_caps)
contact.client_caps = client_caps
@ -384,7 +419,7 @@ class ConnectionCaps(object):
lookup = contact.client_caps.get_cache_lookup_strategy()
cache_item = lookup(capscache)
if cache_item.queried == 2:
if cache_item.status == CACHED:
return
else:
validate = contact.client_caps.get_hash_validation_strategy()

View File

@ -91,7 +91,8 @@ def create_log_db():
CREATE TABLE caps_cache (
hash_method TEXT,
hash TEXT,
data BLOB);
data BLOB,
last_seen INTEGER);
CREATE TABLE rooms_last_message_time(
jid_id INTEGER PRIMARY KEY UNIQUE,

View File

@ -2468,8 +2468,12 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
for sess in self.sessions[jid].values():
if not sess.received_thread_id:
contact = gajim.contacts.get_contact(self.name, jid)
session_supported = contact.supports(common.xmpp.NS_SSN) or \
# FIXME: I don't know if this is the correct behavior here.
# Anyway, it is the old behavior when we assumed that
# not-existing contacts don't support anything
contact_exists = bool(contact)
session_supported = contact_exists and \
contact.supports(common.xmpp.NS_SSN) or \
contact.supports(common.xmpp.NS_ESESSION)
if session_supported:
sess.terminate()

View File

@ -29,18 +29,24 @@
##
import common.gajim
import caps
from account import Account
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,
composing_xep, chatstate, client_caps=None):
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.show = show
self.status = status
self.name = name
@ -80,35 +86,21 @@ class CommonContact(object):
# return caps for a contact that has no resources left.
return False
else:
return self._client_supports(requested_feature)
def _client_supports(self, requested_feature):
lookup_item = self.client_caps.get_cache_lookup_strategy()
cache_item = lookup_item(caps.capscache)
supported_features = cache_item.features
if requested_feature in supported_features:
return True
elif supported_features == [] and cache_item.queried in (0, 1):
# assume feature is supported, if we don't know yet, what the client
# is capable of
return requested_feature not in caps.FEATURE_BLACKLIST
else:
return False
return caps.client_supports(self.client_caps, requested_feature)
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
self.groups = groups
self.groups = [i for i in set(groups)] # filter duplicate values
self.sub = sub
self.ask = ask
@ -184,11 +176,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
@ -201,153 +193,112 @@ class GC_Contact(CommonContact):
def get_shown_name(self):
return self.name
def as_contact(self):
'''Create a Contact instance from this GC_Contact instance'''
return Contact(jid=self.get_full_jid(), account=self.account,
resource=self.resource, name=self.name, groups=[], show=self.show,
status=self.status, sub='none', client_caps=self.client_caps)
class Contacts:
'''Information concerning all contacts and groupchat contacts'''
def __init__(self):
self._contacts = {} # list of contacts {acct: {jid1: [C1, C2]}, } one Contact per resource
self._gc_contacts = {} # list of contacts that are in gc {acct: {room_jid: {nick: C}}}
self._metacontact_manager = MetacontactManager(self)
self._accounts = {}
def change_account_name(self, old_name, new_name):
self._accounts[new_name] = self._accounts[old_name]
del self._accounts[old_name]
self._metacontact_manager.change_account_name(old_name, new_name)
# For meta contacts:
self._metacontacts_tags = {}
def change_account_name(self, old_name, new_name):
self._contacts[new_name] = self._contacts[old_name]
self._gc_contacts[new_name] = self._gc_contacts[old_name]
self._metacontacts_tags[new_name] = self._metacontacts_tags[old_name]
del self._contacts[old_name]
del self._gc_contacts[old_name]
del self._metacontacts_tags[old_name]
def change_contact_jid(self, old_jid, new_jid, account):
if account not in self._contacts:
return
if old_jid not in self._contacts[account]:
return
self._contacts[account][new_jid] = []
for _contact in self._contacts[account][old_jid]:
_contact.jid = new_jid
self._contacts[account][new_jid].append(_contact)
del self._contacts[account][old_jid]
def add_account(self, account):
self._contacts[account] = {}
self._gc_contacts[account] = {}
if account not in self._metacontacts_tags:
self._metacontacts_tags[account] = {}
def add_account(self, account_name):
self._accounts[account_name] = Account(account_name,
Contacts_New(), GC_Contacts())
self._metacontact_manager.add_account(account_name)
def get_accounts(self):
return self._contacts.keys()
return self._accounts.keys()
def remove_account(self, account):
del self._contacts[account]
del self._gc_contacts[account]
del self._metacontacts_tags[account]
del self._accounts[account]
self._metacontact_manager.remove_account(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={}):
# We don't want duplicated group values
groups_unique = []
for group in groups:
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,
account = self._accounts.get(account, account) # Use Account object if available
return Contact(jid=jid, account=account, name=name, groups=groups,
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 create_self_contact(self, jid, account, resource, show, status, priority, keyID=''):
conn = common.gajim.connections[account]
nick = common.gajim.nicks[account]
account = self._accounts.get(account, account) # Use Account object if available
return self.create_contact(jid=jid, account=account,
name=nick, groups=['self_contact'], show=show, status=status,
sub='both', ask='none', priority=priority, keyID=keyID,
resource=resource, mood=conn.mood, tune=conn.tune,
activity=conn.activity)
def create_not_in_roster_contact(self, jid, account, resource='', name='', keyID=''):
account = self._accounts.get(account, account) # Use Account object if available
return self.create_contact(jid=jid, account=account, resource=resource,
name=name, groups=[_('Not in Roster')], show='not in roster',
status='', sub='none', keyID=keyID)
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):
# No such account before ?
if account not in self._contacts:
self._contacts[account] = {contact.jid : [contact]}
return
# No such jid before ?
if contact.jid not in self._contacts[account]:
self._contacts[account][contact.jid] = [contact]
return
contacts = self._contacts[account][contact.jid]
# We had only one that was offline, remove it
if len(contacts) == 1 and contacts[0].show == 'offline':
# Do not use self.remove_contact: it deteles
# self._contacts[account][contact.jid]
contacts.remove(contacts[0])
# If same JID with same resource already exists, use the new one
for c in contacts:
if c.resource == contact.resource:
self.remove_contact(account, c)
break
contacts.append(contact)
if account not in self._accounts:
self.add_account(account)
return self._accounts[account].contacts.add_contact(contact)
def remove_contact(self, account, contact):
if account not in self._contacts:
if account not in self._accounts:
return
if contact.jid not in self._contacts[account]:
return
if contact in self._contacts[account][contact.jid]:
self._contacts[account][contact.jid].remove(contact)
if len(self._contacts[account][contact.jid]) == 0:
del self._contacts[account][contact.jid]
def clear_contacts(self, account):
self._contacts[account] = {}
return self._accounts[account].contacts.remove_contact(contact)
def remove_jid(self, account, jid, remove_meta=True):
'''Removes all contacts for a given jid'''
if account not in self._contacts:
return
if jid not in self._contacts[account]:
return
del self._contacts[account][jid]
self._accounts[account].contacts.remove_jid(jid)
if remove_meta:
# remove metacontacts info
self.remove_metacontact(account, jid)
self._metacontact_manager.remove_metacontact(account, jid)
def get_contacts(self, account, jid):
'''Returns the list of contact instances for this jid.'''
if jid in self._contacts[account]:
return self._contacts[account][jid]
else:
return []
return self._accounts[account].contacts.get_contacts(jid)
def get_contact(self, account, jid, resource=None):
### WARNING ###
# This function returns a *RANDOM* resource if resource = None!
# Do *NOT* use if you need to get the contact to which you
# send a message for example, as a bare JID in Jabber means
# highest available resource, which this function ignores!
'''Returns the contact instance for the given resource if it's given else
the first contact is no resource is given or None if there is not'''
if jid in self._contacts[account]:
if not resource:
return self._contacts[account][jid][0]
for c in self._contacts[account][jid]:
if c.resource == resource:
return c
return None
return self._accounts[account].contacts.get_contact(jid, resource=resource)
def iter_contacts(self, account):
if account in self._contacts:
for jid in self._contacts[account].keys():
for contact in self._contacts[account][jid][:]:
yield contact
for contact in self._accounts[account].contacts.iter_contacts():
yield contact
def get_contact_from_full_jid(self, account, fjid):
''' Get Contact object for specific resource of given jid'''
barejid, resource = common.gajim.get_room_and_nick_from_fjid(fjid)
return self.get_contact(account, barejid, resource)
return self._accounts[account].contacts.get_contact_from_full_jid(fjid)
def get_first_contact_from_jid(self, account, jid):
return self._accounts[account].contacts.get_first_contact_from_jid(jid)
def get_contacts_from_group(self, account, group):
return self._accounts[account].contacts.get_contacts_from_group(group)
def get_jid_list(self, account):
return self._accounts[account].contacts.get_jid_list()
def change_contact_jid(self, old_jid, new_jid, account):
return self._accounts[account].change_contact_jid(old_jid, new_jid)
def get_highest_prio_contact_from_contacts(self, contacts):
if not contacts:
@ -366,21 +317,7 @@ class Contacts:
contact = self.get_gc_contact(account, room, nick)
return contact
return self.get_highest_prio_contact_from_contacts(contacts)
def get_first_contact_from_jid(self, account, jid):
if jid in self._contacts[account]:
return self._contacts[account][jid][0]
return None
def get_contacts_from_group(self, account, group):
'''Returns all contacts in the given group'''
group_contacts = []
for jid in self._contacts[account]:
contacts = self.get_contacts(account, jid)
if group in contacts[0].groups:
group_contacts += contacts
return group_contacts
def get_nb_online_total_contacts(self, accounts=[], groups=[]):
'''Returns the number of online contacts and the total number of
contacts'''
@ -419,11 +356,227 @@ class Contacts:
nbr_total += 1
return nbr_online, nbr_total
def is_pm_from_jid(self, account, jid):
'''Returns True if the given jid is a private message jid'''
if jid in self._contacts[account]:
return False
return True
def is_pm_from_contact(self, account, contact):
'''Returns True if the given contact is a private message contact'''
if isinstance(contact, Contact):
return False
return True
def __getattr__(self, attr_name):
# Only called if self has no attr_name
if hasattr(self._metacontact_manager, attr_name):
return getattr(self._metacontact_manager, attr_name)
else:
raise AttributeError(attr_name)
def create_gc_contact(self, room_jid, account, name='', show='', status='',
role='', affiliation='', jid='', resource=''):
account = self._accounts.get(account, account) # Use Account object if available
return GC_Contact(room_jid, account, name, show, status, role, affiliation, jid,
resource)
def add_gc_contact(self, account, gc_contact):
return self._accounts[account].gc_contacts.add_gc_contact(gc_contact)
def remove_gc_contact(self, account, gc_contact):
return self._accounts[account].gc_contacts.remove_gc_contact(gc_contact)
def remove_room(self, account, room_jid):
return self._accounts[account].gc_contacts.remove_room(room_jid)
def get_gc_list(self, account):
return self._accounts[account].gc_contacts.get_gc_list()
def get_nick_list(self, account, room_jid):
return self._accounts[account].gc_contacts.get_nick_list(room_jid)
def get_gc_contact(self, account, room_jid, nick):
return self._accounts[account].gc_contacts.get_gc_contact(room_jid, nick)
def get_nb_role_total_gc_contacts(self, account, room_jid, role):
return self._accounts[account].gc_contacts.get_nb_role_total_gc_contacts(room_jid, role)
class Contacts_New():
def __init__(self):
# list of contacts {jid1: [C1, C2]}, } one Contact per resource
self._contacts = {}
def add_contact(self, contact):
if contact.jid not in self._contacts:
self._contacts[contact.jid] = [contact]
return
contacts = self._contacts[contact.jid]
# We had only one that was offline, remove it
if len(contacts) == 1 and contacts[0].show == 'offline':
# Do not use self.remove_contact: it deteles
# self._contacts[account][contact.jid]
contacts.remove(contacts[0])
# If same JID with same resource already exists, use the new one
for c in contacts:
if c.resource == contact.resource:
self.remove_contact(c)
break
contacts.append(contact)
def remove_contact(self, contact):
if contact.jid not in self._contacts:
return
if contact in self._contacts[contact.jid]:
self._contacts[contact.jid].remove(contact)
if len(self._contacts[contact.jid]) == 0:
del self._contacts[contact.jid]
def remove_jid(self, jid):
'''Removes all contacts for a given jid'''
if jid not in self._contacts:
return
del self._contacts[jid]
def get_contacts(self, jid):
'''Returns the list of contact instances for this jid.'''
if jid in self._contacts:
return self._contacts[jid]
else:
return []
def get_contact(self, jid, resource=None):
### WARNING ###
# This function returns a *RANDOM* resource if resource = None!
# Do *NOT* use if you need to get the contact to which you
# send a message for example, as a bare JID in Jabber means
# highest available resource, which this function ignores!
'''Returns the contact instance for the given resource if it's given else
the first contact is no resource is given or None if there is not'''
if jid in self._contacts:
if not resource:
return self._contacts[jid][0]
for c in self._contacts[jid]:
if c.resource == resource:
return c
return None
def iter_contacts(self):
for jid in self._contacts.keys():
for contact in self._contacts[jid][:]:
yield contact
def get_jid_list(self):
return self._contacts.keys()
def get_contact_from_full_jid(self, fjid):
''' Get Contact object for specific resource of given jid'''
barejid, resource = common.gajim.get_room_and_nick_from_fjid(fjid)
return self.get_contact(barejid, resource)
def get_first_contact_from_jid(self, jid):
if jid in self._contacts:
return self._contacts[jid][0]
return None
def get_contacts_from_group(self, group):
'''Returns all contacts in the given group'''
group_contacts = []
for jid in self._contacts:
contacts = self.get_contacts(jid)
if group in contacts[0].groups:
group_contacts += contacts
return group_contacts
def change_contact_jid(self, old_jid, new_jid):
if old_jid not in self._contacts:
return
self._contacts[new_jid] = []
for _contact in self._contacts[old_jid]:
_contact.jid = new_jid
self._contacts[new_jid].append(_contact)
del self._contacts[old_jid]
class GC_Contacts():
def __init__(self):
# list of contacts that are in gc {room_jid: {nick: C}}}
self._rooms = {}
def add_gc_contact(self, gc_contact):
if gc_contact.room_jid not in self._rooms:
self._rooms[gc_contact.room_jid] = {gc_contact.name: gc_contact}
else:
self._rooms[gc_contact.room_jid][gc_contact.name] = gc_contact
def remove_gc_contact(self, gc_contact):
if gc_contact.room_jid not in self._rooms:
return
if gc_contact.name not in self._rooms[gc_contact.room_jid]:
return
del self._rooms[gc_contact.room_jid][gc_contact.name]
# It was the last nick in room ?
if not len(self._rooms[gc_contact.room_jid]):
del self._rooms[gc_contact.room_jid]
def remove_room(self, room_jid):
if room_jid not in self._rooms:
return
del self._rooms[room_jid]
def get_gc_list(self):
return self._rooms.keys()
def get_nick_list(self, room_jid):
gc_list = self.get_gc_list()
if not room_jid in gc_list:
return []
return self._rooms[room_jid].keys()
def get_gc_contact(self, room_jid, nick):
nick_list = self.get_nick_list(room_jid)
if not nick in nick_list:
return None
return self._rooms[room_jid][nick]
def get_nb_role_total_gc_contacts(self, room_jid, role):
'''Returns the number of group chat contacts for the given role and the
total number of group chat contacts'''
if room_jid not in self._rooms:
return 0, 0
nb_role = nb_total = 0
for nick in self._rooms[room_jid]:
if self._rooms[room_jid][nick].role == role:
nb_role += 1
nb_total += 1
return nb_role, nb_total
class MetacontactManager():
def __init__(self, contacts):
self._metacontacts_tags = {}
self._contacts = contacts
def change_account_name(self, old_name, new_name):
self._metacontacts_tags[new_name] = self._metacontacts_tags[old_name]
del self._metacontacts_tags[old_name]
def add_account(self, account):
if account not in self._metacontacts_tags:
self._metacontacts_tags[account] = {}
def remove_account(self, account):
del self._metacontacts_tags[account]
def define_metacontacts(self, account, tags_list):
self._metacontacts_tags[account] = tags_list
def get_new_metacontacts_tag(self, jid):
if not jid in self._metacontacts_tags.keys():
def _get_new_metacontacts_tag(self, jid):
if not jid in self._metacontacts_tags:
return jid
#FIXME: can this append ?
assert False
@ -434,7 +587,7 @@ class Contacts:
return []
return self._metacontacts_tags[account].keys()
def get_metacontacts_tag(self, account, jid):
def _get_metacontacts_tag(self, account, jid):
'''Returns the tag of a jid'''
if not account in self._metacontacts_tags:
return None
@ -445,19 +598,19 @@ class Contacts:
return None
def add_metacontact(self, brother_account, brother_jid, account, jid, order=None):
tag = self.get_metacontacts_tag(brother_account, brother_jid)
tag = self._get_metacontacts_tag(brother_account, brother_jid)
if not tag:
tag = self.get_new_metacontacts_tag(brother_jid)
tag = self._get_new_metacontacts_tag(brother_jid)
self._metacontacts_tags[brother_account][tag] = [{'jid': brother_jid,
'tag': tag}]
if brother_account != account:
common.gajim.connections[brother_account].store_metacontacts(
self._metacontacts_tags[brother_account])
# be sure jid has no other tag
old_tag = self.get_metacontacts_tag(account, jid)
old_tag = self._get_metacontacts_tag(account, jid)
while old_tag:
self.remove_metacontact(account, jid)
old_tag = self.get_metacontacts_tag(account, jid)
old_tag = self._get_metacontacts_tag(account, jid)
if tag not in self._metacontacts_tags[account]:
self._metacontacts_tags[account][tag] = [{'jid': jid, 'tag': tag}]
else:
@ -471,6 +624,9 @@ class Contacts:
self._metacontacts_tags[account])
def remove_metacontact(self, account, jid):
if not account in self._metacontacts_tags:
return None
found = None
for tag in self._metacontacts_tags[account]:
for data in self._metacontacts_tags[account][tag]:
@ -484,7 +640,7 @@ class Contacts:
break
def has_brother(self, account, jid, accounts):
tag = self.get_metacontacts_tag(account, jid)
tag = self._get_metacontacts_tag(account, jid)
if not tag:
return False
meta_jids = self.get_metacontacts_jids(tag, accounts)
@ -516,7 +672,7 @@ class Contacts:
'''return the family of the given jid, including jid in the form:
[{'account': acct, 'jid': jid, 'order': order}, ]
'order' is optional'''
tag = self.get_metacontacts_tag(account, jid)
tag = self._get_metacontacts_tag(account, jid)
return self.get_metacontacts_family_from_tag(account, tag)
def get_metacontacts_family_from_tag(self, account, tag):
@ -530,7 +686,7 @@ class Contacts:
answers.append(data)
return answers
def compare_metacontacts(self, data1, data2):
def _compare_metacontacts(self, data1, data2):
'''compare 2 metacontacts.
Data is {'jid': jid, 'account': account, 'order': order}
order is optional'''
@ -538,8 +694,8 @@ class Contacts:
jid2 = data2['jid']
account1 = data1['account']
account2 = data2['account']
contact1 = self.get_contact_with_highest_priority(account1, jid1)
contact2 = self.get_contact_with_highest_priority(account2, jid2)
contact1 = self._contacts.get_contact_with_highest_priority(account1, jid1)
contact2 = self._contacts.get_contact_with_highest_priority(account2, jid2)
show_list = ['not in roster', 'error', 'offline', 'invisible', 'dnd',
'xa', 'away', 'chat', 'online', 'requested', 'message']
# contact can be null when a jid listed in the metacontact data
@ -613,98 +769,7 @@ class Contacts:
def get_metacontacts_big_brother(self, family):
'''which of the family will be the big brother under wich all
others will be ?'''
family.sort(cmp=self.compare_metacontacts)
family.sort(cmp=self._compare_metacontacts)
return family[-1]
def is_pm_from_jid(self, account, jid):
'''Returns True if the given jid is a private message jid'''
if jid in self._contacts[account]:
return False
return True
def is_pm_from_contact(self, account, contact):
'''Returns True if the given contact is a private message contact'''
if isinstance(contact, Contact):
return False
return True
def get_jid_list(self, account):
return self._contacts[account].keys()
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,
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='',
role='', affiliation='', jid='', resource=''):
return GC_Contact(room_jid, name, show, status, role, affiliation, jid,
resource)
def add_gc_contact(self, account, gc_contact):
# No such account before ?
if account not in self._gc_contacts:
self._contacts[account] = {gc_contact.room_jid : {gc_contact.name: \
gc_contact}}
return
# No such room_jid before ?
if gc_contact.room_jid not in self._gc_contacts[account]:
self._gc_contacts[account][gc_contact.room_jid] = {gc_contact.name: \
gc_contact}
return
self._gc_contacts[account][gc_contact.room_jid][gc_contact.name] = \
gc_contact
def remove_gc_contact(self, account, gc_contact):
if account not in self._gc_contacts:
return
if gc_contact.room_jid not in self._gc_contacts[account]:
return
if gc_contact.name not in self._gc_contacts[account][
gc_contact.room_jid]:
return
del self._gc_contacts[account][gc_contact.room_jid][gc_contact.name]
# It was the last nick in room ?
if not len(self._gc_contacts[account][gc_contact.room_jid]):
del self._gc_contacts[account][gc_contact.room_jid]
def remove_room(self, account, room_jid):
if account not in self._gc_contacts:
return
if room_jid not in self._gc_contacts[account]:
return
del self._gc_contacts[account][room_jid]
def get_gc_list(self, account):
if account not in self._gc_contacts:
return []
return self._gc_contacts[account].keys()
def get_nick_list(self, account, room_jid):
gc_list = self.get_gc_list(account)
if not room_jid in gc_list:
return []
return self._gc_contacts[account][room_jid].keys()
def get_gc_contact(self, account, room_jid, nick):
nick_list = self.get_nick_list(account, room_jid)
if not nick in nick_list:
return None
return self._gc_contacts[account][room_jid][nick]
def get_nb_role_total_gc_contacts(self, account, room_jid, role):
'''Returns the number of group chat contacts for the given role and the
total number of group chat contacts'''
if account not in self._gc_contacts:
return 0, 0
if room_jid not in self._gc_contacts[account]:
return 0, 0
nb_role = nb_total = 0
for nick in self._gc_contacts[account][room_jid]:
if self._gc_contacts[account][room_jid][nick].role == role:
nb_role += 1
nb_total += 1
return nb_role, nb_total
# vim: se ts=3:

View File

@ -27,7 +27,7 @@ docdir = '../'
datadir = '../'
localedir = '../po'
version = '0.12.5.8-dev'
version = '0.13.0.1-dev'
import sys, os.path
for base in ('.', 'common'):

View File

@ -838,14 +838,27 @@ class Logger:
gzip.close()
data = string.getvalue()
self.cur.execute('''
INSERT INTO caps_cache ( hash_method, hash, data )
VALUES (?, ?, ?);
''', (hash_method, hash_, buffer(data))) # (1) -- note above
INSERT INTO caps_cache ( hash_method, hash, data, last_seen )
VALUES (?, ?, ?, ?);
''', (hash_method, hash_, buffer(data), int(time.time())))
# (1) -- note above
try:
self.con.commit()
except sqlite.OperationalError, e:
print >> sys.stderr, str(e)
def update_caps_time(self, method, hash_):
sql = '''UPDATE caps_cache SET last_seen = %d
WHERE hash_method = "%s" and hash = "%s"''' % \
(int(time.time()), method, hash_)
self.simple_commit(sql)
def clean_caps_table(self):
'''Remove caps which was not seen for 3 months'''
sql = '''DELETE FROM caps_cache WHERE last_seen < %d''' % \
int(time.time() - 3*30*24*3600)
self.simple_commit(sql)
def replace_roster(self, account_name, roster_version, roster):
''' Replace current roster in DB by a new one.
accout_name is the name of the account to change

View File

@ -1,36 +0,0 @@
#!/usr/bin/python
import types
class VerboseClassType(type):
indent = ''
def __init__(cls, name, bases, dict):
super(VerboseClassType, cls).__init__(cls, name, bases, dict)
new = {}
print 'Initializing new class %s:' % cls
for fname, fun in dict.iteritems():
wrap = hasattr(fun, '__call__')
print '%s%s is %s, we %s wrap it.' % \
(cls.__class__.indent, fname, fun, wrap and 'will' or "won't")
if not wrap: continue
setattr(cls, fname, cls.wrap(name, fname, fun))
def wrap(cls, name, fname, fun):
def verbose(*a, **b):
args = ', '.join(map(repr, a)+map(lambda x:'%s=%r'%x, b.iteritems()))
print '%s%s.%s(%s):' % (cls.__class__.indent, name, fname, args)
cls.__class__.indent += '| '
r = fun(*a, **b)
cls.__class__.indent = cls.__class__.indent[:-4]
print '%s+=%r' % (cls.__class__.indent, r)
return r
verbose.__name__ = fname
return verbose
def nested_property(f):
ret = f()
p = {}
for v in ('fget', 'fset', 'fdel', 'doc'):
if v in ret: p[v]=ret[v]
return property(**p)

View File

@ -29,6 +29,7 @@
import os
import locale
import re
from time import time
from common import gajim
from common import helpers
from common import caps
@ -218,6 +219,8 @@ class OptionsParser:
self.update_config_to_01257()
if old < [0, 12, 5, 8] and new >= [0, 12, 5, 8]:
self.update_config_to_01258()
if old < [0, 13, 0, 1] and new >= [0, 13, 0, 1]:
self.update_config_to_01301()
gajim.logger.init_vars()
gajim.config.set('version', new_version)
@ -817,4 +820,23 @@ class OptionsParser:
'proxy.jabber.ru', 'proxy.jabbim.cz'])
gajim.config.set('version', '0.12.5.8')
def update_config_to_01301(self):
back = os.getcwd()
os.chdir(logger.LOG_DB_FOLDER)
con = sqlite.connect(logger.LOG_DB_FILE)
os.chdir(back)
cur = con.cursor()
try:
cur.executescript(
'''
ALTER TABLE caps_cache
ADD last_seen INTEGER default %d;
''' % int(time())
)
con.commit()
except sqlite.OperationalError:
pass
con.close()
gajim.config.set('version', '0.13.0.1')
# vim: se ts=3:

View File

@ -1888,9 +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='',
groups=[], show='', status='', sub='', ask='', resource='',
priority=5, keyID='', our_chatstate=None, chatstate=None)
contact = gajim.contacts.create_contact(jid=self.jid, account=self.account)
gajim.interface.instances[self.account]['infos'][self.jid] = \
vcard.VcardWindow(contact, self.account)
# Remove jabber page

View File

@ -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)

View File

@ -176,7 +176,7 @@ class PrivateChatControl(ChatControl):
ChatControl.update_ui(self)
def update_contact(self):
self.contact = gajim.contacts.contact_from_gc_contact(self.gc_contact)
self.contact = self.gc_contact.as_contact()
def begin_e2e_negotiation(self):
self.no_autonegotiation = True
@ -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)
@ -2254,14 +2254,14 @@ class GroupchatControl(ChatControlBase):
def on_info(self, widget, nick):
'''Call vcard_information_window class to display user's information'''
c = gajim.contacts.get_gc_contact(self.account, self.room_jid, nick)
c2 = gajim.contacts.contact_from_gc_contact(c)
if c2.jid in gajim.interface.instances[self.account]['infos']:
gajim.interface.instances[self.account]['infos'][c2.jid].window.\
gc_contact = gajim.contacts.get_gc_contact(self.account, self.room_jid, nick)
contact = gc_contact.as_contact()
if contact.jid in gajim.interface.instances[self.account]['infos']:
gajim.interface.instances[self.account]['infos'][contact.jid].window.\
present()
else:
gajim.interface.instances[self.account]['infos'][c2.jid] = \
vcard.VcardWindow(c2, self.account, c)
gajim.interface.instances[self.account]['infos'][contact.jid] = \
vcard.VcardWindow(contact, self.account, gc_contact)
def on_history(self, widget, nick):
jid = gajim.construct_fjid(self.room_jid, nick)

View File

@ -352,11 +352,9 @@ class Interface:
# Ignore offline presence of unknown self resource
if new_show < 2:
return
contact1 = gajim.contacts.create_contact(jid=ji,
name=gajim.nicks[account], groups=['self_contact'],
show=array[1], status=status_message, sub='both', ask='none',
priority=priority, keyID=keyID, resource=resource,
mood=conn.mood, tune=conn.tune, activity=conn.activity)
contact1 = gajim.contacts.create_self_contact(jid=ji,
account=account, show=array[1], status=status_message,
priority=priority, keyID=keyID, resource=resource)
old_show = 0
gajim.contacts.add_contact(account, contact1)
lcontact.append(contact1)
@ -541,8 +539,8 @@ class Interface:
show = model[iter_][3]
else:
show = 'offline'
gc_c = gajim.contacts.create_gc_contact(room_jid = jid,
name = nick, show = show)
gc_c = gajim.contacts.create_gc_contact(room_jid=jid, account=account,
name=nick, show=show)
ctrl = self.new_private_chat(gc_c, account, session)
ctrl.print_conversation(_('Error %(code)s: %(msg)s') % {
@ -620,8 +618,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)
@ -898,7 +896,7 @@ class Interface:
ctrl.print_conversation(_('%(nick)s is now known as %(new_nick)s') \
% {'nick': nick, 'new_nick': new_nick}, 'status')
gc_c = gajim.contacts.get_gc_contact(account, room_jid, new_nick)
c = gajim.contacts.contact_from_gc_contact(gc_c)
c = gc_c.as_contact()
ctrl.gc_contact = gc_c
ctrl.contact = c
if ctrl.session:
@ -1221,8 +1219,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:
@ -1361,9 +1359,8 @@ 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='',
groups=[_('Not in Roster')], show='not in roster', status='',
sub='none', keyID=keyID)
contact = gajim.contacts.create_not_in_roster_contact(jid=jid,
account=account, keyID=keyID)
gajim.contacts.add_contact(account, contact)
self.roster.add_contact(contact.jid, account)
file_props = array[1]
@ -2233,7 +2230,7 @@ class Interface:
else:
show = 'offline'
gc_contact = gajim.contacts.create_gc_contact(
room_jid = room_jid, name = nick, show = show)
room_jid=room_jid, account=account, name=nick, show=show)
if not session:
session = gajim.connections[account].make_new_session(
@ -2577,7 +2574,8 @@ class Interface:
account):
# Join new groupchat
if minimize:
contact = gajim.contacts.create_contact(jid=room_jid, name=nick)
#GCMIN
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)
@ -2600,7 +2598,8 @@ 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)
# GCMIN
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,
@ -2610,7 +2609,7 @@ class Interface:
mw.new_tab(gc_control)
def new_private_chat(self, gc_contact, account, session=None):
contact = gajim.contacts.contact_from_gc_contact(gc_contact)
contact = gc_contact.as_contact()
type_ = message_control.TYPE_PM
fjid = gc_contact.room_jid + '/' + gc_contact.name

View File

@ -688,9 +688,7 @@ class RosterWindow:
is_observer = contact.is_observer()
if is_observer:
# if he has a tag, remove it
tag = gajim.contacts.get_metacontacts_tag(account, jid)
if tag:
gajim.contacts.remove_metacontact(account, jid)
gajim.contacts.remove_metacontact(account, jid)
# Add contact to roster
family = gajim.contacts.get_metacontacts_family(account, jid)
@ -822,7 +820,8 @@ class RosterWindow:
else:
name = jid.split('@')[0]
# New groupchat
contact = gajim.contacts.create_contact(jid=jid, name=name,
#GCMIN
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)
@ -857,7 +856,8 @@ 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,
#TRANSP
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)
@ -998,9 +998,8 @@ 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,
groups=[_('Not in Roster')], show='not in roster', status='',
sub='none', resource=resource, keyID=keyID)
contact = gajim.contacts.create_not_in_roster_contact(jid=jid,
account=account, resource=resource, name=nick, keyID=keyID)
gajim.contacts.add_contact(account, contact)
self.add_contact(contact.jid, account)
return contact
@ -1788,7 +1787,8 @@ class RosterWindow:
if gajim.jid_is_transport(jid):
array[jid]['groups'] = [_('Transports')]
contact1 = gajim.contacts.create_contact(jid=ji, name=name,
#TRANSP - potential
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)
@ -1935,7 +1935,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)
@ -2525,7 +2525,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,
@ -2554,11 +2554,10 @@ class RosterWindow:
show = roster.getShow(jid+'/'+resource)
if not show:
show = 'online'
contact = gajim.contacts.create_contact(jid=jid,
name=account, groups=['self_contact'], show=show,
status=roster.getStatus(jid + '/' + resource),
resource=resource,
priority=roster.getPriority(jid + '/' + resource))
contact = gajim.contacts.create_self_contact(jid=jid,
account=account, show=show, status=roster.getStatus(jid + '/' + resource),
priority=roster.getPriority(jid + '/' + resource),
resource=resource)
contacts.append(contact)
if self.tooltip.timeout == 0 or self.tooltip.id != props[0]:
self.tooltip.id = row
@ -5116,7 +5115,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)

View File

@ -110,9 +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=[],
show='', status='', sub='', ask='', resource='', priority=0,
keyID='', our_chatstate=None, chatstate=None)
contact = gajim.contacts.create_contact(jid=jid, account=self.account)
gajim.interface.instances[self.account]['infos'][jid] = \
vcard.VcardWindow(contact, self.account)

View File

@ -203,7 +203,8 @@ class ChatControlSession(stanza_session.EncryptedStanzaSession):
if not contact:
# contact is not in the roster, create a fake one to display
# notification
contact = contacts.Contact(jid=jid, resource=resource)
contact = gajim.contacts.create_not_in_roster_contact(jid=jid,
account=self.conn.name, resource=resource)
advanced_notif_num = notify.get_advanced_notification('message_received',
self.conn.name, contact)
@ -506,7 +507,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,

View File

@ -7,6 +7,7 @@ import lib
lib.setup_env()
from common import gajim
from common import contacts as contacts_module
from gajim import Interface
from gajim_mocks import *
@ -25,6 +26,9 @@ class TestStatusChange(unittest.TestCase):
'''tests gajim.py's incredibly complex handle_event_notify'''
def setUp(self):
gajim.connections = {}
gajim.contacts = contacts_module.Contacts()
gajim.interface.roster = roster_window.RosterWindow()
for acc in contacts:
@ -38,13 +42,6 @@ class TestStatusChange(unittest.TestCase):
self.assertEqual(0, len(notify.notifications))
def tearDown(self):
gajim.interface.roster.model.clear()
for acc in contacts:
gajim.contacts.clear_contacts(acc)
del gajim.interface.roster
notify.notifications = []
def contact_comes_online(self, account, jid, resource, prio):

View File

@ -9,15 +9,16 @@ from mock import Mock, expectParams
from gajim_mocks import *
from common import gajim
from common import contacts as contacts_module
import roster_window
gajim.get_jid_from_account = lambda acc: 'myjid@' + acc
class TestRosterWindow(unittest.TestCase):
def setUp(self):
gajim.interface = MockInterface()
self.roster = roster_window.RosterWindow()
self.C_NAME = roster_window.C_NAME
self.C_TYPE = roster_window.C_TYPE
@ -26,13 +27,13 @@ class TestRosterWindow(unittest.TestCase):
# Add after creating RosterWindow
# We want to test the filling explicitly
gajim.contacts = contacts_module.Contacts()
gajim.connections = {}
self.roster = roster_window.RosterWindow()
for acc in contacts:
gajim.connections[acc] = MockConnection(acc)
def tearDown(self):
self.roster.model.clear()
for acc in gajim.contacts.get_accounts():
gajim.contacts.clear_contacts(acc)
gajim.contacts.add_account(acc)
### Custom assertions
def assert_all_contacts_are_in_roster(self, acc):
@ -142,11 +143,6 @@ class TestRosterWindow(unittest.TestCase):
groups = contacts[acc][jid]['groups'] or ['General',]
# cleanup
self.roster.model.clear()
for acc in contacts:
gajim.contacts.clear_contacts(acc)
def test_fill_roster_model(self):
for acc in contacts:
self.roster.fill_contacts_and_groups_dicts(contacts[acc], acc)
@ -190,7 +186,7 @@ class TestRosterWindowMetaContacts(TestRosterWindowRegrouped):
self.test_fill_roster_model()
jid = u'coolstuff@gajim.org'
contact = gajim.contacts.create_contact(jid)
contact = gajim.contacts.create_contact(jid, account1)
gajim.contacts.add_contact(account1, contact)
self.roster.add_contact(jid, account1)
self.roster.chg_contact_status(contact, 'offline', '', account1)

View File

@ -41,6 +41,7 @@ modules = ( 'unit.test_xmpp_dispatcher_nb',
'unit.test_contacts',
'unit.test_gui_interface',
'unit.test_sessions',
'unit.test_account',
)
#modules = ()

21
test/unit/test_account.py Normal file
View File

@ -0,0 +1,21 @@
'''
Tests for Account classes
'''
import unittest
import lib
lib.setup_env()
from common.account import Account
class Test(unittest.TestCase):
def testInstantiate(self):
account = Account(name='MyAcc', contacts=None, gc_contacts=None)
self.assertEquals('MyAcc', account.name)
self.assertTrue(account.gc_contacts is None)
self.assertTrue(account.contacts is None)
if __name__ == "__main__":
unittest.main()

View File

@ -66,9 +66,9 @@ class TestCapsCache(CommonCapsTest):
def test_initialize_from_db(self):
''' Read cashed dummy data from db '''
self.assertEqual(self.cc[self.client_caps].queried, 0)
self.assertEqual(self.cc[self.client_caps].status, caps.NEW)
self.cc.initialize_from_db()
self.assertEqual(self.cc[self.client_caps].queried, 2)
self.assertEqual(self.cc[self.client_caps].status, caps.CACHED)
def test_preload_triggering_query(self):
''' Make sure that preload issues a disco '''
@ -113,25 +113,23 @@ class TestClientCaps(CommonCapsTest):
"http://gajim.org#m3P2WeXPMGVH2tZPe7yITnfY0Dw=")
def test_client_supports(self):
contact = Contact(client_caps=self.client_caps)
self.assertTrue(contact.supports(NS_PING),
self.assertTrue(caps.client_supports(self.client_caps, NS_PING),
msg="Assume supported, if we don't have caps")
self.assertFalse(contact.supports(NS_XHTML_IM),
self.assertFalse(caps.client_supports(self.client_caps, NS_XHTML_IM),
msg="Must not assume blacklisted feature is supported on default")
self.cc.initialize_from_db()
self.assertFalse(contact.supports(NS_PING),
self.assertFalse(caps.client_supports(self.client_caps, NS_PING),
msg="Must return false on unsupported feature")
self.assertTrue(contact.supports(NS_XHTML_IM),
self.assertTrue(caps.client_supports(self.client_caps, NS_XHTML_IM),
msg="Must return True on supported feature")
self.assertTrue(contact.supports(NS_MUC),
msg="Must return True on supported feature")
self.assertTrue(caps.client_supports(self.client_caps, NS_MUC),
msg="Must return True on supported feature")
class TestOldClientCaps(TestClientCaps):

View File

@ -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,99 @@ 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(room_jid="confernce@gajim.org", account="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")
def test_legacy_accounts_handling(self):
self.contacts.add_account("one")
self.contacts.add_account("two")
self.contacts.change_account_name("two", "old")
self.contacts.remove_account("one")
self.assertEqual(["old"], self.contacts.get_accounts())
def test_legacy_contacts_from_groups(self):
jid1 = "test1@gajim.org"
jid2 = "test2@gajim.org"
account = "account"
group = "GroupA"
contact1 = self.contacts.create_contact(jid=jid1, account=account,
groups=[group])
self.contacts.add_contact(account, contact1)
contact2 = self.contacts.create_contact(jid=jid2, account=account,
groups=[group])
self.contacts.add_contact(account, contact2)
self.assertEqual(2, len(self.contacts.get_contacts_from_group(account, group)))
self.assertEqual(0, len(self.contacts.get_contacts_from_group(account, '')))
if __name__ == "__main__":
unittest.main()