Add annotations and fix pylint/mypy errors

This commit is contained in:
Philipp Hörist 2018-09-13 23:56:12 +02:00 committed by Philipp Hörist
parent 226c42a92a
commit 77c9b3a98d
39 changed files with 349 additions and 223 deletions

View File

@ -273,7 +273,8 @@ class GajimApplication(Gtk.Application):
self.activate() self.activate()
return 0 return 0
def _handle_local_options(self, application, def _handle_local_options(self,
application: Gtk.Application,
options: GLib.VariantDict) -> int: options: GLib.VariantDict) -> int:
# Parse all options that have to be executed before ::startup # Parse all options that have to be executed before ::startup
if options.contains('profile'): if options.contains('profile'):

View File

@ -413,7 +413,7 @@ class ChatControl(ChatControlBase):
img = self._pep_images[pep_type] img = self._pep_images[pep_type]
if pep_type in pep: if pep_type in pep:
img.set_from_pixbuf(gtkgui_helpers.get_pep_as_pixbuf(pep[pep_type])) img.set_from_pixbuf(gtkgui_helpers.get_pep_as_pixbuf(pep[pep_type]))
img.set_tooltip_markup(pep[pep_type].asMarkupText()) img.set_tooltip_markup(pep[pep_type].as_markup_text())
img.show() img.show()
else: else:
img.hide() img.hide()

View File

@ -31,62 +31,77 @@ to automatic discovery and dispatching, also features manual control
over the process. over the process.
""" """
from typing import Any # pylint: disable=unused-import
from typing import Dict # pylint: disable=unused-import
from gajim.command_system.tools import remove from gajim.command_system.tools import remove
COMMANDS = {} COMMANDS = {} # type: Dict[Any, Any]
CONTAINERS = {} CONTAINERS = {} # type: Dict[Any, Any]
def add_host(host): def add_host(host):
CONTAINERS[host] = [] CONTAINERS[host] = []
def remove_host(host): def remove_host(host):
remove(CONTAINERS, host) remove(CONTAINERS, host)
def add_container(container): def add_container(container):
for host in container.HOSTS: for host in container.HOSTS:
CONTAINERS[host].append(container) CONTAINERS[host].append(container)
def remove_container(container): def remove_container(container):
for host in container.HOSTS: for host in container.HOSTS:
remove(CONTAINERS[host], container) remove(CONTAINERS[host], container)
def add_commands(container): def add_commands(container):
commands = COMMANDS.setdefault(container, {}) commands = COMMANDS.setdefault(container, {})
for command in traverse_commands(container): for command in traverse_commands(container):
for name in command.names: for name in command.names:
commands[name] = command commands[name] = command
def remove_commands(container): def remove_commands(container):
remove(COMMANDS, container) remove(COMMANDS, container)
def traverse_commands(container): def traverse_commands(container):
for name in dir(container): for name in dir(container):
attribute = getattr(container, name) attribute = getattr(container, name)
if is_command(attribute): if is_command(attribute):
yield attribute yield attribute
def is_command(attribute): def is_command(attribute):
from gajim.command_system.framework import Command from gajim.command_system.framework import Command
return isinstance(attribute, Command) return isinstance(attribute, Command)
def is_root(namespace): def is_root(namespace):
metaclass = namespace.get("__metaclass__", None) metaclass = namespace.get("__metaclass__", None)
if not metaclass: if not metaclass:
return False return False
return issubclass(metaclass, Dispatchable) return issubclass(metaclass, Dispatchable)
def get_command(host, name): def get_command(host, name):
for container in CONTAINERS[host]: for container in CONTAINERS[host]:
command = COMMANDS[container].get(name) command = COMMANDS[container].get(name)
if command: if command:
return command return command
def list_commands(host): def list_commands(host):
for container in CONTAINERS[host]: for container in CONTAINERS[host]:
commands = COMMANDS[container] commands = COMMANDS[container]
for name, command in commands.items(): for name, command in commands.items():
yield name, command yield name, command
class Dispatchable(type): class Dispatchable(type):
# pylint: disable=no-value-for-parameter # pylint: disable=no-value-for-parameter
def __init__(self, name, bases, namespace): def __init__(self, name, bases, namespace):
@ -99,6 +114,7 @@ class Dispatchable(type):
if self.AUTOMATIC: if self.AUTOMATIC:
self.enable() self.enable()
class Host(Dispatchable): class Host(Dispatchable):
def enable(self): def enable(self):
@ -107,6 +123,7 @@ class Host(Dispatchable):
def disable(self): def disable(self):
remove_host(self) remove_host(self)
class Container(Dispatchable): class Container(Dispatchable):
def enable(self): def enable(self):

View File

@ -34,6 +34,7 @@ code in here will not be executed and commands defined here will not be
detected. detected.
""" """
from gajim.common.i18n import _
from gajim.command_system.framework import CommandContainer, command, doc from gajim.command_system.framework import CommandContainer, command, doc
from gajim.command_system.implementation.hosts import ChatCommands, PrivateChatCommands, GroupChatCommands from gajim.command_system.implementation.hosts import ChatCommands, PrivateChatCommands, GroupChatCommands

View File

@ -37,6 +37,7 @@ from os.path import expanduser
from gi.repository import GLib from gi.repository import GLib
from gajim.common.i18n import _
from gajim.command_system.framework import CommandContainer, command, doc from gajim.command_system.framework import CommandContainer, command, doc
from gajim.command_system.implementation.hosts import ChatCommands, PrivateChatCommands, GroupChatCommands from gajim.command_system.implementation.hosts import ChatCommands, PrivateChatCommands, GroupChatCommands

View File

@ -23,6 +23,7 @@ from datetime import date
from gajim import dialogs from gajim import dialogs
from gajim.common import app from gajim.common import app
from gajim.common import helpers from gajim.common import helpers
from gajim.common.i18n import _
from gajim.common.exceptions import GajimGeneralException from gajim.common.exceptions import GajimGeneralException
from gajim.common.const import KindConstant from gajim.common.const import KindConstant

View File

