diff --git a/gajim/common/connection.py b/gajim/common/connection.py index c34b160dd..6fcafd3c2 100644 --- a/gajim/common/connection.py +++ b/gajim/common/connection.py @@ -492,7 +492,7 @@ class Connection(CommonConnection, ConnectionHandlers): self._sm_resume_data = {} # Register all modules - modules.register(self) + modules.register_modules(self) app.ged.register_event_handler('message-outgoing', ged.OUT_CORE, self._nec_message_outgoing) @@ -505,7 +505,7 @@ class Connection(CommonConnection, ConnectionHandlers): # END __init__ def cleanup(self): - modules.unregister(self) + modules.unregister_modules(self) app.ged.remove_event_handler('message-outgoing', ged.OUT_CORE, self._nec_message_outgoing) app.ged.remove_event_handler('gc-message-outgoing', ged.OUT_CORE, diff --git a/gajim/common/modules/__init__.py b/gajim/common/modules/__init__.py index 0a71446c9..393d7f645 100644 --- a/gajim/common/modules/__init__.py +++ b/gajim/common/modules/__init__.py @@ -17,9 +17,9 @@ from typing import Dict # pylint: disable=unused-import from typing import List from typing import Tuple +import sys import logging from importlib import import_module -from pathlib import Path from unittest.mock import MagicMock from gajim.common.types import ConnectionT @@ -32,6 +32,49 @@ ZEROCONF_MODULES = ['iq', 'discovery', 'chatstates'] +MODULES = [ + 'adhoc_commands', + 'annotations', + 'bits_of_binary', + 'blocking', + 'bookmarks', + 'caps', + 'carbons', + 'chatstates', + 'delimiter', + 'discovery', + 'entity_time', + 'gateway', + 'httpupload', + 'http_auth', + 'iq', + 'last_activity', + 'mam', + 'message', + 'metacontacts', + 'muc', + 'pep', + 'ping', + 'presence', + 'privacylists', + 'pubsub', + 'receipts', + 'register', + 'roster', + 'roster_item_exchange', + 'search', + 'security_labels', + 'software_version', + 'user_activity', + 'user_avatar', + 'user_location', + 'user_mood', + 'user_nickname', + 'user_tune', + 'vcard_avatars', + 'vcard_temp', +] + _imported_modules = [] # type: List[tuple] _modules = {} # type: Dict[str, Dict[str, Any]] _store_publish_modules = [ @@ -41,20 +84,6 @@ _store_publish_modules = [ 'UserTune', ] # type: List[str] -for file in Path(__file__).parent.iterdir(): - if file.stem == '__init__': - continue - - _module = import_module('.%s' % file.stem, package='gajim.common.modules') - if hasattr(_module, 'get_instance'): - log.info('Load module: %s', file.stem) - if file.stem == 'pep': - # Register the PEP module first, because other modules - # depend on it - _imported_modules.insert(0, (_module, file.stem)) - else: - _imported_modules.append((_module, file.stem)) - class ModuleMock: def __init__(self, name: str) -> None: @@ -84,33 +113,32 @@ class ModuleMock: return MagicMock() -def register(con: ConnectionT, *args: Any, **kwargs: Any) -> None: +def register_modules(con: ConnectionT, *args: Any, **kwargs: Any) -> None: if con in _modules: return _modules[con.name] = {} - for module in _imported_modules: - mod, name = module + for module_name in MODULES: if con.name == 'Local': - if name not in ZEROCONF_MODULES: + if module_name not in ZEROCONF_MODULES: continue - instance, name = mod.get_instance(con, *args, **kwargs) + instance, name = _load_module(module_name, con, *args, **kwargs) _modules[con.name][name] = instance -def register_single(con: ConnectionT, instance: Any, name: str) -> None: +def register_single_module(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: ConnectionT) -> None: +def unregister_modules(con: ConnectionT) -> None: for instance in _modules[con.name].values(): if hasattr(instance, 'cleanup'): instance.cleanup() del _modules[con.name] -def unregister_single(con: ConnectionT, name: str) -> None: +def unregister_single_module(con: ConnectionT, name: str) -> None: if con.name not in _modules: return if name not in _modules[con.name]: @@ -130,6 +158,15 @@ def get(account: str, name: str) -> Any: return ModuleMock(name) +def _load_module(name: str, con: ConnectionT, *args: Any, **kwargs: Any) -> Any: + if name not in MODULES: + raise ValueError('Module %s does not exist' % name) + module = sys.modules.get(name) + if module is None: + module = import_module('.%s' % name, package='gajim.common.modules') + return module.get_instance(con, *args, **kwargs) # type: ignore + + def get_handlers(con: ConnectionT) -> List[Tuple[Any, ...]]: handlers = [] # type: List[Tuple[Any, ...]] for module in _modules[con.name].values(): diff --git a/gajim/common/zeroconf/connection_zeroconf.py b/gajim/common/zeroconf/connection_zeroconf.py index cdd8a6f70..c4ccd5b19 100644 --- a/gajim/common/zeroconf/connection_zeroconf.py +++ b/gajim/common/zeroconf/connection_zeroconf.py @@ -70,7 +70,7 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf): self.is_zeroconf = True # Register all modules - modules.register(self) + modules.register_modules(self) app.ged.register_event_handler('message-outgoing', ged.OUT_CORE, self._nec_message_outgoing) diff --git a/gajim/plugins/pluginmanager.py b/gajim/plugins/pluginmanager.py index c5070c39d..6f09b56e3 100644 --- a/gajim/plugins/pluginmanager.py +++ b/gajim/plugins/pluginmanager.py @@ -408,7 +408,7 @@ class PluginManager(metaclass=Singleton): if not module.zeroconf and con.name == 'Local': continue instance, name = module.get_instance(con) - modules.register_single(con, instance, name) + modules.register_single_module(con, instance, name) # If handlers have been registered, register the # plugin handlers. Otherwise this will be done @@ -424,7 +424,7 @@ class PluginManager(metaclass=Singleton): for con in app.connections.values(): for module in plugin.modules: instance = con.get_module(module.name) - modules.unregister_single(con, module.name) + modules.unregister_single_module(con, module.name) # Account is still connected and handlers are registered # So just unregister the plugin handlers @@ -562,7 +562,7 @@ class PluginManager(metaclass=Singleton): instance, name = module.get_instance(con) if not module.zeroconf and con.name == 'Local': continue - modules.register_single(con, instance, name) + modules.register_single_module(con, instance, name) def _plugin_is_active_in_global_config(self, plugin): return app.config.get_per('plugins', plugin.short_name, 'active')