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()
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'):

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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'}

View File

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

View File

@ -19,82 +19,90 @@
# You should have received a copy of the GNU General Public License
# 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 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[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()

View File

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

View File

@ -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 = {

View File

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

View File

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

View File

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

View File

@ -12,14 +12,18 @@
# You should have received a copy of the GNU General Public License
# 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
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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 = ''

View File

@ -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 = '<b>%s</b>' % 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'

View File

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

View File

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

View File

@ -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):
@ -90,8 +91,8 @@ class NetworkEventsController(object):
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)
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):
@ -111,15 +112,16 @@ class NetworkEventsController(object):
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)
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):
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.
'''

View File

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

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 gajim.common.app import app
from gajim.common.i18n import _
from gajim.gtk import ErrorDialog
from gajim.gtk import InformationDialog

View File

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

View File

@ -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 = {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -14,15 +14,18 @@
# You should have received a copy of the GNU General Public License
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
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, '')

View File

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