@ -42,7 +42,7 @@ from gajim.common.contacts import LegacyContactsAPI
from gajim.common.events import Events from gajim.common.events import Events
from gajim.common.css_config import CSSConfig from gajim.common.css_config import CSSConfig
interface = None # The actual interface (the gtk one for the moment) interface = None # type: gajim.interface.Interface
thread_interface = lambda *args: None # Interface to run a thread and then a callback thread_interface = lambda *args: None # Interface to run a thread and then a callback
config = c_config.Config() config = c_config.Config()
version = gajim.__version__ version = gajim.__version__
@ -52,10 +52,10 @@ ipython_window = None
app = None # Gtk.Application app = None # Gtk.Application
ged = ged_module.GlobalEventsDispatcher() # Global Events Dispatcher ged = ged_module.GlobalEventsDispatcher() # Global Events Dispatcher
nec = None # Network Events Controller nec = None # type: gajim.common.nec.NetworkEventsController
plugin_manager = None # Plugins Manager plugin_manager = None # Plugins Manager
logger = None logger = None # type: gajim.common.logger.Logger
# For backwards compatibility needed # For backwards compatibility needed
# some plugins use that # some plugins use that
@ -122,7 +122,7 @@ SHOW_LIST = ['offline', 'connecting', 'online', 'chat', 'away', 'xa', 'dnd',
ZEROCONF_ACC_NAME = 'Local' ZEROCONF_ACC_NAME = 'Local'
# These will be set in app.gui_interface. # These will be set in app.gui_interface.
idlequeue = None idlequeue = None # type: nbxmpp.idlequeue.IdleQueue
socks5queue = None socks5queue = None
gajim_identity = {'type': 'pc', 'category': 'client', 'name': 'Gajim'} gajim_identity = {'type': 'pc', 'category': 'client', 'name': 'Gajim'}

View File

@ -32,6 +32,7 @@ from gi.repository import GLib
from enum import IntEnum, unique from enum import IntEnum, unique
import gajim import gajim
from gajim.common.i18n import _
@unique @unique

View File

@ -19,82 +19,90 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Gajim. If not, see <http://www.gnu.org/licenses/>. # along with Gajim. If not, see <http://www.gnu.org/licenses/>.
from typing import Dict # pylint: disable=unused-import
from typing import List
from typing import Generator
from typing import Optional # pylint: disable=unused-import
from typing import Tuple
from typing import Union
import os import os
import sys import sys
import tempfile import tempfile
from pathlib import Path from pathlib import Path
import gajim import gajim
from gajim.common.i18n import _
from gajim.common.const import PathType, PathLocation from gajim.common.const import PathType, PathLocation
from gajim.common.types import PathTuple
def get(key): def get(key: str) -> Union[str, List[str]]:
if key == 'PLUGINS_DIRS': if key == 'PLUGINS_DIRS':
if gajim.IS_FLATPAK: if gajim.IS_FLATPAK:
return ['/app/plugins', return ['/app/plugins',
_paths['PLUGINS_BASE']] _paths['PLUGINS_BASE']]
else: return [_paths['PLUGINS_BASE'],
return [_paths['PLUGINS_BASE'], _paths['PLUGINS_USER']]
_paths['PLUGINS_USER']]
return _paths[key] return _paths[key]
def get_paths(type_): def get_paths(type_: PathType) -> Generator[str, None, None]:
for key, value in _paths.items(): for key, value in _paths.items():
location, path, path_type = value path_type = value[2]
if type_ != path_type: if type_ != path_type:
continue continue
yield _paths[key] yield _paths[key]
def override_path(*args, **kwargs): def override_path(*args, **kwargs):
_paths._add(*args, **kwargs) _paths.add(*args, **kwargs)
def set_separation(active: bool): def set_separation(active: bool) -> None:
_paths.profile_separation = active _paths.profile_separation = active
def set_profile(profile: str): def set_profile(profile: str) -> None:
_paths.profile = profile _paths.profile = profile
def set_config_root(config_root: str): def set_config_root(config_root: str) -> None:
_paths.custom_config_root = config_root _paths.custom_config_root = config_root
def init(): def init() -> None:
_paths.init() _paths.init()
def create_paths(): def create_paths() -> None:
for path in get_paths(PathType.FOLDER): for path in get_paths(PathType.FOLDER):
if not isinstance(path, Path): if not isinstance(path, Path):
path = Path(path) path_ = Path(path)
if path.is_file(): if path_.is_file():
print(_('%s is a file but it should be a directory') % path) print(_('%s is a file but it should be a directory') % path_)
print(_('Gajim will now exit')) print(_('Gajim will now exit'))
sys.exit() sys.exit()
if not path.exists(): if not path_.exists():
for parent_path in reversed(path.parents): for parent_path in reversed(path_.parents):
# Create all parent folders # Create all parent folders
# don't use mkdir(parent=True), as it ignores `mode` # don't use mkdir(parent=True), as it ignores `mode`
# when creating the parents # when creating the parents
if not parent_path.exists(): if not parent_path.exists():
print(('creating %s directory') % parent_path) print(('creating %s directory') % parent_path)
parent_path.mkdir(mode=0o700) parent_path.mkdir(mode=0o700)
print(('creating %s directory') % path) print(('creating %s directory') % path_)
path.mkdir(mode=0o700) path_.mkdir(mode=0o700)
class ConfigPaths: class ConfigPaths:
def __init__(self): def __init__(self) -> None:
self._paths = {} self._paths = {} # type: Dict[str, PathTuple]
self.profile = '' self.profile = ''
self.profile_separation = False self.profile_separation = False
self.custom_config_root = None self.custom_config_root = None # type: Optional[str]
if os.name == 'nt': if os.name == 'nt':
try: try:
@ -133,23 +141,23 @@ class ConfigPaths:
] ]
for path in source_paths: for path in source_paths:
self._add(*path) self.add(*path)
def __getitem__(self, key): def __getitem__(self, key: str) -> str:
location, path, _ = self._paths[key] location, path, _ = self._paths[key]
if location == PathLocation.CONFIG: if location == PathLocation.CONFIG:
return os.path.join(self.config_root, path) return os.path.join(self.config_root, path)
elif location == PathLocation.CACHE: if location == PathLocation.CACHE:
return os.path.join(self.cache_root, path) return os.path.join(self.cache_root, path)
elif location == PathLocation.DATA: if location == PathLocation.DATA:
return os.path.join(self.data_root, path) return os.path.join(self.data_root, path)
return path return path
def items(self): def items(self) -> Generator[Tuple[str, PathTuple], None, None]:
for key, value in self._paths.items(): for key, value in self._paths.items():
yield (key, value) yield (key, value)
def _prepare(self, path, unique): def _prepare(self, path: str, unique: bool) -> str:
if os.name == 'nt': if os.name == 'nt':
path = path.capitalize() path = path.capitalize()
if self.profile: if self.profile:
@ -157,7 +165,12 @@ class ConfigPaths:
return '%s.%s' % (path, self.profile) return '%s.%s' % (path, self.profile)
return path return path
def _add(self, name, path, location=None, path_type=None, unique=False): def add(self,
name: str,
path: str,
location: PathLocation = None,
path_type: PathType = None,
unique: bool = False) -> None:
if path and location is not None: if path and location is not None:
path = self._prepare(path, unique) path = self._prepare(path, unique)
self._paths[name] = (location, path, path_type) self._paths[name] = (location, path, path_type)
@ -175,7 +188,7 @@ class ConfigPaths:
] ]
for path in user_dir_paths: for path in user_dir_paths:
self._add(*path) self.add(*path)
# These paths are unique per profile # These paths are unique per profile
unique_profile_paths = [ unique_profile_paths = [
@ -191,7 +204,7 @@ class ConfigPaths:
] ]
for path in unique_profile_paths: for path in unique_profile_paths:
self._add(*path, unique=True) self.add(*path, unique=True)
# These paths are only unique per profile if the commandline arg # These paths are only unique per profile if the commandline arg
# `separate` is passed # `separate` is passed
@ -219,7 +232,7 @@ class ConfigPaths:
] ]
for path in paths: for path in paths:
self._add(*path) self.add(*path)
_paths = ConfigPaths() _paths = ConfigPaths()

View File

