From cea7c66f7587d64611486aa8779c2050aff9ee6d Mon Sep 17 00:00:00 2001 From: Alexander Cherniuk Date: Thu, 26 Nov 2009 12:21:43 +0200 Subject: [PATCH] A portion of doc-string refactoring --- src/common/GnuPG.py | 8 +- src/common/GnuPGInterface.py | 62 +++++--- src/common/account.py | 8 +- src/common/atom.py | 53 ++++--- src/common/caps.py | 169 +++++++++++---------- src/common/commands.py | 42 ++++-- src/common/config.py | 9 +- src/common/configpaths.py | 4 +- src/common/connection.py | 230 +++++++++++++++++++--------- src/common/connection_handlers.py | 176 ++++++++++++++-------- src/common/contacts.py | 240 ++++++++++++++++++------------ 11 files changed, 637 insertions(+), 364 deletions(-) diff --git a/src/common/GnuPG.py b/src/common/GnuPG.py index f6d8e7e2b..64abe75ce 100644 --- a/src/common/GnuPG.py +++ b/src/common/GnuPG.py @@ -213,7 +213,9 @@ if gajim.HAVE_GPG: return self.get_keys(True) def _stripHeaderFooter(self, data): - """Remove header and footer from data""" + """ + Remove header and footer from data + """ if not data: return '' lines = data.split('\n') while lines[0] != '': @@ -229,7 +231,9 @@ if gajim.HAVE_GPG: return line def _addHeaderFooter(self, data, type_): - """Add header and footer from data""" + """ + Add header and footer from data + """ out = "-----BEGIN PGP %s-----\n" % type_ out = out + "Version: PGP\n" out = out + "\n" diff --git a/src/common/GnuPGInterface.py b/src/common/GnuPGInterface.py index d91f776e3..aa4a9eeee 100644 --- a/src/common/GnuPGInterface.py +++ b/src/common/GnuPGInterface.py @@ -21,7 +21,8 @@ ## along with Gajim. If not, see . ## -"""Interface to GNU Privacy Guard (GnuPG) +""" +Interface to GNU Privacy Guard (GnuPG) GnuPGInterface is a Python module to interface with GnuPG. It concentrates on interacting with GnuPG via filehandles, @@ -249,7 +250,8 @@ _fd_options = { 'passphrase': '--passphrase-fd', 'command': '--command-fd' } class GnuPG: - """Class instances represent GnuPG. + """ + Class instances represent GnuPG Instance attributes of a GnuPG object are: @@ -275,8 +277,10 @@ class GnuPG: self.options = Options() def run(self, gnupg_commands, args=None, create_fhs=None, attach_fhs=None): - """Calls GnuPG with the list of string commands gnupg_commands, - complete with prefixing dashes. + """ + Calls GnuPG with the list of string commands gnupg_commands, complete + with prefixing dashes + For example, gnupg_commands could be '["--sign", "--encrypt"]' Returns a GnuPGInterface.Process object. @@ -336,7 +340,6 @@ class GnuPG: is a FileObject connected to GnuPG's standard input, and can be written to. """ - if args is None: args = [] if create_fhs is None: create_fhs = [] if attach_fhs is None: attach_fhs = {} @@ -367,9 +370,10 @@ class GnuPG: def _attach_fork_exec(self, gnupg_commands, args, create_fhs, attach_fhs): - """This is like run(), but without the passphrase-helping - (note that run() calls this).""" - + """ + This is like run(), but without the passphrase-helping (note that run() + calls this) + """ process = Process() for fh_name in create_fhs + attach_fhs.keys(): @@ -404,7 +408,9 @@ class GnuPG: def _as_parent(self, process): - """Stuff run after forking in parent""" + """ + Stuff run after forking in parent + """ for k, p in process._pipes.items(): if not p.direct: os.close(p.child) @@ -417,7 +423,9 @@ class GnuPG: def _as_child(self, process, gnupg_commands, args): - """Stuff run after forking in child""" + """ + Stuff run after forking in child + """ # child for std in _stds: p = process._pipes[std] @@ -444,7 +452,10 @@ class GnuPG: class Pipe: - """simple struct holding stuff about pipes we use""" + """ + Simple struct holding stuff about pipes we use + """ + def __init__(self, parent, child, direct): self.parent = parent self.child = child @@ -452,7 +463,8 @@ class Pipe: class Options: - """Objects of this class encompass options passed to GnuPG. + """ + Objects of this class encompass options passed to GnuPG. This class is responsible for determining command-line arguments which are based on options. It can be said that a GnuPG object has-a Options object in its options attribute. @@ -522,7 +534,6 @@ class Options: >>> gnupg.options.get_args() ['--armor', '--recipient', 'Alice', '--recipient', 'Bob', '--no-secmem-warning'] """ - def __init__(self): # booleans self.armor = 0 @@ -558,12 +569,15 @@ class Options: self.extra_args = [] def get_args( self ): - """Generate a list of GnuPG arguments based upon attributes.""" - + """ + Generate a list of GnuPG arguments based upon attributes + """ return self.get_meta_args() + self.get_standard_args() + self.extra_args def get_standard_args( self ): - """Generate a list of standard, non-meta or extra arguments""" + """ + Generate a list of standard, non-meta or extra arguments + """ args = [] if self.homedir is not None: args.extend( [ '--homedir', self.homedir ] ) @@ -595,7 +609,9 @@ class Options: return args def get_meta_args( self ): - """Get a list of generated meta-arguments""" + """ + Get a list of generated meta-arguments + """ args = [] if self.meta_pgp_5_compatible: args.extend( [ '--compress-algo', '1', @@ -608,8 +624,9 @@ class Options: class Process: - """Objects of this class encompass properties of a GnuPG - process spawned by GnuPG.run(). + """ + Objects of this class encompass properties of a GnuPG process spawned by + GnuPG.run() # gnupg is a GnuPG object process = gnupg.run( [ '--decrypt' ], stdout = 1 ) @@ -637,9 +654,10 @@ class Process: self._waited = None def wait(self): - """Wait on the process to exit, allowing for child cleanup. - Will raise an IOError if the process exits non-zero.""" - + """ + Wait on the process to exit, allowing for child cleanup. Will raise an + IOError if the process exits non-zero + """ e = os.waitpid(self.pid, 0)[1] if e != 0: raise IOError, "GnuPG exited non-zero, with code %d" % (e << 8) diff --git a/src/common/account.py b/src/common/account.py index 1c080cad8..4db660165 100644 --- a/src/common/account.py +++ b/src/common/account.py @@ -19,14 +19,14 @@ ## 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__() \ No newline at end of file + return hash(self.name) diff --git a/src/common/atom.py b/src/common/atom.py index 18122e9d1..689df5cee 100644 --- a/src/common/atom.py +++ b/src/common/atom.py @@ -20,9 +20,11 @@ ## along with Gajim. If not, see . ## -''' Atom (rfc 4287) feed parser, used to read data from atom-over-pubsub transports +""" +Atom (rfc 4287) feed parser, used to read data from atom-over-pubsub transports and services. Very simple. Actually implements only atom:entry. Implement more features -if you need. ''' +if you need +""" # suggestion: rewrite functions that return dates to return standard python time tuples, # exteneded to contain timezone @@ -31,8 +33,11 @@ import xmpp import time class PersonConstruct(xmpp.Node, object): - ''' Not used for now, as we don't need authors/contributors in pubsub.com feeds. - They rarely exist there. ''' + """ + Not used for now, as we don't need authors/contributors in pubsub.com feeds. + They rarely exist there + """ + def __init__(self, node): ''' Create person construct from node. ''' xmpp.Node.__init__(self, node=node) @@ -60,15 +65,17 @@ class PersonConstruct(xmpp.Node, object): class Entry(xmpp.Node, object): def __init__(self, node=None): - ''' Create new atom entry object. ''' xmpp.Node.__init__(self, 'entry', node=node) def __repr__(self): return '' % self.getAttr('id') class OldEntry(xmpp.Node, object): - ''' Parser for feeds from pubsub.com. They use old Atom 0.3 format with - their extensions. ''' + """ + Parser for feeds from pubsub.com. They use old Atom 0.3 format with their + extensions + """ + def __init__(self, node=None): ''' Create new Atom 0.3 entry object. ''' xmpp.Node.__init__(self, 'entry', node=node) @@ -77,8 +84,10 @@ class OldEntry(xmpp.Node, object): return '' % self.getAttr('id') def get_feed_title(self): - ''' Returns title of feed, where the entry was created. The result is the feed name - concatenated with source-feed title. ''' + """ + Return title of feed, where the entry was created. The result is the feed + name concatenated with source-feed title + """ if self.parent is not None: main_feed = self.parent.getTagData('title') else: @@ -104,7 +113,9 @@ class OldEntry(xmpp.Node, object): which delivered this entry. ''') def get_feed_link(self): - ''' Get source link ''' + """ + Get source link + """ try: return self.getTag('feed').getTags('link',{'rel':'alternate'})[1].getData() except Exception: @@ -114,15 +125,19 @@ class OldEntry(xmpp.Node, object): ''' Link to main webpage of the feed. ''') def get_title(self): - ''' Get an entry's title. ''' + """ + Get an entry's title + """ return self.getTagData('title') title = property(get_title, None, None, ''' Entry's title. ''') def get_uri(self): - ''' Get the uri the entry points to (entry's first link element with rel='alternate' - or without rel attribute). ''' + """ + Get the uri the entry points to (entry's first link element with + rel='alternate' or without rel attribute) + """ for element in self.getTags('link'): if 'rel' in element.attrs and element.attrs['rel']!='alternate': continue try: @@ -135,12 +150,16 @@ class OldEntry(xmpp.Node, object): ''' URI that is pointed by the entry. ''') def get_updated(self): - ''' Get the time the entry was updated last time. This should be standarized, - but pubsub.com sends it in human-readable format. We won't try to parse it. - (Atom 0.3 uses the word «modified» for that). + """ + Get the time the entry was updated last time + + This should be standarized, but pubsub.com sends it in human-readable + format. We won't try to parse it. (Atom 0.3 uses the word «modified» for + that). If there's no time given in the entry, we try with - and elements. ''' + and elements. + """ for name in ('updated', 'modified', 'published', 'issued'): date = self.getTagData(name) if date is not None: break diff --git a/src/common/caps.py b/src/common/caps.py index f34dfcda4..489123fb8 100644 --- a/src/common/caps.py +++ b/src/common/caps.py @@ -23,13 +23,13 @@ ## along with Gajim. If not, see . ## -''' -Module containing all XEP-115 (Entity Capabilities) related classes +""" +Module containing all XEP-115 (Entity Capabilities) related classes Basic Idea: CapsCache caches features to hash relationships. The cache is queried -through ClientCaps objects which are hold by contact instances. -''' +through ClientCaps objects which are hold by contact instances. +""" import gajim import helpers @@ -54,7 +54,9 @@ CACHED = 2 # got the answer capscache = None def initialize(logger): - ''' Initializes this module ''' + """ + Initialize this module + """ global capscache capscache = CapsCache(logger) @@ -73,11 +75,12 @@ def client_supports(client_caps, requested_feature): return False def compute_caps_hash(identities, features, dataforms=[], hash_method='sha-1'): - '''Compute caps hash according to XEP-0115, V1.5 + """ + Compute caps hash according to XEP-0115, V1.5 dataforms are xmpp.DataForms objects as common.dataforms don't allow several - values without a field type list-multi''' - + values without a field type list-multi + """ def sort_identities_func(i1, i2): cat1 = i1['category'] cat2 = i2['category'] @@ -98,14 +101,14 @@ def compute_caps_hash(identities, features, dataforms=[], hash_method='sha-1'): if lang1 > lang2: return 1 return 0 - + def sort_dataforms_func(d1, d2): f1 = d1.getField('FORM_TYPE') f2 = d2.getField('FORM_TYPE') if f1 and f2 and (f1.getValue() < f2.getValue()): return -1 return 1 - + S = '' identities.sort(cmp=sort_identities_func) for i in identities: @@ -140,108 +143,119 @@ def compute_caps_hash(identities, features, dataforms=[], hash_method='sha-1'): else: return '' return base64.b64encode(hash_.digest()) - + ################################################################################ ### Internal classes of this module ################################################################################ class AbstractClientCaps(object): - ''' - Base class representing a client and its capabilities as advertised by - a caps tag in a presence. - ''' + """ + Base class representing a client and its capabilities as advertised by a + caps tag in a presence + """ def __init__(self, caps_hash, node): self._hash = caps_hash self._node = node - + def get_discover_strategy(self): return self._discover - + def _discover(self, connection, jid): - ''' To be implemented by subclassess ''' - raise NotImplementedError() - + """ + To be implemented by subclassess + """ + raise NotImplementedError + def get_cache_lookup_strategy(self): return self._lookup_in_cache - + def _lookup_in_cache(self, caps_cache): - ''' To be implemented by subclassess ''' - raise NotImplementedError() - + """ + To be implemented by subclassess + """ + raise NotImplementedError + def get_hash_validation_strategy(self): return self._is_hash_valid - + def _is_hash_valid(self, identities, features, dataforms): - ''' To be implemented by subclassess ''' - raise NotImplementedError() + """ + To be implemented by subclassess + """ + raise NotImplementedError class ClientCaps(AbstractClientCaps): - ''' The current XEP-115 implementation ''' - + """ + The current XEP-115 implementation + """ + def __init__(self, caps_hash, node, hash_method): AbstractClientCaps.__init__(self, caps_hash, node) assert hash_method != 'old' self._hash_method = hash_method - + def _lookup_in_cache(self, caps_cache): return caps_cache[(self._hash_method, self._hash)] - + def _discover(self, connection, jid): connection.discoverInfo(jid, '%s#%s' % (self._node, self._hash)) - + def _is_hash_valid(self, identities, features, dataforms): computed_hash = compute_caps_hash(identities, features, dataforms=dataforms, hash_method=self._hash_method) - return computed_hash == self._hash + return computed_hash == self._hash + - class OldClientCaps(AbstractClientCaps): - ''' Old XEP-115 implemtation. Kept around for background competability. ''' - + """ + Old XEP-115 implemtation. Kept around for background competability + """ + def __init__(self, caps_hash, node): AbstractClientCaps.__init__(self, caps_hash, node) def _lookup_in_cache(self, caps_cache): return caps_cache[('old', self._node + '#' + self._hash)] - + def _discover(self, connection, jid): connection.discoverInfo(jid) - - def _is_hash_valid(self, identities, features, dataforms): - return True - + def _is_hash_valid(self, identities, features, dataforms): + return True + + class NullClientCaps(AbstractClientCaps): - ''' + """ This is a NULL-Object to streamline caps handling if a client has not - advertised any caps or has advertised them in an improper way. - + advertised any caps or has advertised them in an improper way + Assumes (almost) everything is supported. - ''' - + """ + def __init__(self): AbstractClientCaps.__init__(self, None, None) - + 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.status != CACHED return cache_item - + def _discover(self, connection, jid): pass def _is_hash_valid(self, identities, features, dataforms): - return False + return False class CapsCache(object): - ''' - This object keeps the mapping between caps data and real disco - features they represent, and provides simple way to query that info. - ''' + """ + This object keeps the mapping between caps data and real disco features they + represent, and provides simple way to query that info + """ + def __init__(self, logger=None): # our containers: # __cache is a dictionary mapping: pair of hash method and hash maps @@ -255,7 +269,7 @@ class CapsCache(object): # another object, and we will have plenty of identical long # strings. therefore we can cache them __names = {} - + def __init__(self, hash_method, hash_, logger): # cached into db self.hash_method = hash_method @@ -274,7 +288,7 @@ class CapsCache(object): self._features = [] for feature in value: self._features.append(self.__names.setdefault(feature, feature)) - + features = property(_get_features, _set_features) def _get_identities(self): @@ -291,7 +305,7 @@ class CapsCache(object): d['name'] = i[3] list_.append(d) return list_ - + def _set_identities(self, value): self._identities = [] for identity in value: @@ -299,7 +313,7 @@ class CapsCache(object): t = (identity['category'], identity.get('type'), identity.get('xml:lang'), identity.get('name')) self._identities.append(self.__names.setdefault(t, t)) - + identities = property(_get_identities, _set_identities) def set_and_store(self, identities, features): @@ -308,7 +322,7 @@ class CapsCache(object): 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 @@ -325,9 +339,11 @@ class CapsCache(object): x.identities = identities x.features = features x.status = CACHED - + def _remove_outdated_caps(self): - '''Removes outdated values from the db''' + """ + Remove outdated values from the db + """ self.logger.clean_caps_table() def __getitem__(self, caps): @@ -341,20 +357,20 @@ class CapsCache(object): return x def query_client_of_jid_if_unknown(self, connection, jid, client_caps): - ''' - Start a disco query to determine caps (node, ver, exts). - Won't query if the data is already in cache. - ''' + """ + Start a disco query to determine caps (node, ver, exts). Won't query if + the data is already in cache + """ lookup_cache_item = client_caps.get_cache_lookup_strategy() - q = lookup_cache_item(self) - + q = lookup_cache_item(self) + if q.status == NEW: # do query for bare node+hash pair # this will create proper object q.status = QUERIED discover = client_caps.get_discover_strategy() discover(connection, jid) - else: + else: q.update_last_seen() ################################################################################ @@ -362,14 +378,15 @@ class CapsCache(object): ################################################################################ class ConnectionCaps(object): - ''' - This class highly depends on that it is a part of Connection class. - ''' + """ + This class highly depends on that it is a part of Connection class + """ + def _capsPresenceCB(self, con, presence): - ''' + """ Handle incoming presence stanzas... This is a callback for xmpp registered in connection_handlers.py - ''' + """ # we will put these into proper Contact object and ask # for disco... so that disco will learn how to interpret # these caps @@ -411,7 +428,7 @@ class ConnectionCaps(object): if pm_ctrl: pm_ctrl.update_contact() - def _capsDiscoCB(self, jid, node, identities, features, dataforms): + def _capsDiscoCB(self, jid, node, identities, features, dataforms): contact = gajim.contacts.get_contact_from_full_jid(self.name, jid) if not contact: room_jid, nick = gajim.get_room_and_nick_from_fjid(jid) @@ -420,14 +437,14 @@ class ConnectionCaps(object): return lookup = contact.client_caps.get_cache_lookup_strategy() - cache_item = lookup(capscache) - + cache_item = lookup(capscache) + if cache_item.status == CACHED: return else: validate = contact.client_caps.get_hash_validation_strategy() hash_is_valid = validate(identities, features, dataforms) - + if hash_is_valid: cache_item.set_and_store(identities, features) else: diff --git a/src/common/commands.py b/src/common/commands.py index 71b0300bc..07c866194 100644 --- a/src/common/commands.py +++ b/src/common/commands.py @@ -34,10 +34,13 @@ class AdHocCommand: @staticmethod def isVisibleFor(samejid): - ''' This returns True if that command should be visible and invokable - for others. + """ + This returns True if that command should be visible and invokable for + others + samejid - True when command is invoked by an entity with the same bare - jid.''' + jid. + """ return True def __init__(self, conn, jid, sessionid): @@ -80,7 +83,9 @@ class ChangeStatusCommand(AdHocCommand): @staticmethod def isVisibleFor(samejid): - ''' Change status is visible only if the entity has the same bare jid. ''' + """ + Change status is visible only if the entity has the same bare jid + """ return samejid def execute(self, request): @@ -177,7 +182,9 @@ class LeaveGroupchatsCommand(AdHocCommand): @staticmethod def isVisibleFor(samejid): - ''' Change status is visible only if the entity has the same bare jid. ''' + """ + Change status is visible only if the entity has the same bare jid + """ return samejid def execute(self, request): @@ -259,7 +266,9 @@ class ForwardMessagesCommand(AdHocCommand): @staticmethod def isVisibleFor(samejid): - ''' Change status is visible only if the entity has the same bare jid. ''' + """ + Change status is visible only if the entity has the same bare jid + """ return samejid def execute(self, request): @@ -282,7 +291,10 @@ class ForwardMessagesCommand(AdHocCommand): return False # finish the session class ConnectionCommands: - ''' This class depends on that it is a part of Connection() class. ''' + """ + This class depends on that it is a part of Connection() class + """ + def __init__(self): # a list of all commands exposed: node -> command class self.__commands = {} @@ -297,7 +309,9 @@ class ConnectionCommands: return gajim.get_jid_from_account(self.name) def isSameJID(self, jid): - ''' Tests if the bare jid given is the same as our bare jid. ''' + """ + Test if the bare jid given is the same as our bare jid + """ return xmpp.JID(jid).getStripped() == self.getOurBareJID() def commandListQuery(self, con, iq_obj): @@ -318,8 +332,10 @@ class ConnectionCommands: self.connection.send(iq) def commandInfoQuery(self, con, iq_obj): - ''' Send disco#info result for query for command (JEP-0050, example 6.). - Return True if the result was sent, False if not. ''' + """ + Send disco#info result for query for command (JEP-0050, example 6.). + Return True if the result was sent, False if not + """ jid = helpers.get_full_jid_from_iq(iq_obj) node = iq_obj.getTagAttr('query', 'node') @@ -342,8 +358,10 @@ class ConnectionCommands: return False def commandItemsQuery(self, con, iq_obj): - ''' Send disco#items result for query for command. - Return True if the result was sent, False if not. ''' + """ + Send disco#items result for query for command. Return True if the result + was sent, False if not. + """ jid = helpers.get_full_jid_from_iq(iq_obj) node = iq_obj.getTagAttr('query', 'node') diff --git a/src/common/config.py b/src/common/config.py index 92279c6d3..831b2b1eb 100644 --- a/src/common/config.py +++ b/src/common/config.py @@ -512,7 +512,9 @@ class Config: cb(data, opt3, [opt, opt2], dict_[opt2][opt3]) def get_children(self, node=None): - ''' Tree-like interface ''' + """ + Tree-like interface + """ if node is None: for child, option in self.__options.iteritems(): yield (child, ), option @@ -698,8 +700,9 @@ class Config: return False def should_log(self, account, jid): - '''should conversations between a local account and a remote jid be - logged?''' + """ + Should conversations between a local account and a remote jid be logged? + """ no_log_for = self.get_per('accounts', account, 'no_log_for') if not no_log_for: diff --git a/src/common/configpaths.py b/src/common/configpaths.py index 19e45aef3..bf1372970 100644 --- a/src/common/configpaths.py +++ b/src/common/configpaths.py @@ -46,7 +46,9 @@ import tempfile # not displayed to the user, Unicode is not really necessary here. def fse(s): - '''Convert from filesystem encoding if not already Unicode''' + """ + Convert from filesystem encoding if not already Unicode + """ return unicode(s, sys.getfilesystemencoding()) def windowsify(s): diff --git a/src/common/connection.py b/src/common/connection.py index 823f56824..31e2b0ba4 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -100,10 +100,11 @@ ssl_error = { } class CommonConnection: - ''' + """ Common connection class, can be derivated for normal connection or zeroconf connection - ''' + """ + def __init__(self, name): self.name = name # self.connected: @@ -162,11 +163,15 @@ class CommonConnection: return resource def dispatch(self, event, data): - '''always passes account name as first param''' + """ + Always passes account name as first param + """ gajim.interface.dispatch(event, self.name, data) def _reconnect(self): - '''To be implemented by derivated classes''' + """ + To be implemented by derivated classes + """ raise NotImplementedError def quit(self, kill_core): @@ -174,7 +179,9 @@ class CommonConnection: self.disconnect(on_purpose=True) def test_gpg_passphrase(self, password): - '''Returns 'ok', 'bad_pass' or 'expired' ''' + """ + Returns 'ok', 'bad_pass' or 'expired' + """ if not self.gpg: return False self.gpg.passphrase = password @@ -188,10 +195,12 @@ class CommonConnection: return 'ok' def get_signed_msg(self, msg, callback = None): - '''returns the signed message if possible - or an empty string if gpg is not used - or None if waiting for passphrase. - callback is the function to call when user give the passphrase''' + """ + Returns the signed message if possible or an empty string if gpg is not + used or None if waiting for passphrase + + callback is the function to call when user give the passphrase + """ signed = '' keyID = gajim.config.get_per('accounts', self.name, 'keyid') if keyID and self.USE_GPG: @@ -208,7 +217,9 @@ class CommonConnection: return signed def _on_disconnected(self): - ''' called when a disconnect request has completed successfully''' + """ + Called when a disconnect request has completed successfully + """ self.disconnect(on_purpose=True) self.dispatch('STATUS', 'offline') @@ -216,9 +227,10 @@ class CommonConnection: return gajim.SHOW_LIST[self.connected] def check_jid(self, jid): - '''this function must be implemented by derivated classes. - It has to return the valid jid, or raise a helpers.InvalidFormat exception - ''' + """ + This function must be implemented by derivated classes. It has to return + the valid jid, or raise a helpers.InvalidFormat exception + """ raise NotImplementedError def _prepare_message(self, jid, msg, keyID, type_='chat', subject='', @@ -424,32 +436,46 @@ class CommonConnection: common.logger.LOG_DB_PATH def ack_subscribed(self, jid): - '''To be implemented by derivated classes''' + """ + To be implemented by derivated classes + """ raise NotImplementedError def ack_unsubscribed(self, jid): - '''To be implemented by derivated classes''' + """ + To be implemented by derivated classes + """ raise NotImplementedError def request_subscription(self, jid, msg='', name='', groups=[], - auto_auth=False): - '''To be implemented by derivated classes''' + auto_auth=False): + """ + To be implemented by derivated classes + """ raise NotImplementedError def send_authorization(self, jid): - '''To be implemented by derivated classes''' + """ + To be implemented by derivated classes + """ raise NotImplementedError def refuse_authorization(self, jid): - '''To be implemented by derivated classes''' + """ + To be implemented by derivated classes + """ raise NotImplementedError def unsubscribe(self, jid, remove_auth = True): - '''To be implemented by derivated classes''' + """ + To be implemented by derivated classes + """ raise NotImplementedError def unsubscribe_agent(self, agent): - '''To be implemented by derivated classes''' + """ + To be implemented by derivated classes + """ raise NotImplementedError def update_contact(self, jid, name, groups): @@ -457,47 +483,67 @@ class CommonConnection: self.connection.getRoster().setItem(jid=jid, name=name, groups=groups) def update_contacts(self, contacts): - '''update multiple roster items''' + """ + Update multiple roster items + """ if self.connection: self.connection.getRoster().setItemMulti(contacts) def new_account(self, name, config, sync=False): - '''To be implemented by derivated classes''' + """ + To be implemented by derivated classes + """ raise NotImplementedError def _on_new_account(self, con=None, con_type=None): - '''To be implemented by derivated classes''' + """ + To be implemented by derivated classes + """ raise NotImplementedError def account_changed(self, new_name): self.name = new_name def request_last_status_time(self, jid, resource): - '''To be implemented by derivated classes''' + """ + To be implemented by derivated classes + """ raise NotImplementedError def request_os_info(self, jid, resource): - '''To be implemented by derivated classes''' + """ + To be implemented by derivated classes + """ raise NotImplementedError def get_settings(self): - '''To be implemented by derivated classes''' + """ + To be implemented by derivated classes + """ raise NotImplementedError def get_bookmarks(self): - '''To be implemented by derivated classes''' + """ + To be implemented by derivated classes + """ raise NotImplementedError def store_bookmarks(self): - '''To be implemented by derivated classes''' + """ + To be implemented by derivated classes + """ raise NotImplementedError def get_metacontacts(self): - '''To be implemented by derivated classes''' + """ + To be implemented by derivated classes + """ raise NotImplementedError def send_agent_status(self, agent, ptype): - '''To be implemented by derivated classes''' + """ + To be implemented by derivated classes + """ raise NotImplementedError def gpg_passphrase(self, passphrase): @@ -581,7 +627,6 @@ class CommonConnection: self._update_status(show, msg) class Connection(CommonConnection, ConnectionHandlers): - '''Connection class''' def __init__(self, name): CommonConnection.__init__(self, name) ConnectionHandlers.__init__(self) @@ -672,7 +717,9 @@ class Connection(CommonConnection, ConnectionHandlers): self.connection = None def _disconnectedReconnCB(self): - '''Called when we are disconnected''' + """ + Called when we are disconnected + """ log.info('disconnectedReconnCB called') if gajim.account_is_connected(self.name): # we cannot change our status to offline or connecting @@ -830,11 +877,11 @@ class Connection(CommonConnection, ConnectionHandlers): self.dispatch('PRIVACY_LISTS_ACTIVE_DEFAULT', (data)) def _select_next_host(self, hosts): - '''Selects the next host according to RFC2782 p.3 based on it's - priority. Chooses between hosts with the same priority randomly, - where the probability of being selected is proportional to the weight - of the host.''' - + """ + Selects the next host according to RFC2782 p.3 based on it's priority. + Chooses between hosts with the same priority randomly, where the + probability of being selected is proportional to the weight of the host + """ hosts_by_prio = sorted(hosts, key=operator.itemgetter('prio')) try: @@ -856,10 +903,13 @@ class Connection(CommonConnection, ConnectionHandlers): return host def connect(self, data = None): - ''' Start a connection to the Jabber server. - Returns connection, and connection type ('tls', 'ssl', 'plain', '') - data MUST contain hostname, usessl, proxy, use_custom_host, - custom_host (if use_custom_host), custom_port (if use_custom_host)''' + """ + Start a connection to the Jabber server + + Returns connection, and connection type ('tls', 'ssl', 'plain', '') data + MUST contain hostname, usessl, proxy, use_custom_host, custom_host (if + use_custom_host), custom_port (if use_custom_host) + """ if self.connection: return self.connection, '' @@ -1256,8 +1306,10 @@ class Connection(CommonConnection, ConnectionHandlers): self.connection.send(' ') def sendPing(self, pingTo=None): - '''Send XMPP Ping (XEP-0199) request. If pingTo is not set, ping is sent - to server to detect connection failure at application level.''' + """ + Send XMPP Ping (XEP-0199) request. If pingTo is not set, ping is sent to + server to detect connection failure at application level + """ if not self.connection: return id_ = self.connection.getAnID() @@ -1325,7 +1377,9 @@ class Connection(CommonConnection, ConnectionHandlers): common.xmpp.features_nb.setDefaultPrivacyList(self.connection, listname) def build_privacy_rule(self, name, action, order=1): - '''Build a Privacy rule stanza for invisibility''' + """ + Build a Privacy rule stanza for invisibility + """ iq = common.xmpp.Iq('set', common.xmpp.NS_PRIVACY, xmlns = '') l = iq.getTag('query').setTag('list', {'name': name}) i = l.setTag('item', {'action': action, 'order': str(order)}) @@ -1358,7 +1412,9 @@ class Connection(CommonConnection, ConnectionHandlers): self.connection.send(iq) def activate_privacy_rule(self, name): - '''activate a privacy rule''' + """ + Activate a privacy rule + """ if not self.connection: return iq = common.xmpp.Iq('set', common.xmpp.NS_PRIVACY, xmlns = '') @@ -1534,7 +1590,9 @@ class Connection(CommonConnection, ConnectionHandlers): original_message=original_message, delayed=delayed, callback=cb) def send_contacts(self, contacts, jid): - '''Send contacts with RosterX (Xep-0144)''' + """ + Send contacts with RosterX (Xep-0144) + """ if not self.connection: return if len(contacts) == 1: @@ -1553,7 +1611,9 @@ class Connection(CommonConnection, ConnectionHandlers): self.connection.send(msg_iq) def send_stanza(self, stanza): - ''' send a stanza untouched ''' + """ + Send a stanza untouched + """ if not self.connection: return self.connection.send(stanza) @@ -1573,7 +1633,7 @@ class Connection(CommonConnection, ConnectionHandlers): self.connection.send(p) def request_subscription(self, jid, msg = '', name = '', groups = [], - auto_auth = False, user_nick = ''): + auto_auth = False, user_nick = ''): if not self.connection: return log.debug('subscription request for %s' % jid) @@ -1677,8 +1737,10 @@ class Connection(CommonConnection, ConnectionHandlers): common.xmpp.features_nb.getRegInfo(con, self._hostname) def request_last_status_time(self, jid, resource, groupchat_jid=None): - '''groupchat_jid is used when we want to send a request to a real jid - and act as if the answer comes from the groupchat_jid''' + """ + groupchat_jid is used when we want to send a request to a real jid and + act as if the answer comes from the groupchat_jid + """ if not self.connection: return to_whom_jid = jid @@ -1694,8 +1756,10 @@ class Connection(CommonConnection, ConnectionHandlers): self.connection.send(iq) def request_os_info(self, jid, resource, groupchat_jid=None): - '''groupchat_jid is used when we want to send a request to a real jid - and act as if the answer comes from the groupchat_jid''' + """ + groupchat_jid is used when we want to send a request to a real jid and + act as if the answer comes from the groupchat_jid + """ if not self.connection: return # If we are invisible, do not request @@ -1715,8 +1779,10 @@ class Connection(CommonConnection, ConnectionHandlers): self.connection.send(iq) def request_entity_time(self, jid, resource, groupchat_jid=None): - '''groupchat_jid is used when we want to send a request to a real jid - and act as if the answer comes from the groupchat_jid''' + """ + groupchat_jid is used when we want to send a request to a real jid and + act as if the answer comes from the groupchat_jid + """ if not self.connection: return # If we are invisible, do not request @@ -1736,7 +1802,9 @@ class Connection(CommonConnection, ConnectionHandlers): self.connection.send(iq) def get_settings(self): - ''' Get Gajim settings as described in XEP 0049 ''' + """ + Get Gajim settings as described in XEP 0049 + """ if not self.connection: return iq = common.xmpp.Iq(typ='get') @@ -1757,9 +1825,12 @@ class Connection(CommonConnection, ConnectionHandlers): self._request_bookmarks_xml() def get_bookmarks(self, storage_type=None): - '''Get Bookmarks from storage or PubSub if supported as described in - XEP 0048 - storage_type can be set to xml to force request to xml storage''' + """ + Get Bookmarks from storage or PubSub if supported as described in XEP + 0048 + + storage_type can be set to xml to force request to xml storage + """ if not self.connection: return if self.pubsub_supported and storage_type != 'xml': @@ -1771,9 +1842,12 @@ class Connection(CommonConnection, ConnectionHandlers): self._request_bookmarks_xml() def store_bookmarks(self, storage_type=None): - ''' Send bookmarks to the storage namespace or PubSub if supported + """ + Send bookmarks to the storage namespace or PubSub if supported + storage_type can be set to 'pubsub' or 'xml' so store in only one method - else it will be stored on both''' + else it will be stored on both + """ if not self.connection: return iq = common.xmpp.Node(tag='storage', attrs={'xmlns': 'storage:bookmarks'}) @@ -1815,7 +1889,9 @@ class Connection(CommonConnection, ConnectionHandlers): self.connection.send(iqA) def get_annotations(self): - '''Get Annonations from storage as described in XEP 0048, and XEP 0145''' + """ + Get Annonations from storage as described in XEP 0048, and XEP 0145 + """ self.annotations = {} if not self.connection: return @@ -1825,7 +1901,9 @@ class Connection(CommonConnection, ConnectionHandlers): self.connection.send(iq) def store_annotations(self): - '''Set Annonations in private storage as described in XEP 0048, and XEP 0145''' + """ + Set Annonations in private storage as described in XEP 0048, and XEP 0145 + """ if not self.connection: return iq = common.xmpp.Iq(typ='set') @@ -1840,7 +1918,9 @@ class Connection(CommonConnection, ConnectionHandlers): def get_metacontacts(self): - '''Get metacontacts list from storage as described in XEP 0049''' + """ + Get metacontacts list from storage as described in XEP 0049 + """ if not self.connection: return iq = common.xmpp.Iq(typ='get') @@ -1852,7 +1932,9 @@ class Connection(CommonConnection, ConnectionHandlers): self.connection.send(iq) def store_metacontacts(self, tags_list): - ''' Send meta contacts to the storage namespace ''' + """ + Send meta contacts to the storage namespace + """ if not self.connection: return iq = common.xmpp.Iq(typ='set') @@ -2000,16 +2082,20 @@ class Connection(CommonConnection, ConnectionHandlers): self.connection.send(p) def gc_got_disconnected(self, room_jid): - ''' A groupchat got disconnected. This can be or purpose or not. + """ + A groupchat got disconnected. This can be or purpose or not + Save the time we quit to avoid duplicate logs AND be faster than get that date from DB. Save it in mem AND in a small table (with fast access) - ''' + """ log_time = time_time() self.last_history_time[room_jid] = log_time gajim.logger.set_room_last_message_time(room_jid, log_time) def gc_set_role(self, room_jid, nick, role, reason = ''): - '''role is for all the life of the room so it's based on nick''' + """ + Role is for all the life of the room so it's based on nick + """ if not self.connection: return iq = common.xmpp.Iq(typ = 'set', to = room_jid, queryNS =\ @@ -2022,7 +2108,9 @@ class Connection(CommonConnection, ConnectionHandlers): self.connection.send(iq) def gc_set_affiliation(self, room_jid, jid, affiliation, reason = ''): - '''affiliation is for all the life of the room so it's based on jid''' + """ + Affiliation is for all the life of the room so it's based on jid + """ if not self.connection: return iq = common.xmpp.Iq(typ = 'set', to = room_jid, queryNS =\ @@ -2117,7 +2205,9 @@ class Connection(CommonConnection, ConnectionHandlers): _on_unregister_account_connect(self.connection) def send_invite(self, room, to, reason='', continue_tag=False): - '''sends invitation''' + """ + Send invitation + """ message=common.xmpp.Message(to = room) c = message.addChild(name = 'x', namespace = common.xmpp.NS_MUC_USER) c = c.addChild(name = 'invite', attrs={'to' : to}) diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py index 2dbff985b..13547358e 100644 --- a/src/common/connection_handlers.py +++ b/src/common/connection_handlers.py @@ -100,9 +100,9 @@ class ConnectionBytestream: return True def send_success_connect_reply(self, streamhost): - ''' send reply to the initiator of FT that we - made a connection - ''' + """ + Send reply to the initiator of FT that we made a connection + """ if not self.connection or self.connected < 2: return if streamhost is None: @@ -117,7 +117,9 @@ class ConnectionBytestream: self.connection.send(iq) def remove_transfers_for_contact(self, contact): - ''' stop all active transfer for contact ''' + """ + Stop all active transfer for contact + """ for file_props in self.files_props.values(): if self.is_transfer_stopped(file_props): continue @@ -132,7 +134,9 @@ class ConnectionBytestream: self.remove_transfer(file_props) def remove_all_transfers(self): - ''' stops and removes all active connections from the socks5 pool ''' + """ + Stop and remove all active connections from the socks5 pool + """ for file_props in self.files_props.values(): self.remove_transfer(file_props, remove_from_list = False) del(self.files_props) @@ -161,9 +165,11 @@ class ConnectionBytestream: gajim.socks5queue.remove_receiver(host['idx']) gajim.socks5queue.remove_sender(host['idx']) - def send_socks5_info(self, file_props, fast = True, receiver = None, - sender = None): - ''' send iq for the present streamhosts and proxies ''' + def send_socks5_info(self, file_props, fast = True, receiver = None, sender + = None): + """ + Send iq for the present streamhosts and proxies + """ if not self.connection or self.connected < 2: return if not isinstance(self.peerhost, tuple): @@ -269,9 +275,12 @@ class ConnectionBytestream: self.connection.send(iq) def send_file_rejection(self, file_props, code='403', typ=None): - ''' informs sender that we refuse to download the file + """ + Inform sender that we refuse to download the file + typ is used when code = '400', in this case typ can be 'strean' for - invalid stream or 'profile' for invalid profile''' + invalid stream or 'profile' for invalid profile + """ # user response to ConfirmationDialog may come after we've disconneted if not self.connection or self.connected < 2: return @@ -294,7 +303,9 @@ class ConnectionBytestream: self.connection.send(iq) def send_file_approval(self, file_props): - ''' send iq, confirming that we want to download the file ''' + """ + Send iq, confirming that we want to download the file + """ # user response to ConfirmationDialog may come after we've disconneted if not self.connection or self.connected < 2: return @@ -326,7 +337,9 @@ class ConnectionBytestream: return file_props['receiver'].jid + '/' + file_props['receiver'].resource def send_file_request(self, file_props): - ''' send iq for new FT request ''' + """ + Send iq for new FT request + """ if not self.connection or self.connected < 2: return file_props['sender'] = self._ft_get_our_jid() @@ -357,7 +370,9 @@ class ConnectionBytestream: self.connection.send(iq) def _result_socks5_sid(self, sid, hash_id): - ''' store the result of sha message from auth. ''' + """ + Store the result of SHA message from auth + """ if sid not in self.files_props: return file_props = self.files_props[sid] @@ -365,8 +380,10 @@ class ConnectionBytestream: return def _connect_error(self, to, _id, sid, code=404): - ''' cb, when there is an error establishing BS connection, or - when connection is rejected''' + """ + Called when there is an error establishing BS connection, or when + connection is rejected + """ if not self.connection or self.connected < 2: return msg_dict = { @@ -391,7 +408,9 @@ class ConnectionBytestream: self.dispatch('FILE_REQUEST_ERROR', (to, file_props, msg)) def _proxy_auth_ok(self, proxy): - '''cb, called after authentication to proxy server ''' + """ + Called after authentication to proxy server + """ if not self.connection or self.connected < 2: return file_props = self.files_props[proxy['sid']] @@ -673,16 +692,24 @@ class ConnectionBytestream: raise common.xmpp.NodeProcessed class ConnectionDisco: - ''' hold xmpppy handlers and public methods for discover services''' + """ + Holds xmpppy handlers and public methods for discover services + """ + def discoverItems(self, jid, node = None, id_prefix = None): - '''According to XEP-0030: jid is mandatory, - name, node, action is optional.''' + """ + According to XEP-0030: + jid is mandatory; + name, node, action is optional. + """ self._discover(common.xmpp.NS_DISCO_ITEMS, jid, node, id_prefix) def discoverInfo(self, jid, node = None, id_prefix = None): - '''According to XEP-0030: + """ + According to XEP-0030: For identity: category, type is mandatory, name is optional. - For feature: var is mandatory''' + For feature: var is mandatory. + """ self._discover(common.xmpp.NS_DISCO_INFO, jid, node, id_prefix) def request_register_agent_info(self, agent): @@ -738,7 +765,9 @@ class ConnectionDisco: self._IqCB(con, resp) def _discoGetCB(self, con, iq_obj): - ''' get disco info ''' + """ + Get disco info + """ if not self.connection or self.connected < 2: return frm = helpers.get_full_jid_from_iq(iq_obj) @@ -1008,9 +1037,11 @@ class ConnectionVcard: self.dispatch('ERROR', (_('Disk Write Error'), str(e))) def get_cached_vcard(self, fjid, is_fake_jid = False): - '''return the vcard as a dict - return {} if vcard was too old - return None if we don't have cached vcard''' + """ + Return the vcard as a dict. + Return {} if vcard was too old. + Return None if we don't have cached vcard. + """ jid, nick = gajim.get_room_and_nick_from_fjid(fjid) puny_jid = helpers.sanitize_filename(jid) if is_fake_jid: @@ -1045,9 +1076,13 @@ class ConnectionVcard: return vcard def request_vcard(self, jid = None, groupchat_jid = None): - '''request the VCARD. If groupchat_jid is not nul, it means we request a vcard - to a fake jid, like in private messages in groupchat. jid can be the - real jid of the contact, but we want to consider it comes from a fake jid''' + """ + Request the VCARD + + If groupchat_jid is not nul, it means we request a vcard to a fake jid, + like in private messages in groupchat. jid can be the real jid of the + contact, but we want to consider it comes from a fake jid + """ if not self.connection or self.connected < 2: return iq = common.xmpp.Iq(typ = 'get') @@ -1238,8 +1273,9 @@ class ConnectionVcard: del self.awaiting_answers[id_] def _vCardCB(self, con, vc): - '''Called when we receive a vCard - Parse the vCard and send it to plugins''' + """ + Called when we receive a vCard Parse the vCard and send it to plugins + """ if not vc.getTag('vCard'): return if not vc.getTag('vCard').getNamespace() == common.xmpp.NS_VCARD: @@ -1345,8 +1381,9 @@ class ConnectionHandlersBase: self.sessions = {} def get_sessions(self, jid): - '''get all sessions for the given full jid''' - + """ + Get all sessions for the given full jid + """ if not gajim.interface.is_pm_contact(jid, self.name): jid = gajim.get_jid_without_resource(jid) @@ -1356,9 +1393,10 @@ class ConnectionHandlersBase: return [] def get_or_create_session(self, fjid, thread_id): - '''returns an existing session between this connection and 'jid', returns a - new one if none exist.''' - + """ + Return an existing session between this connection and 'jid', returns a + new one if none exist + """ pm = True jid = fjid @@ -1386,7 +1424,9 @@ class ConnectionHandlersBase: return None def terminate_sessions(self, send_termination=False): - '''send termination messages and delete all active sessions''' + """ + Send termination messages and delete all active sessions + """ for jid in self.sessions: for thread_id in self.sessions[jid]: self.sessions[jid][thread_id].terminate(send_termination) @@ -1405,10 +1445,11 @@ class ConnectionHandlersBase: del self.sessions[jid] def find_null_session(self, jid): - '''finds all of the sessions between us and a remote jid in which we -haven't received a thread_id yet and returns the session that we last -sent a message to.''' - + """ + Find all of the sessions between us and a remote jid in which we haven't + received a thread_id yet and returns the session that we last sent a + message to + """ sessions = self.sessions[jid].values() # sessions that we haven't received a thread ID in @@ -1425,8 +1466,9 @@ sent a message to.''' return None def find_controlless_session(self, jid, resource=None): - '''find an active session that doesn't have a control attached''' - + """ + Find an active session that doesn't have a control attached + """ try: sessions = self.sessions[jid].values() @@ -1444,8 +1486,12 @@ sent a message to.''' return None def make_new_session(self, jid, thread_id=None, type_='chat', cls=None): - '''create and register a new session. thread_id=None to generate one. - type_ should be 'chat' or 'pm'.''' + """ + Create and register a new session + + thread_id=None to generate one. + type_ should be 'chat' or 'pm'. + """ if not cls: cls = gajim.default_session_type @@ -1463,7 +1509,9 @@ sent a message to.''' return sess -class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, ConnectionCommands, ConnectionPubSub, ConnectionPEP, ConnectionCaps, ConnectionHandlersBase, ConnectionJingle): +class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, + ConnectionDisco, ConnectionCommands, ConnectionPubSub, ConnectionPEP, + ConnectionCaps, ConnectionHandlersBase, ConnectionJingle): def __init__(self): ConnectionVcard.__init__(self) ConnectionBytestream.__init__(self) @@ -1544,9 +1592,9 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, self.dispatch('ERROR_ANSWER', (id_, jid_from, errmsg, errcode)) def _PrivateCB(self, con, iq_obj): - ''' + """ Private Data (XEP 048 and 049) - ''' + """ log.debug('PrivateCB') query = iq_obj.getTag('query') storage = query.getTag('storage') @@ -1573,8 +1621,9 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, self.annotations[jid] = annotation def _parse_bookmarks(self, storage, storage_type): - '''storage_type can be 'pubsub' or 'xml' to tell from where we got - bookmarks''' + """ + storage_type can be 'pubsub' or 'xml' to tell from where we got bookmarks + """ # Bookmarked URLs and Conferences # http://www.xmpp.org/extensions/xep-0048.html resend_to_pubsub = False @@ -1788,7 +1837,9 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, self.dispatch('ENTITY_TIME', (jid_stripped, resource, time_info)) def _gMailNewMailCB(self, con, gm): - '''Called when we get notified of new mail messages in gmail account''' + """ + Called when we get notified of new mail messages in gmail account + """ if not self.connection or self.connected < 2: return if not gm.getTag('new-mail'): @@ -1810,7 +1861,10 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, raise common.xmpp.NodeProcessed def _gMailQueryCB(self, con, gm): - '''Called when we receive results from Querying the server for mail messages in gmail account''' + """ + Called when we receive results from Querying the server for mail messages + in gmail account + """ if not gm.getTag('mailbox'): return self.gmail_url = gm.getTag('mailbox').getAttr('url') @@ -1856,7 +1910,9 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, raise common.xmpp.NodeProcessed def _rosterItemExchangeCB(self, con, msg): - ''' XEP-0144 Roster Item Echange ''' + """ + XEP-0144 Roster Item Echange + """ exchange_items_list = {} jid_from = helpers.get_full_jid_from_iq(msg) items_list = msg.getTag('x').getChildren() @@ -1898,7 +1954,9 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, raise common.xmpp.NodeProcessed def _messageCB(self, con, msg): - '''Called when we receive a message''' + """ + Called when we receive a message + """ log.debug('MessageCB') mtype = msg.getType() @@ -2167,7 +2225,9 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, is_continued)) def _presenceCB(self, con, prs): - '''Called when we receive a presence''' + """ + Called when we receive a presence + """ ptype = prs.getType() if ptype == 'available': ptype = None @@ -2269,7 +2329,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, gc_control = gajim.interface.msg_win_mgr.get_gc_control(room_jid, self.name) - + # If gc_control is missing - it may be minimized. Try to get it from # there. If it's not there - then it's missing anyway and will # remain set to None. @@ -2550,11 +2610,11 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, raise common.xmpp.NodeProcessed def _PrivacySetCB(self, con, iq_obj): - ''' + """ Privacy lists (XEP 016) - A list has been set - ''' + A list has been set. + """ log.debug('PrivacySetCB') if not self.connection or self.connected < 2: return diff --git a/src/common/contacts.py b/src/common/contacts.py index 5a9df3499..fbc49b229 100644 --- a/src/common/contacts.py +++ b/src/common/contacts.py @@ -33,26 +33,28 @@ import caps from account import Account class XMPPEntity(object): - '''Base representation of entities in XMPP''' - + """ + Base representation of entities in XMPP + """ + 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): - + + 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 - + self.client_caps = client_caps or caps.NullClientCaps() - + # please read xep-85 http://www.xmpp.org/extensions/xep-0085.html # we keep track of xep85 support with the peer by three extra states: # None, False and 'ask' @@ -67,18 +69,18 @@ class CommonContact(XMPPEntity): self.composing_xep = composing_xep # this is contact's chatstate self.chatstate = chatstate - + def get_full_jid(self): raise NotImplementedError - + def get_shown_name(self): raise NotImplementedError def supports(self, requested_feature): - ''' - Returns True if the contact has advertised to support the feature + """ + Return True if the contact has advertised to support the feature identified by the given namespace. False otherwise. - ''' + """ if self.show == 'offline': # Unfortunately, if all resources are offline, the contact # includes the last resource that was online. Check for its @@ -90,26 +92,29 @@ class CommonContact(XMPPEntity): class Contact(CommonContact): - '''Information concerning each contact''' - 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): - - CommonContact.__init__(self, jid, account, resource, show, status, name, + """ + Information concerning each contact + """ + + 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): + + 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 = [i for i in set(groups)] # filter duplicate values self.sub = sub self.ask = ask - + self.priority = priority self.keyID = keyID self.msg_id = msg_id self.last_status_time = last_status_time - + self.pep = {} def get_full_jid(self): @@ -137,7 +142,9 @@ class Contact(CommonContact): return self.groups def is_hidden_from_roster(self): - '''if contact should not be visible in roster''' + """ + If contact should not be visible in roster + """ # XEP-0162: http://www.xmpp.org/extensions/xep-0162.html if self.is_transport(): return False @@ -173,43 +180,50 @@ class Contact(CommonContact): class GC_Contact(CommonContact): - '''Information concerning each groupchat contact''' + """ + Information concerning each groupchat contact + """ + def __init__(self, room_jid, account, name='', show='', status='', role='', - affiliation='', jid='', resource='', our_chatstate=None, - composing_xep=None, chatstate=None): - + affiliation='', jid='', resource='', our_chatstate=None, + composing_xep=None, chatstate=None): + CommonContact.__init__(self, jid, account, resource, show, status, name, our_chatstate, composing_xep, chatstate) - + self.room_jid = room_jid self.role = role self.affiliation = affiliation - + def get_full_jid(self): return self.room_jid + '/' + self.name def get_shown_name(self): return self.name - + def as_contact(self): - '''Create a Contact instance from this GC_Contact instance''' + """ + 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''' + """ + Information concerning all contacts and groupchat contacts + """ + def __init__(self): - self._metacontact_manager = MetacontactManager(self) self._accounts = {} - - def change_account_name(self, old_name, new_name): + + def change_account_name(self, old_name, new_name): self._accounts[new_name] = self._accounts[old_name] self._accounts[new_name].name = new_name del self._accounts[old_name] - + self._metacontact_manager.change_account_name(old_name, new_name) def add_account(self, account_name): @@ -234,7 +248,7 @@ class Contacts: keyID=keyID, client_caps=client_caps, our_chatstate=our_chatstate, chatstate=chatstate, last_status_time=last_status_time, composing_xep=composing_xep) - + def create_self_contact(self, jid, account, resource, show, status, priority, name='', keyID=''): conn = common.gajim.connections[account] @@ -246,7 +260,7 @@ class Contacts: resource=resource) self_contact.pep = conn.pep return self_contact - + 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, @@ -275,7 +289,7 @@ class Contacts: self._accounts[account].contacts.remove_jid(jid) if remove_meta: self._metacontact_manager.remove_metacontact(account, jid) - + def get_contacts(self, account, jid): return self._accounts[account].contacts.get_contacts(jid) @@ -288,13 +302,13 @@ class Contacts: def get_contact_from_full_jid(self, account, fjid): 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() @@ -318,10 +332,11 @@ class Contacts: contact = self.get_gc_contact(account, room, nick) return contact return self.get_highest_prio_contact_from_contacts(contacts) - + def get_nb_online_total_contacts(self, accounts=[], groups=[]): - '''Returns the number of online contacts and the total number of - contacts''' + """ + Return the number of online contacts and the total number of contacts + """ if accounts == []: accounts = self.get_accounts() nbr_online = 0 @@ -358,24 +373,28 @@ class Contacts: return nbr_online, nbr_total def is_pm_from_jid(self, account, jid): - '''Returns True if the given jid is a private message jid''' + """ + Return 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''' + """ + Return 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 @@ -402,15 +421,15 @@ class Contacts: 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): + + def add_contact(self, contact): if contact.jid not in self._contacts: self._contacts[contact.jid] = [contact] return @@ -426,7 +445,7 @@ class Contacts_New(): self.remove_contact(c) break contacts.append(contact) - + def remove_contact(self, contact): if contact.jid not in self._contacts: return @@ -434,28 +453,34 @@ class Contacts_New(): 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''' + """ + Remove 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.''' + """ + Return 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''' + """ + Return 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] @@ -468,22 +493,26 @@ class Contacts_New(): 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''' + """ + 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''' + """ + Return all contacts in the given group + """ group_contacts = [] for jid in self._contacts: contacts = self.get_contacts(jid) @@ -502,11 +531,11 @@ class Contacts_New(): 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} @@ -544,8 +573,10 @@ class GC_Contacts(): 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''' + """ + Return 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 @@ -554,25 +585,25 @@ class GC_Contacts(): 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 @@ -582,13 +613,15 @@ class MetacontactManager(): #FIXME: can this append ? assert False - def iter_metacontacts_families(self, account): + def iter_metacontacts_families(self, account): for tag in self._metacontacts_tags[account]: family = self._get_metacontacts_family_from_tag(account, tag) yield family def _get_metacontacts_tag(self, account, jid): - '''Returns the tag of a jid''' + """ + Return the tag of a jid + """ if not account in self._metacontacts_tags: return None for tag in self._metacontacts_tags[account]: @@ -626,7 +659,7 @@ class MetacontactManager(): 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]: @@ -657,7 +690,9 @@ class MetacontactManager(): return False def _get_metacontacts_jids(self, tag, accounts): - '''Returns all jid for the given tag in the form {acct: [jid1, jid2],.}''' + """ + Return all jid for the given tag in the form {acct: [jid1, jid2],.} + """ answers = {} for account in self._metacontacts_tags: if tag in self._metacontacts_tags[account]: @@ -669,9 +704,10 @@ class MetacontactManager(): return answers def get_metacontacts_family(self, account, jid): - '''return the family of the given jid, including jid in the form: - [{'account': acct, 'jid': jid, 'order': order}, ] - 'order' is optional''' + """ + 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) return self._get_metacontacts_family_from_tag(account, tag) @@ -687,9 +723,12 @@ class MetacontactManager(): return answers def _compare_metacontacts(self, data1, data2): - '''compare 2 metacontacts. - Data is {'jid': jid, 'account': account, 'order': order} - order is optional''' + """ + Compare 2 metacontacts + + Data is {'jid': jid, 'account': account, 'order': order} order is + optional + """ jid1 = data1['jid'] jid2 = data2['jid'] account1 = data1['account'] @@ -765,16 +804,17 @@ class MetacontactManager(): if account2 > account1: return -1 return 0 - - def get_nearby_family_and_big_brother(self, family, account): - '''Return the nearby family and its Big Brother - Nearby family is the part of the family that is grouped with the metacontact. - A metacontact may be over different accounts. If accounts are not merged - then the given family is split account wise. + def get_nearby_family_and_big_brother(self, family, account): + """ + Return the nearby family and its Big Brother + + Nearby family is the part of the family that is grouped with the + metacontact. A metacontact may be over different accounts. If accounts + are not merged then the given family is split account wise. (nearby_family, big_brother_jid, big_brother_account) - ''' + """ if common.gajim.config.get('mergeaccounts'): # group all together nearby_family = family @@ -789,9 +829,11 @@ class MetacontactManager(): return (nearby_family, big_brother_jid, big_brother_account) def _get_metacontacts_big_brother(self, family): - '''which of the family will be the big brother under wich all - others will be ?''' + """ + Which of the family will be the big brother under wich all others will be + ? + """ family.sort(cmp=self._compare_metacontacts) return family[-1] - + # vim: se ts=3: