From 77c9b3a98df2634037015901c32f3b8ce916e215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20H=C3=B6rist?= Date: Thu, 13 Sep 2018 23:56:12 +0200 Subject: [PATCH] Add annotations and fix pylint/mypy errors --- gajim/application.py | 3 +- gajim/chat_control.py | 2 +- gajim/command_system/dispatcher.py | 21 +++- gajim/command_system/implementation/custom.py | 1 + .../command_system/implementation/execute.py | 1 + .../command_system/implementation/standard.py | 1 + gajim/common/app.py | 8 +- gajim/common/config.py | 1 + gajim/common/configpaths.py | 77 +++++++----- gajim/common/connection_handlers_events.py | 56 --------- gajim/common/const.py | 17 +-- gajim/common/dbus_support.py | 1 + gajim/common/helpers.py | 1 + gajim/common/i18n.py | 6 +- gajim/common/modules/__init__.py | 22 ++-- gajim/common/modules/annotations.py | 14 ++- gajim/common/modules/pep.py | 110 +++++++++++------- gajim/common/modules/ping.py | 21 +++- gajim/common/modules/user_activity.py | 2 +- gajim/common/modules/user_location.py | 2 +- gajim/common/modules/user_mood.py | 25 ++-- gajim/common/modules/user_nickname.py | 28 +++-- gajim/common/modules/user_tune.py | 26 +++-- gajim/common/nec.py | 37 +++--- gajim/common/pep.py | 2 +- gajim/common/types.py | 47 ++++++++ gajim/dialog_messages.py | 1 + gajim/dialogs.py | 1 + gajim/disco.py | 7 +- gajim/gajim_remote.py | 6 +- gajim/gtk/add_contact.py | 1 + gajim/gtk/filechoosers.py | 1 + gajim/gtk/service_registration.py | 1 + gajim/gtk/themes.py | 1 + gajim/gui_interface.py | 2 +- gajim/history_manager.py | 1 + gajim/message_textview.py | 1 + gajim/plugins/plugins_i18n.py | 9 +- gajim/tooltips.py | 8 +- 39 files changed, 349 insertions(+), 223 deletions(-) create mode 100644 gajim/common/types.py diff --git a/gajim/application.py b/gajim/application.py index c46a39c05..7ab32c38b 100644 --- a/gajim/application.py +++ b/gajim/application.py @@ -273,7 +273,8 @@ class GajimApplication(Gtk.Application): self.activate() return 0 - def _handle_local_options(self, application, + def _handle_local_options(self, + application: Gtk.Application, options: GLib.VariantDict) -> int: # Parse all options that have to be executed before ::startup if options.contains('profile'): diff --git a/gajim/chat_control.py b/gajim/chat_control.py index cd2b0419f..0687c6527 100644 --- a/gajim/chat_control.py +++ b/gajim/chat_control.py @@ -413,7 +413,7 @@ class ChatControl(ChatControlBase): img = self._pep_images[pep_type] if pep_type in pep: 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() else: img.hide() diff --git a/gajim/command_system/dispatcher.py b/gajim/command_system/dispatcher.py index ccdce57b5..11de2ea70 100644 --- a/gajim/command_system/dispatcher.py +++ b/gajim/command_system/dispatcher.py @@ -31,62 +31,77 @@ to automatic discovery and dispatching, also features manual control 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 -COMMANDS = {} -CONTAINERS = {} +COMMANDS = {} # type: Dict[Any, Any] +CONTAINERS = {} # type: Dict[Any, Any] + def add_host(host): CONTAINERS[host] = [] + def remove_host(host): remove(CONTAINERS, host) + def add_container(container): for host in container.HOSTS: CONTAINERS[host].append(container) + def remove_container(container): for host in container.HOSTS: remove(CONTAINERS[host], container) + def add_commands(container): commands = COMMANDS.setdefault(container, {}) for command in traverse_commands(container): for name in command.names: commands[name] = command + def remove_commands(container): remove(COMMANDS, container) + def traverse_commands(container): for name in dir(container): attribute = getattr(container, name) if is_command(attribute): yield attribute + def is_command(attribute): from gajim.command_system.framework import Command return isinstance(attribute, Command) + def is_root(namespace): metaclass = namespace.get("__metaclass__", None) if not metaclass: return False return issubclass(metaclass, Dispatchable) + def get_command(host, name): for container in CONTAINERS[host]: command = COMMANDS[container].get(name) if command: return command + def list_commands(host): for container in CONTAINERS[host]: commands = COMMANDS[container] for name, command in commands.items(): yield name, command + class Dispatchable(type): # pylint: disable=no-value-for-parameter def __init__(self, name, bases, namespace): @@ -99,6 +114,7 @@ class Dispatchable(type): if self.AUTOMATIC: self.enable() + class Host(Dispatchable): def enable(self): @@ -107,6 +123,7 @@ class Host(Dispatchable): def disable(self): remove_host(self) + class Container(Dispatchable): def enable(self): diff --git a/gajim/command_system/implementation/custom.py b/gajim/command_system/implementation/custom.py index 5380c2699..6aace07dc 100644 --- a/gajim/command_system/implementation/custom.py +++ b/gajim/command_system/implementation/custom.py @@ -34,6 +34,7 @@ code in here will not be executed and commands defined here will not be detected. """ +from gajim.common.i18n import _ from gajim.command_system.framework import CommandContainer, command, doc from gajim.command_system.implementation.hosts import ChatCommands, PrivateChatCommands, GroupChatCommands diff --git a/gajim/command_system/implementation/execute.py b/gajim/command_system/implementation/execute.py index 2766cbdbe..4e6eb9530 100644 --- a/gajim/command_system/implementation/execute.py +++ b/gajim/command_system/implementation/execute.py @@ -37,6 +37,7 @@ from os.path import expanduser from gi.repository import GLib +from gajim.common.i18n import _ from gajim.command_system.framework import CommandContainer, command, doc from gajim.command_system.implementation.hosts import ChatCommands, PrivateChatCommands, GroupChatCommands diff --git a/gajim/command_system/implementation/standard.py b/gajim/command_system/implementation/standard.py index 58f2fc997..89b3cf9e8 100644 --- a/gajim/command_system/implementation/standard.py +++ b/gajim/command_system/implementation/standard.py @@ -23,6 +23,7 @@ from datetime import date from gajim import dialogs from gajim.common import app from gajim.common import helpers +from gajim.common.i18n import _ from gajim.common.exceptions import GajimGeneralException from gajim.common.const import KindConstant diff --git a/gajim/common/app.py b/gajim/common/app.py index 3541964e4..61562830d 100644 --- a/gajim/common/app.py +++ b/gajim/common/app.py @@ -42,7 +42,7 @@ from gajim.common.contacts import LegacyContactsAPI from gajim.common.events import Events 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 config = c_config.Config() version = gajim.__version__ @@ -52,10 +52,10 @@ ipython_window = None app = None # Gtk.Application ged = ged_module.GlobalEventsDispatcher() # Global Events Dispatcher -nec = None # Network Events Controller +nec = None # type: gajim.common.nec.NetworkEventsController plugin_manager = None # Plugins Manager -logger = None +logger = None # type: gajim.common.logger.Logger # For backwards compatibility needed # some plugins use that @@ -122,7 +122,7 @@ SHOW_LIST = ['offline', 'connecting', 'online', 'chat', 'away', 'xa', 'dnd', ZEROCONF_ACC_NAME = 'Local' # These will be set in app.gui_interface. -idlequeue = None +idlequeue = None # type: nbxmpp.idlequeue.IdleQueue socks5queue = None gajim_identity = {'type': 'pc', 'category': 'client', 'name': 'Gajim'} diff --git a/gajim/common/config.py b/gajim/common/config.py index 0d9138268..a9741a41c 100644 --- a/gajim/common/config.py +++ b/gajim/common/config.py @@ -32,6 +32,7 @@ from gi.repository import GLib from enum import IntEnum, unique import gajim +from gajim.common.i18n import _ @unique diff --git a/gajim/common/configpaths.py b/gajim/common/configpaths.py index f3799b9a1..020e85244 100644 --- a/gajim/common/configpaths.py +++ b/gajim/common/configpaths.py @@ -19,82 +19,90 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . +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 sys import tempfile from pathlib import Path import gajim +from gajim.common.i18n import _ 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 gajim.IS_FLATPAK: return ['/app/plugins', _paths['PLUGINS_BASE']] - else: - return [_paths['PLUGINS_BASE'], - _paths['PLUGINS_USER']] + return [_paths['PLUGINS_BASE'], + _paths['PLUGINS_USER']] return _paths[key] -def get_paths(type_): +def get_paths(type_: PathType) -> Generator[str, None, None]: for key, value in _paths.items(): - location, path, path_type = value + path_type = value[2] if type_ != path_type: continue yield _paths[key] 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 -def set_profile(profile: str): +def set_profile(profile: str) -> None: _paths.profile = profile -def set_config_root(config_root: str): +def set_config_root(config_root: str) -> None: _paths.custom_config_root = config_root -def init(): +def init() -> None: _paths.init() -def create_paths(): +def create_paths() -> None: for path in get_paths(PathType.FOLDER): if not isinstance(path, Path): - path = Path(path) + path_ = Path(path) - if path.is_file(): - print(_('%s is a file but it should be a directory') % path) + if path_.is_file(): + print(_('%s is a file but it should be a directory') % path_) print(_('Gajim will now exit')) sys.exit() - if not path.exists(): - for parent_path in reversed(path.parents): + if not path_.exists(): + for parent_path in reversed(path_.parents): # Create all parent folders # don't use mkdir(parent=True), as it ignores `mode` # when creating the parents if not parent_path.exists(): print(('creating %s directory') % parent_path) parent_path.mkdir(mode=0o700) - print(('creating %s directory') % path) - path.mkdir(mode=0o700) + print(('creating %s directory') % path_) + path_.mkdir(mode=0o700) class ConfigPaths: - def __init__(self): - self._paths = {} + def __init__(self) -> None: + self._paths = {} # type: Dict[str, PathTuple] self.profile = '' self.profile_separation = False - self.custom_config_root = None + self.custom_config_root = None # type: Optional[str] if os.name == 'nt': try: @@ -133,23 +141,23 @@ class ConfigPaths: ] 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] if location == PathLocation.CONFIG: return os.path.join(self.config_root, path) - elif location == PathLocation.CACHE: + if location == PathLocation.CACHE: 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 path - def items(self): + def items(self) -> Generator[Tuple[str, PathTuple], None, None]: for key, value in self._paths.items(): yield (key, value) - def _prepare(self, path, unique): + def _prepare(self, path: str, unique: bool) -> str: if os.name == 'nt': path = path.capitalize() if self.profile: @@ -157,7 +165,12 @@ class ConfigPaths: return '%s.%s' % (path, self.profile) 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: path = self._prepare(path, unique) self._paths[name] = (location, path, path_type) @@ -175,7 +188,7 @@ class ConfigPaths: ] for path in user_dir_paths: - self._add(*path) + self.add(*path) # These paths are unique per profile unique_profile_paths = [ @@ -191,7 +204,7 @@ class ConfigPaths: ] 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 # `separate` is passed @@ -219,7 +232,7 @@ class ConfigPaths: ] for path in paths: - self._add(*path) + self.add(*path) _paths = ConfigPaths() diff --git a/gajim/common/connection_handlers_events.py b/gajim/common/connection_handlers_events.py index 8b39da5a4..32373b8a4 100644 --- a/gajim/common/connection_handlers_events.py +++ b/gajim/common/connection_handlers_events.py @@ -176,7 +176,6 @@ class HelperEvent: class IqErrorReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): name = 'iq-error-received' - base_network_events = [] def generate(self): self.get_id() @@ -187,7 +186,6 @@ class IqErrorReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): class StreamReceivedEvent(nec.NetworkIncomingEvent): name = 'stream-received' - base_network_events = [] class StreamConflictReceivedEvent(nec.NetworkIncomingEvent): name = 'stream-conflict-received' @@ -321,7 +319,6 @@ PresenceHelperEvent): class ZeroconfPresenceReceivedEvent(nec.NetworkIncomingEvent): name = 'presence-received' - base_network_events = [] def generate(self): 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): name = 'gc-presence-received' - base_network_events = [] def generate(self): self.ptype = self.presence_obj.ptype @@ -436,15 +432,12 @@ class GcPresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): class OurShowEvent(nec.NetworkIncomingEvent): name = 'our-show' - base_network_events = [] class BeforeChangeShowEvent(nec.NetworkIncomingEvent): name = 'before-change-show' - base_network_events = [] class ChatstateReceivedEvent(nec.NetworkIncomingEvent): name = 'chatstate-received' - base_network_events = [] def generate(self): self.stanza = self.msg_obj.stanza @@ -456,7 +449,6 @@ class ChatstateReceivedEvent(nec.NetworkIncomingEvent): class GcMessageReceivedEvent(nec.NetworkIncomingEvent): name = 'gc-message-received' - base_network_events = [] def generate(self): self.stanza = self.msg_obj.stanza @@ -556,7 +548,6 @@ class GcMessageReceivedEvent(nec.NetworkIncomingEvent): class GcConfigChangedReceivedEvent(nec.NetworkIncomingEvent): name = 'gc-config-changed-received' - base_network_events = [] def generate(self): self.conn = self.msg_event.conn @@ -567,7 +558,6 @@ class GcConfigChangedReceivedEvent(nec.NetworkIncomingEvent): class MessageSentEvent(nec.NetworkIncomingEvent): name = 'message-sent' - base_network_events = [] def generate(self): if not self.automatic_message: @@ -579,11 +569,9 @@ class MessageSentEvent(nec.NetworkIncomingEvent): class MessageNotSentEvent(nec.NetworkIncomingEvent): name = 'message-not-sent' - base_network_events = [] class MessageErrorEvent(nec.NetworkIncomingEvent, HelperEvent): name = 'message-error' - base_network_events = [] def init(self): self.zeroconf = False @@ -600,11 +588,9 @@ class MessageErrorEvent(nec.NetworkIncomingEvent, HelperEvent): class AnonymousAuthEvent(nec.NetworkIncomingEvent): name = 'anonymous-auth' - base_network_events = [] class JingleRequestReceivedEvent(nec.NetworkIncomingEvent): name = 'jingle-request-received' - base_network_events = [] def generate(self): self.fjid = self.jingle_session.peerjid @@ -614,7 +600,6 @@ class JingleRequestReceivedEvent(nec.NetworkIncomingEvent): class JingleConnectedReceivedEvent(nec.NetworkIncomingEvent): name = 'jingle-connected-received' - base_network_events = [] def generate(self): self.fjid = self.jingle_session.peerjid @@ -624,7 +609,6 @@ class JingleConnectedReceivedEvent(nec.NetworkIncomingEvent): class JingleDisconnectedReceivedEvent(nec.NetworkIncomingEvent): name = 'jingle-disconnected-received' - base_network_events = [] def generate(self): self.fjid = self.jingle_session.peerjid @@ -634,7 +618,6 @@ class JingleDisconnectedReceivedEvent(nec.NetworkIncomingEvent): class JingleTransferCancelledEvent(nec.NetworkIncomingEvent): name = 'jingleFT-cancelled-received' - base_network_events = [] def generate(self): self.fjid = self.jingle_session.peerjid @@ -644,7 +627,6 @@ class JingleTransferCancelledEvent(nec.NetworkIncomingEvent): class JingleErrorReceivedEvent(nec.NetworkIncomingEvent): name = 'jingle-error-received' - base_network_events = [] def generate(self): self.fjid = self.jingle_session.peerjid @@ -654,15 +636,12 @@ class JingleErrorReceivedEvent(nec.NetworkIncomingEvent): class AccountCreatedEvent(nec.NetworkIncomingEvent): name = 'account-created' - base_network_events = [] class AccountNotCreatedEvent(nec.NetworkIncomingEvent): name = 'account-not-created' - base_network_events = [] class NewAccountConnectedEvent(nec.NetworkIncomingEvent): name = 'new-account-connected' - base_network_events = [] def generate(self): try: @@ -686,15 +665,12 @@ class NewAccountConnectedEvent(nec.NetworkIncomingEvent): class NewAccountNotConnectedEvent(nec.NetworkIncomingEvent): name = 'new-account-not-connected' - base_network_events = [] class ConnectionTypeEvent(nec.NetworkIncomingEvent): name = 'connection-type' - base_network_events = [] class StanzaReceivedEvent(nec.NetworkIncomingEvent): name = 'stanza-received' - base_network_events = [] def init(self): self.additional_data = {} @@ -704,14 +680,12 @@ class StanzaReceivedEvent(nec.NetworkIncomingEvent): class StanzaSentEvent(nec.NetworkIncomingEvent): name = 'stanza-sent' - base_network_events = [] def init(self): self.additional_data = {} class AgentRemovedEvent(nec.NetworkIncomingEvent): name = 'agent-removed' - base_network_events = [] def generate(self): self.jid_list = [] @@ -722,7 +696,6 @@ class AgentRemovedEvent(nec.NetworkIncomingEvent): class BadGPGPassphraseEvent(nec.NetworkIncomingEvent): name = 'bad-gpg-passphrase' - base_network_events = [] def generate(self): self.account = self.conn.name @@ -732,7 +705,6 @@ class BadGPGPassphraseEvent(nec.NetworkIncomingEvent): class ConnectionLostEvent(nec.NetworkIncomingEvent): name = 'connection-lost' - base_network_events = [] def generate(self): app.nec.push_incoming_event(OurShowEvent(None, conn=self.conn, @@ -741,11 +713,9 @@ class ConnectionLostEvent(nec.NetworkIncomingEvent): class GPGTrustKeyEvent(nec.NetworkIncomingEvent): name = 'gpg-trust-key' - base_network_events = [] class GPGPasswordRequiredEvent(nec.NetworkIncomingEvent): name = 'gpg-password-required' - base_network_events = [] def generate(self): self.keyid = app.config.get_per('accounts', self.conn.name, 'keyid') @@ -753,7 +723,6 @@ class GPGPasswordRequiredEvent(nec.NetworkIncomingEvent): class PEPReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): name = 'pep-received' - base_network_events = [] def generate(self): if not self.stanza.getTag('event'): @@ -778,72 +747,57 @@ class PEPReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): class PlainConnectionEvent(nec.NetworkIncomingEvent): name = 'plain-connection' - base_network_events = [] class InsecurePasswordEvent(nec.NetworkIncomingEvent): name = 'insecure-password' - base_network_events = [] class InsecureSSLConnectionEvent(nec.NetworkIncomingEvent): name = 'insecure-ssl-connection' - base_network_events = [] class SSLErrorEvent(nec.NetworkIncomingEvent): name = 'ssl-error' - base_network_events = [] class UniqueRoomIdSupportedEvent(nec.NetworkIncomingEvent): name = 'unique-room-id-supported' - base_network_events = [] class UniqueRoomIdNotSupportedEvent(nec.NetworkIncomingEvent): name = 'unique-room-id-not-supported' - base_network_events = [] class NonAnonymousServerErrorEvent(nec.NetworkIncomingEvent): name = 'non-anonymous-server-error' - base_network_events = [] class UpdateGCAvatarEvent(nec.NetworkIncomingEvent): name = 'update-gc-avatar' - base_network_events = [] def generate(self): return True class UpdateRosterAvatarEvent(nec.NetworkIncomingEvent): name = 'update-roster-avatar' - base_network_events = [] def generate(self): return True class UpdateRoomAvatarEvent(nec.NetworkIncomingEvent): name = 'update-room-avatar' - base_network_events = [] def generate(self): return True class ZeroconfNameConflictEvent(nec.NetworkIncomingEvent): name = 'zeroconf-name-conflict' - base_network_events = [] class PasswordRequiredEvent(nec.NetworkIncomingEvent): name = 'password-required' - base_network_events = [] class Oauth2CredentialsRequiredEvent(nec.NetworkIncomingEvent): name = 'oauth2-credentials-required' - base_network_events = [] class SignedInEvent(nec.NetworkIncomingEvent): name = 'signed-in' - base_network_events = [] class FileRequestReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): name = 'file-request-received' - base_network_events = [] def init(self): self.jingle_content = None @@ -960,7 +914,6 @@ class FileRequestReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): class FileRequestErrorEvent(nec.NetworkIncomingEvent): name = 'file-request-error' - base_network_events = [] def generate(self): self.jid = app.get_jid_without_resource(self.jid) @@ -968,7 +921,6 @@ class FileRequestErrorEvent(nec.NetworkIncomingEvent): class FileTransferCompletedEvent(nec.NetworkIncomingEvent): name = 'file-transfer-completed' - base_network_events = [] def generate(self): jid = str(self.file_props.receiver) @@ -977,7 +929,6 @@ class FileTransferCompletedEvent(nec.NetworkIncomingEvent): class GatewayPromptReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): name = 'gateway-prompt-received' - base_network_events = [] def generate(self): self.get_jid_resource() @@ -1251,7 +1202,6 @@ class NotificationEvent(nec.NetworkIncomingEvent): class MessageOutgoingEvent(nec.NetworkOutgoingEvent): name = 'message-outgoing' - base_network_events = [] def init(self): self.additional_data = {} @@ -1297,21 +1247,18 @@ class MessageOutgoingEvent(nec.NetworkOutgoingEvent): class StanzaMessageOutgoingEvent(nec.NetworkOutgoingEvent): name='stanza-message-outgoing' - base_network_events = [] def generate(self): return True class GcStanzaMessageOutgoingEvent(nec.NetworkOutgoingEvent): name='gc-stanza-message-outgoing' - base_network_events = [] def generate(self): return True class GcMessageOutgoingEvent(nec.NetworkOutgoingEvent): name = 'gc-message-outgoing' - base_network_events = [] def init(self): self.additional_data = {} @@ -1333,11 +1280,9 @@ class GcMessageOutgoingEvent(nec.NetworkOutgoingEvent): class ClientCertPassphraseEvent(nec.NetworkIncomingEvent): name = 'client-cert-passphrase' - base_network_events = [] class InformationEvent(nec.NetworkIncomingEvent): name = 'information' - base_network_events = [] def init(self): self.args = None @@ -1355,7 +1300,6 @@ class InformationEvent(nec.NetworkIncomingEvent): class StyleChanged(nec.NetworkIncomingEvent): name = 'style-changed' - base_network_events = [] def generate(self): return True diff --git a/gajim/common/const.py b/gajim/common/const.py index 905743bec..20641381b 100644 --- a/gajim/common/const.py +++ b/gajim/common/const.py @@ -1,6 +1,8 @@ from enum import IntEnum, Enum, unique from collections import namedtuple +from gajim.common.i18n import _ + Option = namedtuple('Option', 'kind label type value name callback data desc enabledif props') Option.__new__.__defaults__ = (None,) * len(Option._fields) @@ -168,13 +170,14 @@ class PEPHandlerType(IntEnum): @unique class PEPEventType(IntEnum): - ACTIVITY = 0 - TUNE = 1 - MOOD = 2 - LOCATION = 3 - NICKNAME = 4 - AVATAR = 5 - ATOM = 6 + ABSTRACT = 0 + ACTIVITY = 1 + TUNE = 2 + MOOD = 3 + LOCATION = 4 + NICKNAME = 5 + AVATAR = 6 + ATOM = 7 ACTIVITIES = { diff --git a/gajim/common/dbus_support.py b/gajim/common/dbus_support.py index 1fe42871a..1f0e63ea0 100644 --- a/gajim/common/dbus_support.py +++ b/gajim/common/dbus_support.py @@ -25,6 +25,7 @@ import logging from gajim.common import app from gajim.common import exceptions +from gajim.common.i18n import _ _GAJIM_ERROR_IFACE = 'org.gajim.dbus.Error' diff --git a/gajim/common/helpers.py b/gajim/common/helpers.py index 9083f5fbf..d61277929 100644 --- a/gajim/common/helpers.py +++ b/gajim/common/helpers.py @@ -48,6 +48,7 @@ from string import Template import nbxmpp from gajim.common.i18n import Q_ +from gajim.common.i18n import _ from gajim.common.i18n import ngettext from gajim.common import configpaths diff --git a/gajim/common/i18n.py b/gajim/common/i18n.py index 1ecd9c49e..f7e0bb59a 100644 --- a/gajim/common/i18n.py +++ b/gajim/common/i18n.py @@ -132,7 +132,7 @@ if os.name == 'nt': _localedir = get_locale_dir() if hasattr(locale, 'bindtextdomain'): - locale.bindtextdomain(DOMAIN, _localedir) + locale.bindtextdomain(DOMAIN, _localedir) # type: ignore gettext.textdomain(DOMAIN) gettext.install(DOMAIN, _localedir) @@ -142,7 +142,7 @@ try: except OSError: _ = gettext.gettext -if gettext._translations: - _translations = list(gettext._translations.values())[0] +if gettext._translations: # type: ignore + _translations = list(gettext._translations.values())[0] # type: ignore else: _translations = gettext.NullTranslations() diff --git a/gajim/common/modules/__init__.py b/gajim/common/modules/__init__.py index 17beacd3b..89ad22af7 100644 --- a/gajim/common/modules/__init__.py +++ b/gajim/common/modules/__init__.py @@ -12,14 +12,18 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . +from typing import Any +from typing import Dict # pylint: disable=unused-import +from typing import List +from typing import Tuple + import logging -from typing import List # noqa -from typing import Dict # noqa -from typing import Any # noqa from importlib import import_module from pathlib import Path from unittest.mock import MagicMock +from gajim.common.types import ConnectionT + log = logging.getLogger('gajim.c.m') ZEROCONF_MODULES = ['adhoc_commands', 'receipts', 'discovery'] @@ -70,7 +74,7 @@ class ModuleMock: return MagicMock() -def register(con, *args, **kwargs): +def register(con: ConnectionT, *args: Any, **kwargs: Any) -> None: if con in _modules: return _modules[con.name] = {} @@ -83,20 +87,20 @@ def register(con, *args, **kwargs): _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: raise ValueError('Unknown account name: %s' % con.name) _modules[con.name][name] = instance -def unregister(con): +def unregister(con: ConnectionT) -> None: for instance in _modules[con.name].values(): if hasattr(instance, 'cleanup'): instance.cleanup() del _modules[con.name] -def unregister_single(con, name): +def unregister_single(con: ConnectionT, name: str) -> None: if con.name not in _modules: return if name not in _modules[con.name]: @@ -111,8 +115,8 @@ def get(account: str, name: str) -> Any: return ModuleMock(name) -def get_handlers(con): - handlers = [] +def get_handlers(con: ConnectionT) -> List[Tuple[Any, ...]]: + handlers = [] # type: List[Tuple[Any, ...]] for module in _modules[con.name].values(): handlers += module.handlers return handlers diff --git a/gajim/common/modules/annotations.py b/gajim/common/modules/annotations.py index 8bf96df10..4eb8ed7e7 100644 --- a/gajim/common/modules/annotations.py +++ b/gajim/common/modules/annotations.py @@ -14,24 +14,30 @@ # 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 nbxmpp from gajim.common import app from gajim.common import helpers +from gajim.common.types import ConnectionT log = logging.getLogger('gajim.c.m.annotations') class Annotations: - def __init__(self, con): + def __init__(self, con: ConnectionT) -> None: self._con = con self._account = con.name self._server = self._con.get_own_jid().getDomain() - self.handlers = [] - self.annotations = {} + self.handlers = [] # type: List[Tuple[Any, ...]] + self.annotations = {} # type: Dict[str, str] def get_annotations(self) -> None: if not app.account_is_connected(self._account): @@ -93,5 +99,5 @@ class Annotations: 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' diff --git a/gajim/common/modules/pep.py b/gajim/common/modules/pep.py index 4434cba9a..f0cb83baf 100644 --- a/gajim/common/modules/pep.py +++ b/gajim/common/modules/pep.py @@ -14,6 +14,11 @@ # XEP-0163: Personal Eventing Protocol +from typing import Any +from typing import Dict +from typing import List +from typing import Tuple + import logging import nbxmpp @@ -22,12 +27,16 @@ from gajim.common import app from gajim.common.exceptions import StanzaMalformed from gajim.common.nec import NetworkIncomingEvent 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') class PEP: - def __init__(self, con): + def __init__(self, con: ConnectionT) -> None: self._con = con self._account = con.name @@ -37,29 +46,40 @@ class PEP: ] self.supported = False - self._pep_handlers = {} - self._store_publish_modules = [] + self._pep_handlers = {} # type: PEPHandlersDict + 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: if identity['category'] == 'pubsub': if identity.get('type') == 'pep': log.info('Discovered PEP support: %s', from_) 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: self._pep_handlers[namespace].append( (notify_handler, retract_handler)) else: self._pep_handlers[namespace] = [(notify_handler, retract_handler)] if notify_handler: - module_instance = notify_handler.__self__ + module_instance = notify_handler.__self__ # type: ignore if module_instance.store_publish: if module_instance not in self._store_publish_modules: 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() event = stanza.getTag('event', namespace=nbxmpp.NS_PUBSUB_EVENT) items = event.getTag('items') @@ -98,17 +118,47 @@ class PEP: handler[PEPHandlerType.NOTIFY](jid, items_[0]) raise nbxmpp.NodeProcessed - def send_stored_publish(self): + def send_stored_publish(self) -> None: for module in self._store_publish_modules: module.send_stored_publish() - def reset_stored_publish(self): + def reset_stored_publish(self) -> None: for module in self._store_publish_modules: 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: - 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._con = con @@ -119,7 +169,7 @@ class AbstractPEPModule: self._pep_notify_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: data = self._extract_info(item) except StanzaMalformed as error: @@ -129,19 +179,19 @@ class AbstractPEPModule: self._log.info('Received: %s %s', jid, 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._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''' raise NotImplementedError - def _build_node(self, data): + def _build_node(self, data: Any) -> nbxmpp.Node: '''To be implemented by subclasses''' 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) app.nec.push_incoming_event( PEPReceivedEvent(None, conn=self._con, @@ -149,7 +199,7 @@ class AbstractPEPModule: pep_type=self.name, 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)): if user_pep: contact.pep[self.name] = user_pep @@ -162,17 +212,17 @@ class AbstractPEPModule: else: 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: self._log.info('Send stored publish') self.send(self._stored_publish) self._stored_publish = None - def reset_stored_publish(self): + def reset_stored_publish(self) -> None: self._log.info('Reset stored publish') self._stored_publish = None - def send(self, data): + def send(self, data: Any) -> None: if not self._con.get_module('PEP').supported: return @@ -191,7 +241,7 @@ class AbstractPEPModule: self._con.get_module('PubSub').send_pb_publish( '', self.namespace, item, 'current') - def retract(self): + def retract(self) -> None: if not self._con.get_module('PEP').supported: return self.send(None) @@ -199,27 +249,9 @@ class AbstractPEPModule: '', 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): name = 'pep-received' -def get_instance(*args, **kwargs): +def get_instance(*args: Any, **kwargs: Any) -> Tuple[PEP, str]: return PEP(*args, **kwargs), 'PEP' diff --git a/gajim/common/modules/ping.py b/gajim/common/modules/ping.py index 907d1d23b..0b7f7dc77 100644 --- a/gajim/common/modules/ping.py +++ b/gajim/common/modules/ping.py @@ -14,6 +14,9 @@ # XEP-0199: XMPP Ping +from typing import Any +from typing import Tuple + import logging import time @@ -21,12 +24,14 @@ import nbxmpp from gajim.common import app 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') class Ping: - def __init__(self, con): + def __init__(self, con: ConnectionT) -> None: self._con = con self._account = con.name self._alarm_time = None @@ -68,7 +73,7 @@ class Ping: log.warning('No reply received for keepalive ping. Reconnecting...') self._con.disconnectedReconnCB() - def send_ping(self, contact): + def send_ping(self, contact: ContactT) -> None: if not app.account_is_connected(self._account): return @@ -84,7 +89,11 @@ class Ping: app.nec.push_incoming_event( 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): log.info('Error: %s', stanza.getError()) app.nec.push_incoming_event( @@ -98,7 +107,9 @@ class Ping: contact=contact, seconds=diff)) - def _answer_request(self, _con, stanza): + def _answer_request(self, + _con: ConnectionT, + stanza: nbxmpp.Iq) -> None: iq = stanza.buildReply('result') ping = iq.getTag('ping') if ping is not None: @@ -120,5 +131,5 @@ class PingErrorEvent(NetworkIncomingEvent): name = 'ping-error' -def get_instance(*args, **kwargs): +def get_instance(*args: Any, **kwargs: Any) -> Tuple[Ping, str]: return Ping(*args, **kwargs), 'Ping' diff --git a/gajim/common/modules/user_activity.py b/gajim/common/modules/user_activity.py index 699cc96a4..8597a4ef6 100644 --- a/gajim/common/modules/user_activity.py +++ b/gajim/common/modules/user_activity.py @@ -33,7 +33,7 @@ class UserActivityData(AbstractPEPData): def __init__(self, activity): self.data = activity - def asMarkupText(self): + def as_markup_text(self): pep = self.data activity = pep['activity'] subactivity = pep['subactivity'] if 'subactivity' in pep else None diff --git a/gajim/common/modules/user_location.py b/gajim/common/modules/user_location.py index 0429e8a7d..b55d1ac15 100644 --- a/gajim/common/modules/user_location.py +++ b/gajim/common/modules/user_location.py @@ -35,7 +35,7 @@ class UserLocationData(AbstractPEPData): self._pep_specific_data = location self.data = location - def asMarkupText(self): + def as_markup_text(self): location = self.data location_string = '' diff --git a/gajim/common/modules/user_mood.py b/gajim/common/modules/user_mood.py index f687e7bea..07b1d64a2 100644 --- a/gajim/common/modules/user_mood.py +++ b/gajim/common/modules/user_mood.py @@ -14,6 +14,12 @@ # 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 nbxmpp @@ -22,6 +28,7 @@ from gi.repository import GLib from gajim.common.const import PEPEventType, MOODS from gajim.common.exceptions import StanzaMalformed from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData +from gajim.common.types import ConnectionT log = logging.getLogger('gajim.c.m.user_mood') @@ -30,10 +37,12 @@ class UserMoodData(AbstractPEPData): type_ = PEPEventType.MOOD - def __init__(self, mood): + def __init__(self, mood: Optional[Dict[str, str]]) -> None: 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']) markuptext = '%s' % GLib.markup_escape_text(mood) if 'text' in self.data: @@ -42,7 +51,7 @@ class UserMoodData(AbstractPEPData): return markuptext @staticmethod - def _translate_mood(mood): + def _translate_mood(mood: str) -> str: if mood in MOODS: return MOODS[mood] return mood @@ -56,12 +65,12 @@ class UserMood(AbstractPEPModule): store_publish = True _log = log - def __init__(self, con): + def __init__(self, con: ConnectionT) -> None: 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_tag = item.getTag('mood', namespace=nbxmpp.NS_MOOD) if mood_tag is None: @@ -76,7 +85,7 @@ class UserMood(AbstractPEPModule): 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}) if data is None: return @@ -88,5 +97,5 @@ class UserMood(AbstractPEPModule): return item -def get_instance(*args, **kwargs): +def get_instance(*args: Any, **kwargs: Any) -> Tuple[UserMood, str]: return UserMood(*args, **kwargs), 'UserMood' diff --git a/gajim/common/modules/user_nickname.py b/gajim/common/modules/user_nickname.py index 986bc074e..48ca8da3e 100644 --- a/gajim/common/modules/user_nickname.py +++ b/gajim/common/modules/user_nickname.py @@ -14,6 +14,11 @@ # 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 nbxmpp @@ -22,6 +27,7 @@ from gajim.common import app from gajim.common.const import PEPEventType from gajim.common.exceptions import StanzaMalformed from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData +from gajim.common.types import ConnectionT log = logging.getLogger('gajim.c.m.user_nickname') @@ -30,10 +36,10 @@ class UserNicknameData(AbstractPEPData): type_ = PEPEventType.NICKNAME - def __init__(self, nickname): + def __init__(self, nickname: Optional[str]) -> None: self.data = nickname - def get_nick(self): + def get_nick(self) -> str: return self.data or '' @@ -45,12 +51,12 @@ class UserNickname(AbstractPEPModule): store_publish = True _log = log - def __init__(self, con): + def __init__(self, con: ConnectionT) -> None: 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 = '' child = item.getTag('nick', namespace=nbxmpp.NS_NICK) if child is None: @@ -59,14 +65,16 @@ class UserNickname(AbstractPEPModule): 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}) if data is None: - return + return None item.addData(data) 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)): contact.contact_name = user_pep.get_nick() @@ -78,12 +86,12 @@ class UserNickname(AbstractPEPModule): 'accounts', self._account, 'name') -def parse_nickname(stanza): +def parse_nickname(stanza: nbxmpp.Node) -> str: nick = stanza.getTag('nick', namespace=nbxmpp.NS_NICK) if nick is None: return '' return nick.getData() -def get_instance(*args, **kwargs): +def get_instance(*args: Any, **kwargs: Any) -> Tuple[UserNickname, str]: return UserNickname(*args, **kwargs), 'UserNickname' diff --git a/gajim/common/modules/user_tune.py b/gajim/common/modules/user_tune.py index cf0cfd983..55160c7f9 100644 --- a/gajim/common/modules/user_tune.py +++ b/gajim/common/modules/user_tune.py @@ -14,14 +14,23 @@ # 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 nbxmpp from gi.repository import GLib +from gajim.common.i18n import _ from gajim.common.const import PEPEventType from gajim.common.exceptions import StanzaMalformed 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') @@ -30,10 +39,13 @@ class UserTuneData(AbstractPEPData): type_ = PEPEventType.TUNE - def __init__(self, tune): + def __init__(self, tune: Optional[Dict[str, str]]) -> None: self.data = tune - def asMarkupText(self): + def as_markup_text(self) -> str: + if self.data is None: + return '' + tune = self.data artist = tune.get('artist', _('Unknown Artist')) @@ -60,12 +72,12 @@ class UserTune(AbstractPEPModule): store_publish = True _log = log - def __init__(self, con): + def __init__(self, con: ConnectionT) -> None: 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_tag = item.getTag('tune', namespace=self.namespace) if tune_tag is None: @@ -80,7 +92,7 @@ class UserTune(AbstractPEPModule): 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}) if data is None: return item @@ -98,5 +110,5 @@ class UserTune(AbstractPEPModule): return item -def get_instance(*args, **kwargs): +def get_instance(*args: Any, **kwargs: Any) -> Tuple[UserTune, str]: return UserTune(*args, **kwargs), 'UserTune' diff --git a/gajim/common/nec.py b/gajim/common/nec.py index feeea5777..1f7351f26 100644 --- a/gajim/common/nec.py +++ b/gajim/common/nec.py @@ -22,11 +22,12 @@ Network Events Controller. :license: GPL ''' -#from plugins.helpers import log +from typing import List # pylint: disable=unused-import + from gajim.common import app -class NetworkEventsController(object): +class NetworkEventsController: def __init__(self): self.incoming_events_generators = {} ''' @@ -45,7 +46,7 @@ class NetworkEventsController(object): for base_event_name in event_class.base_network_events: event_list = self.incoming_events_generators.setdefault( base_event_name, []) - if not event_class in event_list: + if event_class not in event_list: event_list.append(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: event_list = self.outgoing_events_generators.setdefault( base_event_name, []) - if not event_class in event_list: + if event_class not in event_list: event_list.append(event_class) def unregister_outgoing_event(self, event_class): @@ -89,12 +90,12 @@ class NetworkEventsController(object): base_event_name = event_object.name if base_event_name in self.incoming_events_generators: for new_event_class in self.incoming_events_generators[ - base_event_name]: - new_event_object = new_event_class(None, - base_event=event_object) + base_event_name]: + new_event_object = new_event_class( + None, base_event=event_object) if new_event_object.generate(): if not app.ged.raise_event(new_event_object.name, - new_event_object): + new_event_object): self._generate_events_based_on_incoming_event( new_event_object) @@ -110,16 +111,17 @@ class NetworkEventsController(object): base_event_name = event_object.name if base_event_name in self.outgoing_events_generators: for new_event_class in self.outgoing_events_generators[ - base_event_name]: - new_event_object = new_event_class(None, - base_event=event_object) + base_event_name]: + new_event_object = new_event_class( + None, base_event=event_object) if new_event_object.generate(): if not app.ged.raise_event(new_event_object.name, - new_event_object): + new_event_object): self._generate_events_based_on_outgoing_event( new_event_object) -class NetworkEvent(object): + +class NetworkEvent: name = '' def __init__(self, new_name, **kwargs): @@ -133,14 +135,14 @@ class NetworkEvent(object): def init(self): pass - def generate(self): ''' Generates new event (sets it's attributes) based on event object. 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 are possible before dispatching to Global Events Dispatcher. @@ -159,15 +161,16 @@ class NetworkEvent(object): if k not in ('name', 'base_network_events'): setattr(self, k, v) + 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. ''' 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. ''' diff --git a/gajim/common/pep.py b/gajim/common/pep.py index 9d477e06a..a9d6cc785 100644 --- a/gajim/common/pep.py +++ b/gajim/common/pep.py @@ -67,7 +67,7 @@ class AbstractPEP(object): else: acc.pep[self.type_] = self - def asMarkupText(self): + def as_markup_text(self): '''SHOULD be implemented by subclasses''' return '' diff --git a/gajim/common/types.py b/gajim/common/types.py new file mode 100644 index 000000000..408859cb0 --- /dev/null +++ b/gajim/common/types.py @@ -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 . + +# 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]] diff --git a/gajim/dialog_messages.py b/gajim/dialog_messages.py index b72bc251f..51951f95f 100644 --- a/gajim/dialog_messages.py +++ b/gajim/dialog_messages.py @@ -20,6 +20,7 @@ from collections import namedtuple from gi.repository import GLib from gajim.common.app import app +from gajim.common.i18n import _ from gajim.gtk import ErrorDialog from gajim.gtk import InformationDialog diff --git a/gajim/dialogs.py b/gajim/dialogs.py index 4b162260d..cb2a1b534 100644 --- a/gajim/dialogs.py +++ b/gajim/dialogs.py @@ -38,6 +38,7 @@ from gajim import dataforms_widget from random import randrange from gajim.common import ged +from gajim.common.i18n import _ from gajim.common.const import ACTIVITIES from gajim.common.const import MOODS diff --git a/gajim/disco.py b/gajim/disco.py index bab4fbdb5..60b27d474 100644 --- a/gajim/disco.py +++ b/gajim/disco.py @@ -42,11 +42,12 @@ import types import weakref + +import nbxmpp from gi.repository import GLib from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GdkPixbuf -from gi.repository import Pango from gajim.gtk import ErrorDialog from gajim.gtk import InformationDialog @@ -54,13 +55,11 @@ from gajim import gtkgui_helpers from gajim import groups from gajim import adhoc_commands from gajim import search_window -from gajim import gui_menu_builder from gajim.gtk import ServiceRegistration from gajim.common import app -import nbxmpp +from gajim.common.i18n import _ from gajim.common import helpers -from gajim.common import ged from gajim.common.const import StyleAttr LABELS = { diff --git a/gajim/gajim_remote.py b/gajim/gajim_remote.py index bc021c590..1bcaf7c09 100644 --- a/gajim/gajim_remote.py +++ b/gajim/gajim_remote.py @@ -28,13 +28,13 @@ import os import sys import locale import signal -signal.signal(signal.SIGINT, signal.SIG_DFL) # ^C exits the application - from gajim.common import exceptions -from gajim.common import i18n # This installs _() function +from gajim.common.i18n import _ from gajim.common.i18n import Q_ +signal.signal(signal.SIGINT, signal.SIG_DFL) # ^C exits the application + try: PREFERRED_ENCODING = locale.getpreferredencoding() except Exception: diff --git a/gajim/gtk/add_contact.py b/gajim/gtk/add_contact.py index 3fc53719d..4316a8fed 100644 --- a/gajim/gtk/add_contact.py +++ b/gajim/gtk/add_contact.py @@ -18,6 +18,7 @@ from gi.repository import Gtk from gajim.common import app from gajim.common import ged from gajim.common import helpers +from gajim.common.i18n import _ from gajim.gtk import ErrorDialog from gajim.gtk.util import get_builder diff --git a/gajim/gtk/filechoosers.py b/gajim/gtk/filechoosers.py index ea16d7fbc..cf31be430 100644 --- a/gajim/gtk/filechoosers.py +++ b/gajim/gtk/filechoosers.py @@ -25,6 +25,7 @@ from gi.repository import GdkPixbuf from gi.repository import GObject from gajim.common import app +from gajim.common.i18n import _ Filter = namedtuple('Filter', 'name pattern default') diff --git a/gajim/gtk/service_registration.py b/gajim/gtk/service_registration.py index dce48a191..7cf944020 100644 --- a/gajim/gtk/service_registration.py +++ b/gajim/gtk/service_registration.py @@ -19,6 +19,7 @@ from gi.repository import Gtk from gajim.common import app from gajim.common.modules import dataforms +from gajim.common.i18n import _ from gajim.gtk.dataform import DataFormWidget log = logging.getLogger('gajim.gtk.registration') diff --git a/gajim/gtk/themes.py b/gajim/gtk/themes.py index 94d3e1203..40cdfdce5 100644 --- a/gajim/gtk/themes.py +++ b/gajim/gtk/themes.py @@ -21,6 +21,7 @@ from gi.repository import Gtk from gi.repository import Gdk from gajim.common import app +from gajim.common.i18n import _ from gajim.common.const import StyleAttr, DialogButton, ButtonAction from gajim.common.connection_handlers_events import StyleChanged from gajim.gtk import ErrorDialog diff --git a/gajim/gui_interface.py b/gajim/gui_interface.py index 17e29594c..0fd112c85 100644 --- a/gajim/gui_interface.py +++ b/gajim/gui_interface.py @@ -2127,7 +2127,7 @@ class Interface: if app.connections[acct].music_track_info == music_track_info: continue app.connections[acct].get_module('UserTune').send( - (artist, title, source, None, None)) + (artist, title, source, '', '')) app.connections[acct].music_track_info = music_track_info def read_sleepy(self): diff --git a/gajim/history_manager.py b/gajim/history_manager.py index 0a5157016..bba23654f 100644 --- a/gajim/history_manager.py +++ b/gajim/history_manager.py @@ -79,6 +79,7 @@ if is_standalone(): configpaths.init() from gajim.common import app +from gajim.common.i18n import _ from gajim.common.const import JIDConstant, KindConstant from gajim.common import helpers from gajim.gtk import YesNoDialog diff --git a/gajim/message_textview.py b/gajim/message_textview.py index 99bf27b5b..21e51ad54 100644 --- a/gajim/message_textview.py +++ b/gajim/message_textview.py @@ -24,6 +24,7 @@ from gi.repository import GLib from gi.repository import Pango from gajim.common import app +from gajim.common.i18n import _ from gajim import gtkgui_helpers if app.is_installed('GSPELL'): diff --git a/gajim/plugins/plugins_i18n.py b/gajim/plugins/plugins_i18n.py index b71a31128..16860bc21 100644 --- a/gajim/plugins/plugins_i18n.py +++ b/gajim/plugins/plugins_i18n.py @@ -14,15 +14,18 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . +from typing import cast + +import os import locale import gettext -from os import path as os_path -import os + from gajim.common import app from gajim.common import configpaths 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': locale.setlocale(locale.LC_ALL, '') diff --git a/gajim/tooltips.py b/gajim/tooltips.py index 5ab0294fe..f0715a650 100644 --- a/gajim/tooltips.py +++ b/gajim/tooltips.py @@ -528,25 +528,25 @@ class RosterTooltip(Gtk.Window, StatusTable): to the given property list. """ if 'mood' in contact.pep: - mood = contact.pep['mood'].asMarkupText() + mood = contact.pep['mood'].as_markup_text() self.mood.set_markup(mood) self.mood.show() self.mood_label.show() if 'activity' in contact.pep: - activity = contact.pep['activity'].asMarkupText() + activity = contact.pep['activity'].as_markup_text() self.activity.set_markup(activity) self.activity.show() self.activity_label.show() if 'tune' in contact.pep: - tune = contact.pep['tune'].asMarkupText() + tune = contact.pep['tune'].as_markup_text() self.tune.set_markup(tune) self.tune.show() self.tune_label.show() if 'geoloc' in contact.pep: - location = contact.pep['geoloc'].asMarkupText() + location = contact.pep['geoloc'].as_markup_text() self.location.set_markup(location) self.location.show() self.location_label.show()