@ -176,7 +176,6 @@ class HelperEvent:
class IqErrorReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): class IqErrorReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
name = 'iq-error-received' name = 'iq-error-received'
base_network_events = []
def generate(self): def generate(self):
self.get_id() self.get_id()
@ -187,7 +186,6 @@ class IqErrorReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
class StreamReceivedEvent(nec.NetworkIncomingEvent): class StreamReceivedEvent(nec.NetworkIncomingEvent):
name = 'stream-received' name = 'stream-received'
base_network_events = []
class StreamConflictReceivedEvent(nec.NetworkIncomingEvent): class StreamConflictReceivedEvent(nec.NetworkIncomingEvent):
name = 'stream-conflict-received' name = 'stream-conflict-received'
@ -321,7 +319,6 @@ PresenceHelperEvent):
class ZeroconfPresenceReceivedEvent(nec.NetworkIncomingEvent): class ZeroconfPresenceReceivedEvent(nec.NetworkIncomingEvent):
name = 'presence-received' name = 'presence-received'
base_network_events = []
def generate(self): def generate(self):
self.jid, self.resource = app.get_room_and_nick_from_fjid(self.fjid) self.jid, self.resource = app.get_room_and_nick_from_fjid(self.fjid)
@ -348,7 +345,6 @@ class ZeroconfPresenceReceivedEvent(nec.NetworkIncomingEvent):
class GcPresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): class GcPresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
name = 'gc-presence-received' name = 'gc-presence-received'
base_network_events = []
def generate(self): def generate(self):
self.ptype = self.presence_obj.ptype self.ptype = self.presence_obj.ptype
@ -436,15 +432,12 @@ class GcPresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
class OurShowEvent(nec.NetworkIncomingEvent): class OurShowEvent(nec.NetworkIncomingEvent):
name = 'our-show' name = 'our-show'
base_network_events = []
class BeforeChangeShowEvent(nec.NetworkIncomingEvent): class BeforeChangeShowEvent(nec.NetworkIncomingEvent):
name = 'before-change-show' name = 'before-change-show'
base_network_events = []
class ChatstateReceivedEvent(nec.NetworkIncomingEvent): class ChatstateReceivedEvent(nec.NetworkIncomingEvent):
name = 'chatstate-received' name = 'chatstate-received'
base_network_events = []
def generate(self): def generate(self):
self.stanza = self.msg_obj.stanza self.stanza = self.msg_obj.stanza
@ -456,7 +449,6 @@ class ChatstateReceivedEvent(nec.NetworkIncomingEvent):
class GcMessageReceivedEvent(nec.NetworkIncomingEvent): class GcMessageReceivedEvent(nec.NetworkIncomingEvent):
name = 'gc-message-received' name = 'gc-message-received'
base_network_events = []
def generate(self): def generate(self):
self.stanza = self.msg_obj.stanza self.stanza = self.msg_obj.stanza
@ -556,7 +548,6 @@ class GcMessageReceivedEvent(nec.NetworkIncomingEvent):
class GcConfigChangedReceivedEvent(nec.NetworkIncomingEvent): class GcConfigChangedReceivedEvent(nec.NetworkIncomingEvent):
name = 'gc-config-changed-received' name = 'gc-config-changed-received'
base_network_events = []
def generate(self): def generate(self):
self.conn = self.msg_event.conn self.conn = self.msg_event.conn
@ -567,7 +558,6 @@ class GcConfigChangedReceivedEvent(nec.NetworkIncomingEvent):
class MessageSentEvent(nec.NetworkIncomingEvent): class MessageSentEvent(nec.NetworkIncomingEvent):
name = 'message-sent' name = 'message-sent'
base_network_events = []
def generate(self): def generate(self):
if not self.automatic_message: if not self.automatic_message:
@ -579,11 +569,9 @@ class MessageSentEvent(nec.NetworkIncomingEvent):
class MessageNotSentEvent(nec.NetworkIncomingEvent): class MessageNotSentEvent(nec.NetworkIncomingEvent):
name = 'message-not-sent' name = 'message-not-sent'
base_network_events = []
class MessageErrorEvent(nec.NetworkIncomingEvent, HelperEvent): class MessageErrorEvent(nec.NetworkIncomingEvent, HelperEvent):
name = 'message-error' name = 'message-error'
base_network_events = []
def init(self): def init(self):
self.zeroconf = False self.zeroconf = False
@ -600,11 +588,9 @@ class MessageErrorEvent(nec.NetworkIncomingEvent, HelperEvent):
class AnonymousAuthEvent(nec.NetworkIncomingEvent): class AnonymousAuthEvent(nec.NetworkIncomingEvent):
name = 'anonymous-auth' name = 'anonymous-auth'
base_network_events = []
class JingleRequestReceivedEvent(nec.NetworkIncomingEvent): class JingleRequestReceivedEvent(nec.NetworkIncomingEvent):
name = 'jingle-request-received' name = 'jingle-request-received'
base_network_events = []
def generate(self): def generate(self):
self.fjid = self.jingle_session.peerjid self.fjid = self.jingle_session.peerjid
@ -614,7 +600,6 @@ class JingleRequestReceivedEvent(nec.NetworkIncomingEvent):
class JingleConnectedReceivedEvent(nec.NetworkIncomingEvent): class JingleConnectedReceivedEvent(nec.NetworkIncomingEvent):
name = 'jingle-connected-received' name = 'jingle-connected-received'
base_network_events = []
def generate(self): def generate(self):
self.fjid = self.jingle_session.peerjid self.fjid = self.jingle_session.peerjid
@ -624,7 +609,6 @@ class JingleConnectedReceivedEvent(nec.NetworkIncomingEvent):
class JingleDisconnectedReceivedEvent(nec.NetworkIncomingEvent): class JingleDisconnectedReceivedEvent(nec.NetworkIncomingEvent):
name = 'jingle-disconnected-received' name = 'jingle-disconnected-received'
base_network_events = []
def generate(self): def generate(self):
self.fjid = self.jingle_session.peerjid self.fjid = self.jingle_session.peerjid
@ -634,7 +618,6 @@ class JingleDisconnectedReceivedEvent(nec.NetworkIncomingEvent):
class JingleTransferCancelledEvent(nec.NetworkIncomingEvent): class JingleTransferCancelledEvent(nec.NetworkIncomingEvent):
name = 'jingleFT-cancelled-received' name = 'jingleFT-cancelled-received'
base_network_events = []
def generate(self): def generate(self):
self.fjid = self.jingle_session.peerjid self.fjid = self.jingle_session.peerjid
@ -644,7 +627,6 @@ class JingleTransferCancelledEvent(nec.NetworkIncomingEvent):
class JingleErrorReceivedEvent(nec.NetworkIncomingEvent): class JingleErrorReceivedEvent(nec.NetworkIncomingEvent):
name = 'jingle-error-received' name = 'jingle-error-received'
base_network_events = []
def generate(self): def generate(self):
self.fjid = self.jingle_session.peerjid self.fjid = self.jingle_session.peerjid
@ -654,15 +636,12 @@ class JingleErrorReceivedEvent(nec.NetworkIncomingEvent):
class AccountCreatedEvent(nec.NetworkIncomingEvent): class AccountCreatedEvent(nec.NetworkIncomingEvent):
name = 'account-created' name = 'account-created'
base_network_events = []
class AccountNotCreatedEvent(nec.NetworkIncomingEvent): class AccountNotCreatedEvent(nec.NetworkIncomingEvent):
name = 'account-not-created' name = 'account-not-created'
base_network_events = []
class NewAccountConnectedEvent(nec.NetworkIncomingEvent): class NewAccountConnectedEvent(nec.NetworkIncomingEvent):
name = 'new-account-connected' name = 'new-account-connected'
base_network_events = []
def generate(self): def generate(self):
try: try:
@ -686,15 +665,12 @@ class NewAccountConnectedEvent(nec.NetworkIncomingEvent):
class NewAccountNotConnectedEvent(nec.NetworkIncomingEvent): class NewAccountNotConnectedEvent(nec.NetworkIncomingEvent):
name = 'new-account-not-connected' name = 'new-account-not-connected'
base_network_events = []
class ConnectionTypeEvent(nec.NetworkIncomingEvent): class ConnectionTypeEvent(nec.NetworkIncomingEvent):
name = 'connection-type' name = 'connection-type'
base_network_events = []
class StanzaReceivedEvent(nec.NetworkIncomingEvent): class StanzaReceivedEvent(nec.NetworkIncomingEvent):
name = 'stanza-received' name = 'stanza-received'
base_network_events = []
def init(self): def init(self):
self.additional_data = {} self.additional_data = {}
@ -704,14 +680,12 @@ class StanzaReceivedEvent(nec.NetworkIncomingEvent):
class StanzaSentEvent(nec.NetworkIncomingEvent): class StanzaSentEvent(nec.NetworkIncomingEvent):
name = 'stanza-sent' name = 'stanza-sent'
base_network_events = []
def init(self): def init(self):
self.additional_data = {} self.additional_data = {}
class AgentRemovedEvent(nec.NetworkIncomingEvent): class AgentRemovedEvent(nec.NetworkIncomingEvent):
name = 'agent-removed' name = 'agent-removed'
base_network_events = []
def generate(self): def generate(self):
self.jid_list = [] self.jid_list = []
@ -722,7 +696,6 @@ class AgentRemovedEvent(nec.NetworkIncomingEvent):
class BadGPGPassphraseEvent(nec.NetworkIncomingEvent): class BadGPGPassphraseEvent(nec.NetworkIncomingEvent):
name = 'bad-gpg-passphrase' name = 'bad-gpg-passphrase'
base_network_events = []
def generate(self): def generate(self):
self.account = self.conn.name self.account = self.conn.name
@ -732,7 +705,6 @@ class BadGPGPassphraseEvent(nec.NetworkIncomingEvent):
class ConnectionLostEvent(nec.NetworkIncomingEvent): class ConnectionLostEvent(nec.NetworkIncomingEvent):
name = 'connection-lost' name = 'connection-lost'
base_network_events = []
def generate(self): def generate(self):
app.nec.push_incoming_event(OurShowEvent(None, conn=self.conn, app.nec.push_incoming_event(OurShowEvent(None, conn=self.conn,
@ -741,11 +713,9 @@ class ConnectionLostEvent(nec.NetworkIncomingEvent):
class GPGTrustKeyEvent(nec.NetworkIncomingEvent): class GPGTrustKeyEvent(nec.NetworkIncomingEvent):
name = 'gpg-trust-key' name = 'gpg-trust-key'
base_network_events = []
class GPGPasswordRequiredEvent(nec.NetworkIncomingEvent): class GPGPasswordRequiredEvent(nec.NetworkIncomingEvent):
name = 'gpg-password-required' name = 'gpg-password-required'
base_network_events = []
def generate(self): def generate(self):
self.keyid = app.config.get_per('accounts', self.conn.name, 'keyid') self.keyid = app.config.get_per('accounts', self.conn.name, 'keyid')
@ -753,7 +723,6 @@ class GPGPasswordRequiredEvent(nec.NetworkIncomingEvent):
class PEPReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): class PEPReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
name = 'pep-received' name = 'pep-received'
base_network_events = []
def generate(self): def generate(self):
if not self.stanza.getTag('event'): if not self.stanza.getTag('event'):
@ -778,72 +747,57 @@ class PEPReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
class PlainConnectionEvent(nec.NetworkIncomingEvent): class PlainConnectionEvent(nec.NetworkIncomingEvent):
name = 'plain-connection' name = 'plain-connection'
base_network_events = []
class InsecurePasswordEvent(nec.NetworkIncomingEvent): class InsecurePasswordEvent(nec.NetworkIncomingEvent):
name = 'insecure-password' name = 'insecure-password'
base_network_events = []
class InsecureSSLConnectionEvent(nec.NetworkIncomingEvent): class InsecureSSLConnectionEvent(nec.NetworkIncomingEvent):
name = 'insecure-ssl-connection' name = 'insecure-ssl-connection'
base_network_events = []
class SSLErrorEvent(nec.NetworkIncomingEvent): class SSLErrorEvent(nec.NetworkIncomingEvent):
name = 'ssl-error' name = 'ssl-error'
base_network_events = []
class UniqueRoomIdSupportedEvent(nec.NetworkIncomingEvent): class UniqueRoomIdSupportedEvent(nec.NetworkIncomingEvent):
name = 'unique-room-id-supported' name = 'unique-room-id-supported'
base_network_events = []
class UniqueRoomIdNotSupportedEvent(nec.NetworkIncomingEvent): class UniqueRoomIdNotSupportedEvent(nec.NetworkIncomingEvent):
name = 'unique-room-id-not-supported' name = 'unique-room-id-not-supported'
base_network_events = []
class NonAnonymousServerErrorEvent(nec.NetworkIncomingEvent): class NonAnonymousServerErrorEvent(nec.NetworkIncomingEvent):
name = 'non-anonymous-server-error' name = 'non-anonymous-server-error'
base_network_events = []
class UpdateGCAvatarEvent(nec.NetworkIncomingEvent): class UpdateGCAvatarEvent(nec.NetworkIncomingEvent):
name = 'update-gc-avatar' name = 'update-gc-avatar'
base_network_events = []
def generate(self): def generate(self):
return True return True
class UpdateRosterAvatarEvent(nec.NetworkIncomingEvent): class UpdateRosterAvatarEvent(nec.NetworkIncomingEvent):
name = 'update-roster-avatar' name = 'update-roster-avatar'
base_network_events = []
def generate(self): def generate(self):
return True return True
class UpdateRoomAvatarEvent(nec.NetworkIncomingEvent): class UpdateRoomAvatarEvent(nec.NetworkIncomingEvent):
name = 'update-room-avatar' name = 'update-room-avatar'
base_network_events = []
def generate(self): def generate(self):
return True return True
class ZeroconfNameConflictEvent(nec.NetworkIncomingEvent): class ZeroconfNameConflictEvent(nec.NetworkIncomingEvent):
name = 'zeroconf-name-conflict' name = 'zeroconf-name-conflict'
base_network_events = []
class PasswordRequiredEvent(nec.NetworkIncomingEvent): class PasswordRequiredEvent(nec.NetworkIncomingEvent):
name = 'password-required' name = 'password-required'
base_network_events = []
class Oauth2CredentialsRequiredEvent(nec.NetworkIncomingEvent): class Oauth2CredentialsRequiredEvent(nec.NetworkIncomingEvent):
name = 'oauth2-credentials-required' name = 'oauth2-credentials-required'
base_network_events = []
class SignedInEvent(nec.NetworkIncomingEvent): class SignedInEvent(nec.NetworkIncomingEvent):
name = 'signed-in' name = 'signed-in'
base_network_events = []
class FileRequestReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): class FileRequestReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
name = 'file-request-received' name = 'file-request-received'
base_network_events = []
def init(self): def init(self):
self.jingle_content = None self.jingle_content = None
@ -960,7 +914,6 @@ class FileRequestReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
class FileRequestErrorEvent(nec.NetworkIncomingEvent): class FileRequestErrorEvent(nec.NetworkIncomingEvent):
name = 'file-request-error' name = 'file-request-error'
base_network_events = []
def generate(self): def generate(self):
self.jid = app.get_jid_without_resource(self.jid) self.jid = app.get_jid_without_resource(self.jid)
@ -968,7 +921,6 @@ class FileRequestErrorEvent(nec.NetworkIncomingEvent):
class FileTransferCompletedEvent(nec.NetworkIncomingEvent): class FileTransferCompletedEvent(nec.NetworkIncomingEvent):
name = 'file-transfer-completed' name = 'file-transfer-completed'
base_network_events = []
def generate(self): def generate(self):
jid = str(self.file_props.receiver) jid = str(self.file_props.receiver)
@ -977,7 +929,6 @@ class FileTransferCompletedEvent(nec.NetworkIncomingEvent):
class GatewayPromptReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): class GatewayPromptReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
name = 'gateway-prompt-received' name = 'gateway-prompt-received'
base_network_events = []
def generate(self): def generate(self):
self.get_jid_resource() self.get_jid_resource()
@ -1251,7 +1202,6 @@ class NotificationEvent(nec.NetworkIncomingEvent):
class MessageOutgoingEvent(nec.NetworkOutgoingEvent): class MessageOutgoingEvent(nec.NetworkOutgoingEvent):
name = 'message-outgoing' name = 'message-outgoing'
base_network_events = []
def init(self): def init(self):
self.additional_data = {} self.additional_data = {}
@ -1297,21 +1247,18 @@ class MessageOutgoingEvent(nec.NetworkOutgoingEvent):
class StanzaMessageOutgoingEvent(nec.NetworkOutgoingEvent): class StanzaMessageOutgoingEvent(nec.NetworkOutgoingEvent):
name='stanza-message-outgoing' name='stanza-message-outgoing'
base_network_events = []
def generate(self): def generate(self):
return True return True
class GcStanzaMessageOutgoingEvent(nec.NetworkOutgoingEvent): class GcStanzaMessageOutgoingEvent(nec.NetworkOutgoingEvent):
name='gc-stanza-message-outgoing' name='gc-stanza-message-outgoing'
base_network_events = []
def generate(self): def generate(self):
return True return True
class GcMessageOutgoingEvent(nec.NetworkOutgoingEvent): class GcMessageOutgoingEvent(nec.NetworkOutgoingEvent):
name = 'gc-message-outgoing' name = 'gc-message-outgoing'
base_network_events = []
def init(self): def init(self):
self.additional_data = {} self.additional_data = {}
@ -1333,11 +1280,9 @@ class GcMessageOutgoingEvent(nec.NetworkOutgoingEvent):
class ClientCertPassphraseEvent(nec.NetworkIncomingEvent): class ClientCertPassphraseEvent(nec.NetworkIncomingEvent):
name = 'client-cert-passphrase' name = 'client-cert-passphrase'
base_network_events = []
class InformationEvent(nec.NetworkIncomingEvent): class InformationEvent(nec.NetworkIncomingEvent):
name = 'information' name = 'information'
base_network_events = []
def init(self): def init(self):
self.args = None self.args = None
@ -1355,7 +1300,6 @@ class InformationEvent(nec.NetworkIncomingEvent):
class StyleChanged(nec.NetworkIncomingEvent): class StyleChanged(nec.NetworkIncomingEvent):
name = 'style-changed' name = 'style-changed'
base_network_events = []
def generate(self): def generate(self):
return True return True

View File

@ -1,6 +1,8 @@
from enum import IntEnum, Enum, unique from enum import IntEnum, Enum, unique
from collections import namedtuple from collections import namedtuple
from gajim.common.i18n import _
Option = namedtuple('Option', 'kind label type value name callback data desc enabledif props') Option = namedtuple('Option', 'kind label type value name callback data desc enabledif props')
Option.__new__.__defaults__ = (None,) * len(Option._fields) Option.__new__.__defaults__ = (None,) * len(Option._fields)
@ -168,13 +170,14 @@ class PEPHandlerType(IntEnum):
@unique @unique
class PEPEventType(IntEnum): class PEPEventType(IntEnum):
ACTIVITY = 0 ABSTRACT = 0
TUNE = 1 ACTIVITY = 1
MOOD = 2 TUNE = 2
LOCATION = 3 MOOD = 3
NICKNAME = 4 LOCATION = 4
AVATAR = 5 NICKNAME = 5
ATOM = 6 AVATAR = 6
ATOM = 7
ACTIVITIES = { ACTIVITIES = {

View File

@ -25,6 +25,7 @@ import logging
from gajim.common import app from gajim.common import app
from gajim.common import exceptions from gajim.common import exceptions
from gajim.common.i18n import _
_GAJIM_ERROR_IFACE = 'org.gajim.dbus.Error' _GAJIM_ERROR_IFACE = 'org.gajim.dbus.Error'

View File

@ -48,6 +48,7 @@ from string import Template
import nbxmpp import nbxmpp
from gajim.common.i18n import Q_ from gajim.common.i18n import Q_
from gajim.common.i18n import _
from gajim.common.i18n import ngettext from gajim.common.i18n import ngettext
from gajim.common import configpaths from gajim.common import configpaths

View File

@ -132,7 +132,7 @@ if os.name == 'nt':
_localedir = get_locale_dir() _localedir = get_locale_dir()
if hasattr(locale, 'bindtextdomain'): if hasattr(locale, 'bindtextdomain'):
locale.bindtextdomain(DOMAIN, _localedir) locale.bindtextdomain(DOMAIN, _localedir) # type: ignore
gettext.textdomain(DOMAIN) gettext.textdomain(DOMAIN)
gettext.install(DOMAIN, _localedir) gettext.install(DOMAIN, _localedir)
@ -142,7 +142,7 @@ try:
except OSError: except OSError:
_ = gettext.gettext _ = gettext.gettext
if gettext._translations: if gettext._translations: # type: ignore
_translations = list(gettext._translations.values())[0] _translations = list(gettext._translations.values())[0] # type: ignore
else: else:
_translations = gettext.NullTranslations() _translations = gettext.NullTranslations()

View File

@ -12,14 +12,18 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Gajim. If not, see <http://www.gnu.org/licenses/>. # along with Gajim. If not, see <http://www.gnu.org/licenses/>.
from typing import Any
from typing import Dict # pylint: disable=unused-import
from typing import List
from typing import Tuple
import logging import logging
from typing import List # noqa
from typing import Dict # noqa
from typing import Any # noqa
from importlib import import_module from importlib import import_module
from pathlib import Path from pathlib import Path
from unittest.mock import MagicMock from unittest.mock import MagicMock
from gajim.common.types import ConnectionT
log = logging.getLogger('gajim.c.m') log = logging.getLogger('gajim.c.m')
ZEROCONF_MODULES = ['adhoc_commands', 'receipts', 'discovery'] ZEROCONF_MODULES = ['adhoc_commands', 'receipts', 'discovery']
@ -70,7 +74,7 @@ class ModuleMock:
return MagicMock() return MagicMock()
def register(con, *args, **kwargs): def register(con: ConnectionT, *args: Any, **kwargs: Any) -> None:
if con in _modules: if con in _modules:
return return
_modules[con.name] = {} _modules[con.name] = {}
@ -83,20 +87,20 @@ def register(con, *args, **kwargs):
_modules[con.name][name] = instance _modules[con.name][name] = instance
def register_single(con, instance, name): def register_single(con: ConnectionT, instance: Any, name: str) -> None:
if con.name not in _modules: if con.name not in _modules:
raise ValueError('Unknown account name: %s' % con.name) raise ValueError('Unknown account name: %s' % con.name)
_modules[con.name][name] = instance _modules[con.name][name] = instance
def unregister(con): def unregister(con: ConnectionT) -> None:
for instance in _modules[con.name].values(): for instance in _modules[con.name].values():
if hasattr(instance, 'cleanup'): if hasattr(instance, 'cleanup'):
instance.cleanup() instance.cleanup()
del _modules[con.name] del _modules[con.name]
def unregister_single(con, name): def unregister_single(con: ConnectionT, name: str) -> None:
if con.name not in _modules: if con.name not in _modules:
return return
if name not in _modules[con.name]: if name not in _modules[con.name]:
@ -111,8 +115,8 @@ def get(account: str, name: str) -> Any:
return ModuleMock(name) return ModuleMock(name)
def get_handlers(con): def get_handlers(con: ConnectionT) -> List[Tuple[Any, ...]]:
handlers = [] handlers = [] # type: List[Tuple[Any, ...]]
for module in _modules[con.name].values(): for module in _modules[con.name].values():
handlers += module.handlers handlers += module.handlers
return handlers return handlers

View File

@ -14,24 +14,30 @@
# XEP-0145: Annotations # XEP-0145: Annotations
from typing import Any
from typing import Dict # pylint: disable=unused-import
from typing import List # pylint: disable=unused-import
from typing import Tuple
import logging import logging
import nbxmpp import nbxmpp
from gajim.common import app from gajim.common import app
from gajim.common import helpers from gajim.common import helpers
from gajim.common.types import ConnectionT
log = logging.getLogger('gajim.c.m.annotations') log = logging.getLogger('gajim.c.m.annotations')
class Annotations: class Annotations:
def __init__(self, con): def __init__(self, con: ConnectionT) -> None:
self._con = con self._con = con
self._account = con.name self._account = con.name
self._server = self._con.get_own_jid().getDomain() self._server = self._con.get_own_jid().getDomain()
self.handlers = [] self.handlers = [] # type: List[Tuple[Any, ...]]
self.annotations = {} self.annotations = {} # type: Dict[str, str]
def get_annotations(self) -> None: def get_annotations(self) -> None:
if not app.account_is_connected(self._account): if not app.account_is_connected(self._account):
@ -93,5 +99,5 @@ class Annotations:
log.info('Storing rosternotes successful') log.info('Storing rosternotes successful')
def get_instance(*args, **kwargs): def get_instance(*args: Any, **kwargs: Any) -> Tuple[Annotations, str]:
return Annotations(*args, **kwargs), 'Annotations' return Annotations(*args, **kwargs), 'Annotations'

View File

@ -14,6 +14,11 @@
# XEP-0163: Personal Eventing Protocol # XEP-0163: Personal Eventing Protocol
from typing import Any
from typing import Dict
from typing import List
from typing import Tuple
import logging import logging
import nbxmpp import nbxmpp
@ -22,12 +27,16 @@ from gajim.common import app
from gajim.common.exceptions import StanzaMalformed from gajim.common.exceptions import StanzaMalformed
from gajim.common.nec import NetworkIncomingEvent from gajim.common.nec import NetworkIncomingEvent
from gajim.common.const import PEPHandlerType, PEPEventType from gajim.common.const import PEPHandlerType, PEPEventType
from gajim.common.types import ConnectionT
from gajim.common.types import PEPHandlersDict # pylint: disable=unused-import
from gajim.common.types import PEPNotifyCallback
from gajim.common.types import PEPRetractCallback
log = logging.getLogger('gajim.c.m.pep') log = logging.getLogger('gajim.c.m.pep')
class PEP: class PEP:
def __init__(self, con): def __init__(self, con: ConnectionT) -> None:
self._con = con self._con = con
self._account = con.name self._account = con.name
@ -37,29 +46,40 @@ class PEP:
] ]
self.supported = False self.supported = False
self._pep_handlers = {} self._pep_handlers = {} # type: PEPHandlersDict
self._store_publish_modules = [] self._store_publish_modules = [] # type: List[Any]
def pass_disco(self, from_, identities, _features, _data, _node): def pass_disco(self,
from_: nbxmpp.JID,
identities: List[Dict[str, str]],
_features: List[str],
_data: List[nbxmpp.DataForm],
_node: str) -> None:
for identity in identities: for identity in identities:
if identity['category'] == 'pubsub': if identity['category'] == 'pubsub':
if identity.get('type') == 'pep': if identity.get('type') == 'pep':
log.info('Discovered PEP support: %s', from_) log.info('Discovered PEP support: %s', from_)
self.supported = True self.supported = True
def register_pep_handler(self, namespace, notify_handler, retract_handler): def register_pep_handler(
self,
namespace: str,
notify_handler: PEPNotifyCallback,
retract_handler: PEPRetractCallback) -> None:
if namespace in self._pep_handlers: if namespace in self._pep_handlers:
self._pep_handlers[namespace].append( self._pep_handlers[namespace].append(
(notify_handler, retract_handler)) (notify_handler, retract_handler))
else: else:
self._pep_handlers[namespace] = [(notify_handler, retract_handler)] self._pep_handlers[namespace] = [(notify_handler, retract_handler)]
if notify_handler: if notify_handler:
module_instance = notify_handler.__self__ module_instance = notify_handler.__self__ # type: ignore
if module_instance.store_publish: if module_instance.store_publish:
if module_instance not in self._store_publish_modules: if module_instance not in self._store_publish_modules:
self._store_publish_modules.append(module_instance) self._store_publish_modules.append(module_instance)
def _pep_event_received(self, _con, stanza): def _pep_event_received(self,
_con: ConnectionT,
stanza: nbxmpp.Message) -> None:
jid = stanza.getFrom() jid = stanza.getFrom()
event = stanza.getTag('event', namespace=nbxmpp.NS_PUBSUB_EVENT) event = stanza.getTag('event', namespace=nbxmpp.NS_PUBSUB_EVENT)
items = event.getTag('items') items = event.getTag('items')
@ -98,17 +118,47 @@ class PEP:
handler[PEPHandlerType.NOTIFY](jid, items_[0]) handler[PEPHandlerType.NOTIFY](jid, items_[0])
raise nbxmpp.NodeProcessed raise nbxmpp.NodeProcessed
def send_stored_publish(self): def send_stored_publish(self) -> None:
for module in self._store_publish_modules: for module in self._store_publish_modules:
module.send_stored_publish() module.send_stored_publish()
def reset_stored_publish(self): def reset_stored_publish(self) -> None:
for module in self._store_publish_modules: for module in self._store_publish_modules:
module.reset_stored_publish() module.reset_stored_publish()
class AbstractPEPData:
type_ = PEPEventType.ABSTRACT
def __init__(self, data: Any) -> None:
self.data = data
def as_markup_text(self) -> str: # pylint: disable=no-self-use
'''SHOULD be implemented by subclasses'''
return ''
def __eq__(self, other: Any) -> bool:
return other == self.type_
def __bool__(self) -> bool:
return self.data is not None
def __str__(self) -> str:
return str(self.data)
class AbstractPEPModule: class AbstractPEPModule:
def __init__(self, con, account):
name = ''
namespace = ''
pep_class = AbstractPEPData
store_publish = True
_log = log
def __init__(self,
con: ConnectionT,
account: str) -> None:
self._account = account self._account = account
self._con = con self._con = con
@ -119,7 +169,7 @@ class AbstractPEPModule:
self._pep_notify_received, self._pep_notify_received,
self._pep_retract_received) self._pep_retract_received)
def _pep_notify_received(self, jid, item): def _pep_notify_received(self, jid: nbxmpp.JID, item: nbxmpp.Node) -> None:
try: try:
data = self._extract_info(item) data = self._extract_info(item)
except StanzaMalformed as error: except StanzaMalformed as error:
@ -129,19 +179,19 @@ class AbstractPEPModule:
self._log.info('Received: %s %s', jid, data) self._log.info('Received: %s %s', jid, data)
self._push_event(jid, self.pep_class(data)) self._push_event(jid, self.pep_class(data))
def _pep_retract_received(self, jid, id_): def _pep_retract_received(self, jid: nbxmpp.JID, id_: str) -> None:
self._log.info('Retract: %s %s', jid, id_) self._log.info('Retract: %s %s', jid, id_)
self._push_event(jid, self.pep_class(None)) self._push_event(jid, self.pep_class(None))
def _extract_info(self, item): def _extract_info(self, item: nbxmpp.Node) -> Any:
'''To be implemented by subclasses''' '''To be implemented by subclasses'''
raise NotImplementedError raise NotImplementedError
def _build_node(self, data): def _build_node(self, data: Any) -> nbxmpp.Node:
'''To be implemented by subclasses''' '''To be implemented by subclasses'''
raise NotImplementedError raise NotImplementedError
def _push_event(self, jid, user_pep): def _push_event(self, jid: nbxmpp.JID, user_pep: Any) -> None:
self._notification_received(jid, user_pep) self._notification_received(jid, user_pep)
app.nec.push_incoming_event( app.nec.push_incoming_event(
PEPReceivedEvent(None, conn=self._con, PEPReceivedEvent(None, conn=self._con,
@ -149,7 +199,7 @@ class AbstractPEPModule:
pep_type=self.name, pep_type=self.name,
user_pep=user_pep)) user_pep=user_pep))
def _notification_received(self, jid, user_pep): def _notification_received(self, jid: nbxmpp.JID, user_pep: Any) -> None:
for contact in app.contacts.get_contacts(self._account, str(jid)): for contact in app.contacts.get_contacts(self._account, str(jid)):
if user_pep: if user_pep:
contact.pep[self.name] = user_pep contact.pep[self.name] = user_pep
@ -162,17 +212,17 @@ class AbstractPEPModule:
else: else:
self._con.pep.pop(self.name, None) self._con.pep.pop(self.name, None)
def send_stored_publish(self): def send_stored_publish(self) -> None:
if self._stored_publish is not None: if self._stored_publish is not None:
self._log.info('Send stored publish') self._log.info('Send stored publish')
self.send(self._stored_publish) self.send(self._stored_publish)
self._stored_publish = None self._stored_publish = None
def reset_stored_publish(self): def reset_stored_publish(self) -> None:
self._log.info('Reset stored publish') self._log.info('Reset stored publish')
self._stored_publish = None self._stored_publish = None
def send(self, data): def send(self, data: Any) -> None:
if not self._con.get_module('PEP').supported: if not self._con.get_module('PEP').supported:
return return
@ -191,7 +241,7 @@ class AbstractPEPModule:
self._con.get_module('PubSub').send_pb_publish( self._con.get_module('PubSub').send_pb_publish(
'', self.namespace, item, 'current') '', self.namespace, item, 'current')
def retract(self): def retract(self) -> None:
if not self._con.get_module('PEP').supported: if not self._con.get_module('PEP').supported:
return return
self.send(None) self.send(None)
@ -199,27 +249,9 @@ class AbstractPEPModule:
'', self.namespace, 'current') '', self.namespace, 'current')
class AbstractPEPData:
type_ = PEPEventType
def asMarkupText(self):
'''SHOULD be implemented by subclasses'''
return ''
def __eq__(self, other):
return other == self.type_
def __bool__(self):
return self.data is not None
def __str__(self):
return str(self.data)
class PEPReceivedEvent(NetworkIncomingEvent): class PEPReceivedEvent(NetworkIncomingEvent):
name = 'pep-received' name = 'pep-received'
def get_instance(*args, **kwargs): def get_instance(*args: Any, **kwargs: Any) -> Tuple[PEP, str]:
return PEP(*args, **kwargs), 'PEP' return PEP(*args, **kwargs), 'PEP'

