summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormathieui <mathieui@mathieui.net>2013-03-06 22:57:41 +0100
committermathieui <mathieui@mathieui.net>2013-03-06 22:57:41 +0100
commit370cc874c2dffd6b4fd306213654c355a5ecadf6 (patch)
treee61bfddcc547c5b14fe0a311a15631da1a77f2b4 /src
parentcbf563583cfa429397eabf81f009dfe78dd74398 (diff)
downloadpoezio-370cc874c2dffd6b4fd306213654c355a5ecadf6.tar.gz
poezio-370cc874c2dffd6b4fd306213654c355a5ecadf6.tar.bz2
poezio-370cc874c2dffd6b4fd306213654c355a5ecadf6.tar.xz
poezio-370cc874c2dffd6b4fd306213654c355a5ecadf6.zip
Introduce a new way for plugins to interact with poezio
- Try to reduce the use of the “core” object in the plugins - New “api” member for each BasePlugin which is a wrapper around the unique PluginAPI object. (instead of having the methods directly in BasePlugin and then calling the PluginManager) - Documented methods with rst (for sphinx)
Diffstat (limited to 'src')
-rw-r--r--src/plugin.py259
-rw-r--r--src/plugin_manager.py5
2 files changed, 251 insertions, 13 deletions
diff --git a/src/plugin.py b/src/plugin.py
index 537f7b61..82b96443 100644
--- a/src/plugin.py
+++ b/src/plugin.py
@@ -4,6 +4,7 @@ These are used in the plugin system added in poezio 0.7.5
(see plugin_manager.py)
"""
import os
+from functools import partial
from configparser import RawConfigParser
import config
import inspect
@@ -82,23 +83,256 @@ class SafetyMetaclass(type):
class_dict[k] = SafetyMetaclass.safe_func(v)
return type.__new__(meta, name, bases, class_dict)
+class PluginWrap(object):
+ """
+ A wrapper to implicitly pass the module name to PluginAPI
+ """
+ def __init__(self, api, module):
+ self.api = api
+ self.module = module
+
+ def __getattribute__(self, name):
+ api = object.__getattribute__(self, 'api')
+ module = object.__getattribute__(self, 'module')
+ return partial(getattr(api, name), module)
+
+class PluginAPI(object):
+ """
+ The public API exposed to the plugins.
+ Its goal is to limit the use of the raw Core object
+ as much as possible.
+ """
+
+ def __init__(self, core, plugin_manager):
+ self.core = core
+ self.plugin_manager = plugin_manager
+
+ def __getitem__(self, value):
+ return PluginWrap(self, value)
+
+ def send_message(self, _, *args, **kwargs):
+ """
+ Send a message to the current tab.
+
+ :param str msg: The message to send.
+ """
+ return self.core.send_message(*args, **kwargs)
+
+ def add_timed_event(self, _, *args, **kwargs):
+ """
+ Add a timed event.
+
+ :param event: The timed event to add.
+ """
+ return self.core.add_timed_event(*args, **kwargs)
+
+ def information(self, _, *args, **kwargs):
+ """
+ Display a new message in the information buffer.
+
+ :param str msg: The message to display.
+ :param str typ: The message type (e.g. Info, Error…)
+ """
+ return self.core.information(*args, **kwargs)
+
+ def current_tab(self, _):
+ """
+ Get the current Tab.
+
+ :returns: tabs.Tab The current tab.
+ """
+ return self.core.current_tab()
+
+ def run_command(self, _, *args, **kwargs):
+ """
+ Run a command from the current tab.
+ (a command starts with a /, if not, it’s a message)
+
+ :param str line: The command to run.
+ """
+ return self.core.current_tab().execute_command(line)
+
+ def all_tabs(self, _):
+ """
+ Return a list of all opened tabs
+
+ :returns list: The list of tabs.
+ """
+ return self.core.tabs
+
+ def add_command(self, module, *args, **kwargs):
+ """
+ Add a global command.
+
+ :param str name: The name of the command (/name)
+ :param function handler: The function called when the command is run.
+ :param str help: The complete help for that command.
+ :param str short: A short description of the command.
+ :param function completion: The completion function for that command
+ (optional)
+ :param str usage: A string showing the required and optional args
+ of the command. Optional args should be surrounded by []
+ and mandatory args should be surrounded by <>.
+
+ Example string: "<server> [port]"
+
+ :raises: Exception If the command already exists.
+ """
+ return self.plugin_manager.add_command(module, *args, **kwargs)
+
+ def del_command(self, module, *args, **kwargs):
+ """
+ Remove a global command.
+
+ :param str name: The name of the command to remove.
+ That command _must_ have been added by the same plugin
+ """
+ return self.plugin_manager.del_command(module, *args, **kwargs)
+
+ def add_key(self, module, *args, **kwargs):
+ """
+ Associate a global binding to a handler.
+
+ :param str key: The curses representation of the binding.
+ :param function handler: The function called when the binding is pressed.
+
+ :raise Exception: If the binding is already present.
+ """
+ return self.plugin_manager.add_key(module, *args, **kwargs)
+
+ def del_key(self, module, *args, **kwargs):
+ """
+ Remove a global binding.
+
+ :param str key: The binding to remove.
+ """
+ return self.plugin_manager.del_key(module, *args, **kwargs)
+
+ def add_tab_key(self, module, *args, **kwargs):
+ """
+ Associate a binding to a handler, but only for a certain tab type.
+
+ :param Tab tab_type: The type of tab to target.
+ :param str key: The binding to add.
+ :param function handler: The function called when the binding is pressed
+ """
+ return self.plugin_manager.add_tab_key(module, *args, **kwargs)
+
+ def del_tab_key(self, module, *args, **kwargs):
+ """
+ Remove a binding added with add_tab_key
+
+ :param tabs.Tab tab_type: The type of tab to target.
+ :param str key: The binding to remove.
+ """
+ return self.plugin_manager.del_tab_key(module, *args, **kwargs)
+
+ def add_tab_command(self, module, *args, **kwargs):
+ """
+ Add a command to only one type of tab.
+
+ :param tabs.Tab tab_type: The type of Tab to target.
+ :param str name: The name of the command (/name)
+ :param function handler: The function called when the command is run.
+ :param str help: The complete help for that command.
+ :param str short: A short description of the command.
+ :param function completion: The completion function for that command
+ (optional)
+ :param str usage: A string showing the required and optional args
+ of the command. Optional args should be surrounded by []
+ and mandatory args should be surrounded by <>.
+
+ Example string: "<server> [port]"
+
+ :raise Exception: If the command already exists.
+ """
+ return self.plugin_manager.add_tab_command(module, *args, **kwargs)
+
+ def del_tab_command(self, module, *args, **kwargs):
+ """
+ Remove a tab-specific command.
+
+ :param tabs.Tab tab_type: The type of tab to target.
+ :param str name: The name of the command to remove.
+ That command _must_ have been added by the same plugin
+ """
+ return self.plugin_manager.del_tab_command(module, *args, **kwargs)
+
+ def add_event_handler(self, module, *args, **kwargs):
+ """
+ Add an event handler for a poezio event.
+
+ :param str event_name: The event name.
+ :param function handler: The handler function.
+ :param int position: The position of that handler in the handler list.
+ This is useful for plugins like GPG or OTR, which must be the last
+ function called on the text.
+ Defaults to 0.
+
+ A complete list of those events can be found at
+ http://poezio.eu/doc/en/plugins.html#events-list
+ """
+ return self.plugin_manager.add_event_handler(module, *args, **kwargs)
+
+ def del_event_handler(self, module, *args, **kwargs):
+ """
+ Remove a handler for a poezio event.
+
+ :param str event_name: The name of the targeted event.
+ :param function handler: The function to remove from the handlers.
+ """
+ return self.plugin_manager.del_event_handler(module, *args, **kwargs)
+
+ def add_sleek_event_handler(self, module, event_name, handler):
+ """
+ Add an event handler for a sleekxmpp event.
+
+ :param str event_name: The event name.
+ :param function handler: The handler function.
+
+ A list of the SleekXMPP events can be found here
+ http://sleekxmpp.com/event_index.html
+ """
+ self.core.xmmp.add_event_handler(event_name, handler)
+
+ def del_sleek_event_handler(self, module, event_name, handler):
+ """
+ Remove a handler for a SleekXMPP event
+
+ :param str event_name: The name of the targeted event.
+ :param function handler: The function to remove from the handlers.
+ """
+ self.core.xmpp.del_event_handler(event_name, handler)
+
class BasePlugin(object, metaclass=SafetyMetaclass):
"""
Class that all plugins derive from.
"""
- def __init__(self, plugin_manager, core, plugins_conf_dir):
+ def __init__(self, plugin_api, core, plugins_conf_dir):
self.core = core
# More hack; luckily we'll never have more than one core object
SafetyMetaclass.core = core
- self.plugin_manager = plugin_manager
conf = os.path.join(plugins_conf_dir, self.__module__+'.cfg')
self.config = PluginConfig(conf, self.__module__)
+ self._api = plugin_api[self.name]
self.init()
+ @property
+ def name(self):
+ """
+ Get the name (module name) of the plugin.
+ """
+ return self.__module__
+
+ @property
+ def api(self):
+ return self._api
+
def init(self):
"""
Method called at the creation of the plugin.
+
Do not overwrite __init__ and use this instead.
"""
pass
@@ -106,6 +340,7 @@ class BasePlugin(object, metaclass=SafetyMetaclass):
def cleanup(self):
"""
Called when the plugin is unloaded.
+
Overwrite this if you want to erase or save things before the plugin is disabled.
"""
pass
@@ -118,7 +353,7 @@ class BasePlugin(object, metaclass=SafetyMetaclass):
Add a global command.
You cannot overwrite the existing commands.
"""
- return self.plugin_manager.add_command(self.__module__, name, handler, help,
+ return self.api.add_command(name, handler, help,
completion=completion, short=short, usage=usage)
def del_command(self, name):
@@ -126,54 +361,54 @@ class BasePlugin(object, metaclass=SafetyMetaclass):
Remove a global command.
This only works if the command was added by the plugin
"""
- return self.plugin_manager.del_command(self.__module__, name)
+ return self.api.del_command(name)
def add_key(self, key, handler):
"""
Add a global keybind
"""
- return self.plugin_manager.add_key(self.__module__, key, handler)
+ return self.api.add_key(key, handler)
def del_key(self, key):
"""
Remove a global keybind
"""
- return self.plugin_manager.del_key(self.__module__, key)
+ return self.api.del_key(key)
def add_tab_key(self, tab_type, key, handler):
"""
Add a keybind only for a type of tab.
"""
- return self.plugin_manager.add_tab_key(self.__module__, tab_type, key, handler)
+ return self.api.add_tab_key(tab_type, key, handler)
def del_tab_key(self, tab_type, key):
"""
Remove a keybind added through add_tab_key.
"""
- return self.plugin_manager.del_tab_key(self.__module__, tab_type, key)
+ return self.api.del_tab_key(tab_type, key)
def add_tab_command(self, tab_type, name, handler, help, completion=None, short='', usage=''):
"""
Add a command only for a type of tab.
"""
- return self.plugin_manager.add_tab_command(self.__module__, tab_type, name, handler, help,
+ return self.api.add_tab_command(tab_type, name, handler, help,
completion=completion, short=short, usage=usage)
def del_tab_command(self, tab_type, name):
"""
Delete a command added through add_tab_command.
"""
- return self.plugin_manager.del_tab_command(self.__module__, tab_type, name)
+ return self.api.del_tab_command(tab_type, name)
def add_event_handler(self, event_name, handler, position=0):
"""
Add an event handler to the event event_name.
An optional position in the event handler list can be provided.
"""
- return self.plugin_manager.add_event_handler(self.__module__, event_name, handler, position)
+ return self.api.add_event_handler(event_name, handler, position)
def del_event_handler(self, event_name, handler):
"""
Remove 'handler' from the event list for 'event_name'.
"""
- return self.plugin_manager.del_event_handler(self.__module__, event_name, handler)
+ return self.api.del_event_handler(event_name, handler)
diff --git a/src/plugin_manager.py b/src/plugin_manager.py
index a8c651e9..afd04330 100644
--- a/src/plugin_manager.py
+++ b/src/plugin_manager.py
@@ -14,6 +14,7 @@ from gettext import gettext as _
import core
import tabs
+from plugin import PluginAPI
from config import config
log = logging.getLogger(__name__)
@@ -63,6 +64,8 @@ class PluginManager(object):
self.tab_commands = {} #module name -> dict of tab types; tab type -> commands loaded by the module
self.keys = {} # module name → dict of keys/handlers loaded for the module
self.tab_keys = {} #module name → dict of tab types; tab type → list of keybinds (tuples)
+ self.roster_elements = {}
+ self.plugin_api = PluginAPI(core, self)
def load(self, name, notify=True):
"""
@@ -96,7 +99,7 @@ class PluginManager(object):
self.tab_keys[name] = {}
self.tab_commands[name] = {}
self.event_handlers[name] = []
- self.plugins[name] = module.Plugin(self, self.core, plugins_conf_dir)
+ self.plugins[name] = module.Plugin(self.plugin_api, self.core, plugins_conf_dir)
if notify:
self.core.information('Plugin %s loaded' % name, 'Info')