diff options
Diffstat (limited to 'src/plugin.py')
-rw-r--r-- | src/plugin.py | 485 |
1 files changed, 0 insertions, 485 deletions
diff --git a/src/plugin.py b/src/plugin.py deleted file mode 100644 index bf30c981..00000000 --- a/src/plugin.py +++ /dev/null @@ -1,485 +0,0 @@ -""" -Define the PluginConfig and Plugin classes, plus the SafetyMetaclass. -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 -from timed_events import TimedEvent, DelayedEvent -import config -import inspect -import traceback -import logging -log = logging.getLogger(__name__) - -class PluginConfig(config.Config): - """ - Plugin configuration object. - They are accessible inside the plugin with self.config - and behave like the core Config object. - """ - def __init__(self, filename, module_name, default=None): - config.Config.__init__(self, filename, default=default) - self.module_name = module_name - self.read() - - def get(self, option, default=None, section=None): - if not section: - section = self.module_name - return config.Config.get(self, option, default, section) - - def set(self, option, default, section=None): - if not section: - section = self.module_name - return config.Config.set_and_save(self, option, default, section) - - def remove(self, option, section=None): - if not section: - section = self.module_name - return config.Config.remove_and_save(self, option, section) - - def read(self): - """Read the config file""" - RawConfigParser.read(self, self.file_name) - if not self.has_section(self.module_name): - self.add_section(self.module_name) - - def options(self, section=None): - """ - Return the options of the section - If no section is given, it defaults to the plugin name. - """ - if not section: - section = self.module_name - if not self.has_section(section): - self.add_section(section) - return config.Config.options(self, section) - - def write(self): - """Write the config to the disk""" - try: - fp = open(self.file_name, 'w') - RawConfigParser.write(self, fp) - fp.close() - return True - except IOError: - return False - - -class SafetyMetaclass(type): - # A hack - core = None - - @staticmethod - def safe_func(f): - def helper(*args, **kwargs): - try: - return f(*args, **kwargs) - except: - if inspect.stack()[1][1] == inspect.getfile(f): - raise - elif SafetyMetaclass.core: - log.error('Error in a plugin', exc_info=True) - SafetyMetaclass.core.information(traceback.format_exc()) - return None - return helper - - def __new__(meta, name, bases, class_dict): - for k, v in class_dict.items(): - if inspect.isfunction(v): - if k != '__init__' and k != 'init': - 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 get_conversation_messages(self, _, *args, **kwargs): - """ - Get all the Messages of the current Tab. - - :returns: The list of :py:class:`text_buffer.Message` objects. - :returns: None if the Tab does not inherit from ChatTab. - :rtype: :py:class:`list` - """ - return self.core.get_conversation_messages() - - def add_timed_event(self, _, *args, **kwargs): - """ - Schedule a timed event. - - :param timed_events.TimedEvent event: The timed event to schedule. - """ - return self.core.add_timed_event(*args, **kwargs) - - def remove_timed_event(self, _, *args, **kwargs): - """ - Unschedule a timed event. - - :param timed_events.TimedEvent event: The event to unschedule. - """ - return self.core.remove_timed_event(*args, **kwargs) - - def create_timed_event(self, _, *args, **kwargs): - """ - Create a timed event, but do not schedule it; - :py:func:`~PluginAPI.add_timed_event` must be used for that. - - :param datetime.datetime date: The time at which the handler must be executed - :param function callback: The handler that will be executed - :param \*args: Optional arguments passed to the handler. - :return: The created event. - :rtype: :py:class:`timed_events.TimedEvent` - """ - return TimedEvent(*args, **kwargs) - - def create_delayed_event(self, _, *args, **kwargs): - """ - Create a delayed event, but do not schedule it; - :py:func:`~PluginAPI.add_timed_event` must be used for that. - - A delayed event is a timed event with a delay from the time - this function is called (instead of a datetime). - - :param int delay: The number of seconds to schedule the execution - :param function callback: The handler that will be executed - :param \*args: Optional arguments passed to the handler. - :return: The created event. - :rtype: :py:class:`timed_events.DelayedEvent` - """ - return DelayedEvent(*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: The current tab. - """ - return self.core.current_tab() - - def get_status(self, _): - """ - Get the current user global status. - - :returns Status: The current status. - """ - return self.core.get_status() - - 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(*args, **kwargs) - - 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 - https://doc.poez.io/dev/events.html - """ - 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_slix_event_handler(self, module, event_name, handler): - """ - Add an event handler for a slixmpp event. - - :param str event_name: The event name. - :param function handler: The handler function. - - A list of the slixmpp events can be found here - http://sleekxmpp.com/event_index.html - """ - self.core.xmpp.add_event_handler(event_name, handler) - - def del_slix_event_handler(self, module, event_name, handler): - """ - Remove a handler for a slixmpp 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. - """ - - default_config = None - - 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 - conf = os.path.join(plugins_conf_dir, self.__module__+'.cfg') - try: - self.config = PluginConfig(conf, self.__module__, - default=self.default_config) - except Exception: - log.debug('Error while creating the plugin config', exc_info=True) - 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 - - 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 - - def unload(self): - self.cleanup() - - def add_command(self, name, handler, help, completion=None, short='', usage=''): - """ - Add a global command. - You cannot overwrite the existing commands. - """ - return self.api.add_command(name, handler, help, - completion=completion, short=short, usage=usage) - - def del_command(self, name): - """ - Remove a global command. - This only works if the command was added by the plugin - """ - return self.api.del_command(name) - - def add_key(self, key, handler): - """ - Add a global keybind - """ - return self.api.add_key(key, handler) - - def del_key(self, key): - """ - Remove a global keybind - """ - 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.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.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.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.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.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.api.del_event_handler(event_name, handler) |