View File

@ -14,6 +14,9 @@
# XEP-0199: XMPP Ping # XEP-0199: XMPP Ping
from typing import Any
from typing import Tuple
import logging import logging
import time import time
@ -21,12 +24,14 @@ import nbxmpp
from gajim.common import app from gajim.common import app
from gajim.common.nec import NetworkIncomingEvent from gajim.common.nec import NetworkIncomingEvent
from gajim.common.types import ConnectionT
from gajim.common.types import ContactT
log = logging.getLogger('gajim.c.m.ping') log = logging.getLogger('gajim.c.m.ping')
class Ping: class Ping:
def __init__(self, con): def __init__(self, con: ConnectionT) -> None:
self._con = con self._con = con
self._account = con.name self._account = con.name
self._alarm_time = None self._alarm_time = None
@ -68,7 +73,7 @@ class Ping:
log.warning('No reply received for keepalive ping. Reconnecting...') log.warning('No reply received for keepalive ping. Reconnecting...')
self._con.disconnectedReconnCB() self._con.disconnectedReconnCB()
def send_ping(self, contact): def send_ping(self, contact: ContactT) -> None:
if not app.account_is_connected(self._account): if not app.account_is_connected(self._account):
return return
@ -84,7 +89,11 @@ class Ping:
app.nec.push_incoming_event( app.nec.push_incoming_event(
PingSentEvent(None, conn=self._con, contact=contact)) PingSentEvent(None, conn=self._con, contact=contact))
def _pong_received(self, _con, stanza, ping_time, contact): def _pong_received(self,
_con: ConnectionT,
stanza: nbxmpp.Iq,
ping_time: int,
contact: ContactT) -> None:
if not nbxmpp.isResultNode(stanza): if not nbxmpp.isResultNode(stanza):
log.info('Error: %s', stanza.getError()) log.info('Error: %s', stanza.getError())
app.nec.push_incoming_event( app.nec.push_incoming_event(
@ -98,7 +107,9 @@ class Ping:
contact=contact, contact=contact,
seconds=diff)) seconds=diff))
def _answer_request(self, _con, stanza): def _answer_request(self,
_con: ConnectionT,
stanza: nbxmpp.Iq) -> None:
iq = stanza.buildReply('result') iq = stanza.buildReply('result')
ping = iq.getTag('ping') ping = iq.getTag('ping')
if ping is not None: if ping is not None:
@ -120,5 +131,5 @@ class PingErrorEvent(NetworkIncomingEvent):
name = 'ping-error' name = 'ping-error'
def get_instance(*args, **kwargs): def get_instance(*args: Any, **kwargs: Any) -> Tuple[Ping, str]:
return Ping(*args, **kwargs), 'Ping' return Ping(*args, **kwargs), 'Ping'

View File

@ -33,7 +33,7 @@ class UserActivityData(AbstractPEPData):
def __init__(self, activity): def __init__(self, activity):
self.data = activity self.data = activity
def asMarkupText(self): def as_markup_text(self):
pep = self.data pep = self.data
activity = pep['activity'] activity = pep['activity']
subactivity = pep['subactivity'] if 'subactivity' in pep else None subactivity = pep['subactivity'] if 'subactivity' in pep else None

View File

@ -35,7 +35,7 @@ class UserLocationData(AbstractPEPData):
self._pep_specific_data = location self._pep_specific_data = location
self.data = location self.data = location
def asMarkupText(self): def as_markup_text(self):
location = self.data location = self.data
location_string = '' location_string = ''

View File

@ -14,6 +14,12 @@
# XEP-0107: User Mood # XEP-0107: User Mood
from typing import Any
from typing import Dict
from typing import List # pylint: disable=unused-import
from typing import Optional
from typing import Tuple
import logging import logging
import nbxmpp import nbxmpp
@ -22,6 +28,7 @@ from gi.repository import GLib
from gajim.common.const import PEPEventType, MOODS from gajim.common.const import PEPEventType, MOODS
from gajim.common.exceptions import StanzaMalformed from gajim.common.exceptions import StanzaMalformed
from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData
from gajim.common.types import ConnectionT
log = logging.getLogger('gajim.c.m.user_mood') log = logging.getLogger('gajim.c.m.user_mood')
@ -30,10 +37,12 @@ class UserMoodData(AbstractPEPData):
type_ = PEPEventType.MOOD type_ = PEPEventType.MOOD
def __init__(self, mood): def __init__(self, mood: Optional[Dict[str, str]]) -> None:
self.data = mood self.data = mood
def asMarkupText(self): def as_markup_text(self) -> str:
if self.data is None:
return ''
mood = self._translate_mood(self.data['mood']) mood = self._translate_mood(self.data['mood'])
markuptext = '<b>%s</b>' % GLib.markup_escape_text(mood) markuptext = '<b>%s</b>' % GLib.markup_escape_text(mood)
if 'text' in self.data: if 'text' in self.data:
@ -42,7 +51,7 @@ class UserMoodData(AbstractPEPData):
return markuptext return markuptext
@staticmethod @staticmethod
def _translate_mood(mood): def _translate_mood(mood: str) -> str:
if mood in MOODS: if mood in MOODS:
return MOODS[mood] return MOODS[mood]
return mood return mood
@ -56,12 +65,12 @@ class UserMood(AbstractPEPModule):
store_publish = True store_publish = True
_log = log _log = log
def __init__(self, con): def __init__(self, con: ConnectionT) -> None:
AbstractPEPModule.__init__(self, con, con.name) AbstractPEPModule.__init__(self, con, con.name)
self.handlers = [] self.handlers = [] # type: List[Tuple[Any, ...]]
def _extract_info(self, item): def _extract_info(self, item: nbxmpp.Node) -> Optional[Dict[str, str]]:
mood_dict = {} mood_dict = {}
mood_tag = item.getTag('mood', namespace=nbxmpp.NS_MOOD) mood_tag = item.getTag('mood', namespace=nbxmpp.NS_MOOD)
if mood_tag is None: if mood_tag is None:
@ -76,7 +85,7 @@ class UserMood(AbstractPEPModule):
return mood_dict or None return mood_dict or None
def _build_node(self, data): def _build_node(self, data: Optional[Tuple[str, str]]) -> nbxmpp.Node:
item = nbxmpp.Node('mood', {'xmlns': nbxmpp.NS_MOOD}) item = nbxmpp.Node('mood', {'xmlns': nbxmpp.NS_MOOD})
if data is None: if data is None:
return return
@ -88,5 +97,5 @@ class UserMood(AbstractPEPModule):
return item return item
def get_instance(*args, **kwargs): def get_instance(*args: Any, **kwargs: Any) -> Tuple[UserMood, str]:
return UserMood(*args, **kwargs), 'UserMood' return UserMood(*args, **kwargs), 'UserMood'

View File

@ -14,6 +14,11 @@
# XEP-0172: User Nickname # XEP-0172: User Nickname
from typing import Any
from typing import List # pylint: disable=unused-import
from typing import Optional
from typing import Tuple
import logging import logging
import nbxmpp import nbxmpp
@ -22,6 +27,7 @@ from gajim.common import app
from gajim.common.const import PEPEventType from gajim.common.const import PEPEventType
from gajim.common.exceptions import StanzaMalformed from gajim.common.exceptions import StanzaMalformed
from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData
from gajim.common.types import ConnectionT
log = logging.getLogger('gajim.c.m.user_nickname') log = logging.getLogger('gajim.c.m.user_nickname')
@ -30,10 +36,10 @@ class UserNicknameData(AbstractPEPData):
type_ = PEPEventType.NICKNAME type_ = PEPEventType.NICKNAME
def __init__(self, nickname): def __init__(self, nickname: Optional[str]) -> None:
self.data = nickname self.data = nickname
def get_nick(self): def get_nick(self) -> str:
return self.data or '' return self.data or ''
@ -45,12 +51,12 @@ class UserNickname(AbstractPEPModule):
store_publish = True store_publish = True
_log = log _log = log
def __init__(self, con): def __init__(self, con: ConnectionT) -> None:
AbstractPEPModule.__init__(self, con, con.name) AbstractPEPModule.__init__(self, con, con.name)
self.handlers = [] self.handlers = [] # type: List[Tuple[Any, ...]]
def _extract_info(self, item): def _extract_info(self, item: nbxmpp.Node) -> Optional[str]:
nick = '' nick = ''
child = item.getTag('nick', namespace=nbxmpp.NS_NICK) child = item.getTag('nick', namespace=nbxmpp.NS_NICK)
if child is None: if child is None:
@ -59,14 +65,16 @@ class UserNickname(AbstractPEPModule):
return nick or None return nick or None
def _build_node(self, data): def _build_node(self, data: Optional[str]) -> Optional[nbxmpp.Node]:
item = nbxmpp.Node('nick', {'xmlns': nbxmpp.NS_NICK}) item = nbxmpp.Node('nick', {'xmlns': nbxmpp.NS_NICK})
if data is None: if data is None:
return return None
item.addData(data) item.addData(data)
return item return item
def _notification_received(self, jid, user_pep): def _notification_received(self,
jid: nbxmpp.JID,
user_pep: UserNicknameData) -> None:
for contact in app.contacts.get_contacts(self._account, str(jid)): for contact in app.contacts.get_contacts(self._account, str(jid)):
contact.contact_name = user_pep.get_nick() contact.contact_name = user_pep.get_nick()
@ -78,12 +86,12 @@ class UserNickname(AbstractPEPModule):
'accounts', self._account, 'name') 'accounts', self._account, 'name')
def parse_nickname(stanza): def parse_nickname(stanza: nbxmpp.Node) -> str:
nick = stanza.getTag('nick', namespace=nbxmpp.NS_NICK) nick = stanza.getTag('nick', namespace=nbxmpp.NS_NICK)
if nick is None: if nick is None:
return '' return ''
return nick.getData() return nick.getData()
def get_instance(*args, **kwargs): def get_instance(*args: Any, **kwargs: Any) -> Tuple[UserNickname, str]:
return UserNickname(*args, **kwargs), 'UserNickname' return UserNickname(*args, **kwargs), 'UserNickname'

View File

@ -14,14 +14,23 @@
# XEP-0118: User Tune # XEP-0118: User Tune
from typing import Any
from typing import List # pylint: disable=unused-import
from typing import Dict
from typing import Optional
from typing import Tuple
import logging import logging
import nbxmpp import nbxmpp
from gi.repository import GLib from gi.repository import GLib
from gajim.common.i18n import _
from gajim.common.const import PEPEventType from gajim.common.const import PEPEventType
from gajim.common.exceptions import StanzaMalformed from gajim.common.exceptions import StanzaMalformed
from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData
from gajim.common.types import ConnectionT
from gajim.common.types import UserTuneDataT
log = logging.getLogger('gajim.c.m.user_tune') log = logging.getLogger('gajim.c.m.user_tune')
@ -30,10 +39,13 @@ class UserTuneData(AbstractPEPData):
type_ = PEPEventType.TUNE type_ = PEPEventType.TUNE
def __init__(self, tune): def __init__(self, tune: Optional[Dict[str, str]]) -> None:
self.data = tune self.data = tune
def asMarkupText(self): def as_markup_text(self) -> str:
if self.data is None:
return ''
tune = self.data tune = self.data
artist = tune.get('artist', _('Unknown Artist')) artist = tune.get('artist', _('Unknown Artist'))
@ -60,12 +72,12 @@ class UserTune(AbstractPEPModule):
store_publish = True store_publish = True
_log = log _log = log
def __init__(self, con): def __init__(self, con: ConnectionT) -> None:
AbstractPEPModule.__init__(self, con, con.name) AbstractPEPModule.__init__(self, con, con.name)
self.handlers = [] self.handlers = [] # type: List[Tuple[Any, ...]]
def _extract_info(self, item): def _extract_info(self, item: nbxmpp.Node) -> Optional[Dict[str, str]]:
tune_dict = {} tune_dict = {}
tune_tag = item.getTag('tune', namespace=self.namespace) tune_tag = item.getTag('tune', namespace=self.namespace)
if tune_tag is None: if tune_tag is None:
@ -80,7 +92,7 @@ class UserTune(AbstractPEPModule):
return tune_dict or None return tune_dict or None
def _build_node(self, data): def _build_node(self, data: UserTuneDataT) -> nbxmpp.Node:
item = nbxmpp.Node('tune', {'xmlns': nbxmpp.NS_TUNE}) item = nbxmpp.Node('tune', {'xmlns': nbxmpp.NS_TUNE})
if data is None: if data is None:
return item return item
@ -98,5 +110,5 @@ class UserTune(AbstractPEPModule):
return item return item
def get_instance(*args, **kwargs): def get_instance(*args: Any, **kwargs: Any) -> Tuple[UserTune, str]:
return UserTune(*args, **kwargs), 'UserTune' return UserTune(*args, **kwargs), 'UserTune'

View File

@ -22,11 +22,12 @@ Network Events Controller.
:license: GPL :license: GPL
''' '''
#from plugins.helpers import log from typing import List # pylint: disable=unused-import
from gajim.common import app from gajim.common import app
class NetworkEventsController(object):
class NetworkEventsController:
def __init__(self): def __init__(self):
self.incoming_events_generators = {} self.incoming_events_generators = {}
''' '''
@ -45,7 +46,7 @@ class NetworkEventsController(object):
for base_event_name in event_class.base_network_events: for base_event_name in event_class.base_network_events:
event_list = self.incoming_events_generators.setdefault( event_list = self.incoming_events_generators.setdefault(
base_event_name, []) base_event_name, [])
if not event_class in event_list: if event_class not in event_list:
event_list.append(event_class) event_list.append(event_class)
def unregister_incoming_event(self, event_class): def unregister_incoming_event(self, event_class):
@ -58,7 +59,7 @@ class NetworkEventsController(object):
for base_event_name in event_class.base_network_events: for base_event_name in event_class.base_network_events:
event_list = self.outgoing_events_generators.setdefault( event_list = self.outgoing_events_generators.setdefault(
base_event_name, []) base_event_name, [])
if not event_class in event_list: if event_class not in event_list:
event_list.append(event_class) event_list.append(event_class)
def unregister_outgoing_event(self, event_class): def unregister_outgoing_event(self, event_class):
@ -89,12 +90,12 @@ class NetworkEventsController(object):
base_event_name = event_object.name base_event_name = event_object.name
if base_event_name in self.incoming_events_generators: if base_event_name in self.incoming_events_generators:
for new_event_class in self.incoming_events_generators[ for new_event_class in self.incoming_events_generators[
base_event_name]: base_event_name]:
new_event_object = new_event_class(None, new_event_object = new_event_class(
base_event=event_object) None, base_event=event_object)
if new_event_object.generate(): if new_event_object.generate():
if not app.ged.raise_event(new_event_object.name, if not app.ged.raise_event(new_event_object.name,
new_event_object): new_event_object):
self._generate_events_based_on_incoming_event( self._generate_events_based_on_incoming_event(
new_event_object) new_event_object)
@ -110,16 +111,17 @@ class NetworkEventsController(object):
base_event_name = event_object.name base_event_name = event_object.name
if base_event_name in self.outgoing_events_generators: if base_event_name in self.outgoing_events_generators:
for new_event_class in self.outgoing_events_generators[ for new_event_class in self.outgoing_events_generators[
base_event_name]: base_event_name]:
new_event_object = new_event_class(None, new_event_object = new_event_class(
base_event=event_object) None, base_event=event_object)
if new_event_object.generate(): if new_event_object.generate():
if not app.ged.raise_event(new_event_object.name, if not app.ged.raise_event(new_event_object.name,
new_event_object): new_event_object):
self._generate_events_based_on_outgoing_event( self._generate_events_based_on_outgoing_event(
new_event_object) new_event_object)
class NetworkEvent(object):
class NetworkEvent:
name = '' name = ''
def __init__(self, new_name, **kwargs): def __init__(self, new_name, **kwargs):
@ -133,14 +135,14 @@ class NetworkEvent(object):
def init(self): def init(self):
pass pass
def generate(self): def generate(self):
''' '''
Generates new event (sets it's attributes) based on event object. Generates new event (sets it's attributes) based on event object.
Base event object name is one of those in `base_network_events`. Base event object name is one of those in `base_network_events`.
Reference to base event object is stored in `self.base_event` attribute. Reference to base event object is stored in `self.base_event`
attribute.
Note that this is a reference, so modifications to that event object Note that this is a reference, so modifications to that event object
are possible before dispatching to Global Events Dispatcher. are possible before dispatching to Global Events Dispatcher.
@ -159,15 +161,16 @@ class NetworkEvent(object):
if k not in ('name', 'base_network_events'): if k not in ('name', 'base_network_events'):
setattr(self, k, v) setattr(self, k, v)
class NetworkIncomingEvent(NetworkEvent): class NetworkIncomingEvent(NetworkEvent):
base_network_events = [] base_network_events = [] # type: List[str]
''' '''
Names of base network events that new event is going to be generated on. Names of base network events that new event is going to be generated on.
''' '''
class NetworkOutgoingEvent(NetworkEvent): class NetworkOutgoingEvent(NetworkEvent):
base_network_events = [] base_network_events = [] # type: List[str]
''' '''
Names of base network events that new event is going to be generated on. Names of base network events that new event is going to be generated on.
''' '''

View File

@ -67,7 +67,7 @@ class AbstractPEP(object):
else: else:
acc.pep[self.type_] = self acc.pep[self.type_] = self
def asMarkupText(self): def as_markup_text(self):
'''SHOULD be implemented by subclasses''' '''SHOULD be implemented by subclasses'''
return '' return ''

47
gajim/common/types.py Normal file
View File

@ -0,0 +1,47 @@
# 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/>.
# Types for typechecking
from typing import Callable
from typing import Dict
from typing import List
from typing import Optional
from typing import Tuple
from typing import Union
from typing import TYPE_CHECKING
import nbxmpp
from gajim.common.const import PathType, PathLocation
if TYPE_CHECKING:
# pylint: disable=unused-import
from gajim.common.connection import Connection
from gajim.common.zeroconf.connection_zeroconf import ConnectionZeroconf
from gajim.common.contacts import Contact
from gajim.common.contacts import GC_Contact
ConnectionT = Union['Connection', 'ConnectionZeroconf']
ContactT = Union['Contact', 'GC_Contact']
UserTuneDataT = Optional[Tuple[str, str, str, str, str]]
# PEP
PEPNotifyCallback = Callable[[nbxmpp.JID, nbxmpp.Node], None]
PEPRetractCallback = Callable[[nbxmpp.JID, str], None]
PEPHandlersDict = Dict[str, List[Tuple[PEPNotifyCallback, PEPRetractCallback]]]
# Configpaths
PathTuple = Tuple[Optional[PathLocation], str, Optional[PathType]]

View File

@ -20,6 +20,7 @@ from collections import namedtuple
from gi.repository import GLib from gi.repository import GLib
from gajim.common.app import app from gajim.common.app import app
from gajim.common.i18n import _
from gajim.gtk import ErrorDialog from gajim.gtk import ErrorDialog
from gajim.gtk import InformationDialog from gajim.gtk import InformationDialog

View File

@ -38,6 +38,7 @@ from gajim import dataforms_widget
from random import randrange from random import randrange
from gajim.common import ged from gajim.common import ged
from gajim.common.i18n import _
from gajim.common.const import ACTIVITIES from gajim.common.const import ACTIVITIES
from gajim.common.const import MOODS from gajim.common.const import MOODS

View File

@ -42,11 +42,12 @@
import types import types
import weakref import weakref
import nbxmpp
from gi.repository import GLib from gi.repository import GLib
from gi.repository import Gtk from gi.repository import Gtk
from gi.repository import Gdk from gi.repository import Gdk
from gi.repository import GdkPixbuf from gi.repository import GdkPixbuf
from gi.repository import Pango
from gajim.gtk import ErrorDialog from gajim.gtk import ErrorDialog
from gajim.gtk import InformationDialog from gajim.gtk import InformationDialog
@ -54,13 +55,11 @@ from gajim import gtkgui_helpers
from gajim import groups from gajim import groups
from gajim import adhoc_commands from gajim import adhoc_commands
from gajim import search_window from gajim import search_window
from gajim import gui_menu_builder
from gajim.gtk import ServiceRegistration from gajim.gtk import ServiceRegistration
from gajim.common import app from gajim.common import app
import nbxmpp from gajim.common.i18n import _
from gajim.common import helpers from gajim.common import helpers
from gajim.common import ged
from gajim.common.const import StyleAttr from gajim.common.const import StyleAttr
LABELS = { LABELS = {

View File

@ -28,13 +28,13 @@ import os
import sys import sys
import locale import locale
import signal import signal
signal.signal(signal.SIGINT, signal.SIG_DFL) # ^C exits the application
from gajim.common import exceptions from gajim.common import exceptions
from gajim.common import i18n # This installs _() function from gajim.common.i18n import _
from gajim.common.i18n import Q_ from gajim.common.i18n import Q_
signal.signal(signal.SIGINT, signal.SIG_DFL) # ^C exits the application
try: try:
PREFERRED_ENCODING = locale.getpreferredencoding() PREFERRED_ENCODING = locale.getpreferredencoding()
except Exception: except Exception:

View File

@ -18,6 +18,7 @@ from gi.repository import Gtk
from gajim.common import app from gajim.common import app
from gajim.common import ged from gajim.common import ged
from gajim.common import helpers from gajim.common import helpers
from gajim.common.i18n import _
from gajim.gtk import ErrorDialog from gajim.gtk import ErrorDialog
from gajim.gtk.util import get_builder from gajim.gtk.util import get_builder

View File

@ -25,6 +25,7 @@ from gi.repository import GdkPixbuf
from gi.repository import GObject from gi.repository import GObject
from gajim.common import app from gajim.common import app
from gajim.common.i18n import _
Filter = namedtuple('Filter', 'name pattern default') Filter = namedtuple('Filter', 'name pattern default')

View File

@ -19,6 +19,7 @@ from gi.repository import Gtk
from gajim.common import app from gajim.common import app
from gajim.common.modules import dataforms from gajim.common.modules import dataforms
from gajim.common.i18n import _
from gajim.gtk.dataform import DataFormWidget from gajim.gtk.dataform import DataFormWidget
log = logging.getLogger('gajim.gtk.registration') log = logging.getLogger('gajim.gtk.registration')

View File

@ -21,6 +21,7 @@ from gi.repository import Gtk
from gi.repository import Gdk from gi.repository import Gdk
from gajim.common import app from gajim.common import app
from gajim.common.i18n import _
from gajim.common.const import StyleAttr, DialogButton, ButtonAction from gajim.common.const import StyleAttr, DialogButton, ButtonAction
from gajim.common.connection_handlers_events import StyleChanged from gajim.common.connection_handlers_events import StyleChanged
from gajim.gtk import ErrorDialog from gajim.gtk import ErrorDialog

View File

@ -2127,7 +2127,7 @@ class Interface:
if app.connections[acct].music_track_info == music_track_info: if app.connections[acct].music_track_info == music_track_info:
continue continue
app.connections[acct].get_module('UserTune').send( app.connections[acct].get_module('UserTune').send(
(artist, title, source, None, None)) (artist, title, source, '', ''))
app.connections[acct].music_track_info = music_track_info app.connections[acct].music_track_info = music_track_info
def read_sleepy(self): def read_sleepy(self):

View File

@ -79,6 +79,7 @@ if is_standalone():
configpaths.init() configpaths.init()
from gajim.common import app from gajim.common import app
from gajim.common.i18n import _
from gajim.common.const import JIDConstant, KindConstant from gajim.common.const import JIDConstant, KindConstant
from gajim.common import helpers from gajim.common import helpers
from gajim.gtk import YesNoDialog from gajim.gtk import YesNoDialog

View File

@ -24,6 +24,7 @@ from gi.repository import GLib
from gi.repository import Pango from gi.repository import Pango
from gajim.common import app from gajim.common import app
from gajim.common.i18n import _
from gajim import gtkgui_helpers from gajim import gtkgui_helpers
if app.is_installed('GSPELL'): if app.is_installed('GSPELL'):

View File

@ -14,15 +14,18 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Gajim. If not, see <http://www.gnu.org/licenses/>. # along with Gajim. If not, see <http://www.gnu.org/licenses/>.
from typing import cast
import os
import locale import locale
import gettext import gettext
from os import path as os_path
import os
from gajim.common import app from gajim.common import app
from gajim.common import configpaths from gajim.common import configpaths
APP = 'gajim_plugins' APP = 'gajim_plugins'
plugins_locale_dir = os_path.join(configpaths.get('PLUGINS_USER'), 'locale') plugin_user_dir = cast(str, configpaths.get('PLUGINS_USER'))
plugins_locale_dir = os.path.join(plugin_user_dir, 'locale')
if os.name != 'nt': if os.name != 'nt':
locale.setlocale(locale.LC_ALL, '') locale.setlocale(locale.LC_ALL, '')

View File

@ -528,25 +528,25 @@ class RosterTooltip(Gtk.Window, StatusTable):
to the given property list. to the given property list.
""" """
if 'mood' in contact.pep: if 'mood' in contact.pep:
mood = contact.pep['mood'].asMarkupText() mood = contact.pep['mood'].as_markup_text()
self.mood.set_markup(mood) self.mood.set_markup(mood)
self.mood.show() self.mood.show()
self.mood_label.show() self.mood_label.show()
if 'activity' in contact.pep: if 'activity' in contact.pep:
activity = contact.pep['activity'].asMarkupText() activity = contact.pep['activity'].as_markup_text()
self.activity.set_markup(activity) self.activity.set_markup(activity)
self.activity.show() self.activity.show()
self.activity_label.show() self.activity_label.show()
if 'tune' in contact.pep: if 'tune' in contact.pep:
tune = contact.pep['tune'].asMarkupText() tune = contact.pep['tune'].as_markup_text()
self.tune.set_markup(tune) self.tune.set_markup(tune)
self.tune.show() self.tune.show()
self.tune_label.show() self.tune_label.show()
if 'geoloc' in contact.pep: if 'geoloc' in contact.pep:
location = contact.pep['geoloc'].asMarkupText() location = contact.pep['geoloc'].as_markup_text()
self.location.set_markup(location) self.location.set_markup(location)
self.location.show() self.location.show()
self.location_label.show() self.location_label.show()