From 00300cdf81ceb13addfc3b96101abaaf0ec43d5a Mon Sep 17 00:00:00 2001 From: Adrian Sampson Date: Mon, 30 Aug 2010 12:50:17 -0700 Subject: [PATCH] move event-handling logic into plugin system --- beets/events.py | 56 ---------------------------------------- beets/plugins.py | 61 ++++++++++++++++++++++++++++++++++++++++++-- beets/ui/__init__.py | 3 ++- 3 files changed, 61 insertions(+), 59 deletions(-) delete mode 100644 beets/events.py diff --git a/beets/events.py b/beets/events.py deleted file mode 100644 index 5d919151d..000000000 --- a/beets/events.py +++ /dev/null @@ -1,56 +0,0 @@ -# This file is part of beets. -# Copyright 2010, Adrian Sampson. -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. - -#All the handlers for the event system. -#Each key of the dictionary should contain a list of functions to be called -#for any event. Functions will be called in the order they were added. -handlers = { } - -def addEventListener(event, function): - """Adds an event listener to call function() when the specified event - (as a string) happens. The parameters passed to function will vary - depending on what event occured. - - The function should respond to named parameters. function(**kwargs) will - trap all arguments in a dictionary.""" - global handlers - - if event not in handlers: - handlers[event] = [ ] #Empty list to store the handlers - handlers[event].append(function) - -def send(event, **arguments): - """Sends an event to all assigned event listeners. Event is the name of - the event to send, all other named arguments go to the event handler(s). - - Returns the number of handlers called.""" - - if event in handlers: - for handler in handlers[event]: - handler(**arguments) - return len(handlers[event]) - else: - return 0 - -def listen(event): - """Decorator method for creating an event listener. - - @events.listen("imported") - def importListener(**kwargs): - pass""" - def helper(funct): - addEventListener(event, funct) - return funct - - return helper diff --git a/beets/plugins.py b/beets/plugins.py index d15621420..50952bafc 100644 --- a/beets/plugins.py +++ b/beets/plugins.py @@ -17,12 +17,16 @@ import logging import itertools import traceback +from collections import defaultdict + +PLUGIN_NAMESPACE = 'beetsplug' +DEFAULT_PLUGINS = ['bpd'] # Global logger. log = logging.getLogger('beets') -PLUGIN_NAMESPACE = 'beetsplug' -DEFAULT_PLUGINS = ['bpd'] + +# Managing the plugins themselves. class BeetsPlugin(object): """The base class for all beets plugins. Plugins provide @@ -35,6 +39,28 @@ class BeetsPlugin(object): """ raise NotImplementedError + listeners = None + @classmethod + def listen(cls, event): + """Decorator that adds a function as an event handler for the + specified event (as a string). The parameters passed to function + will vary depending on what event occurred. + + The function should respond to named parameters. + function(**kwargs) will trap all arguments in a dictionary. + Example: + + >>> @MyPlugin.listen("imported") + >>> def importListener(**kwargs): + >>> pass + """ + def helper(func): + if cls.listeners is None: + cls.listeners = defaultdict(list) + cls.listeners[event].append(func) + return func + return helper + def load_plugins(names=()): """Imports the modules for a sequence of plugin names. Each name must be the name of a Python module under the "beetsplug" namespace @@ -72,6 +98,9 @@ def find_plugins(): plugins.append(_instances[cls]) return plugins + +# Plugin commands. + def commands(): """Returns a list of Subcommand objects from all loaded plugins. """ @@ -80,3 +109,31 @@ def commands(): out += plugin.commands() return out + +# Event dispatch. + +# All the handlers for the event system. +# Each key of the dictionary should contain a list of functions to be +# called for any event. Functions will be called in the order they were +# added. +_event_handlers = defaultdict(list) + +def load_listeners(): + """Loads and registers event handlers from all loaded plugins. + """ + for plugin in find_plugins(): + if plugin.listeners: + for event, handlers in plugin.listeners.items(): + _event_handlers[event] += handlers + +def send(event, **arguments): + """Sends an event to all assigned event listeners. Event is the + name of the event to send, all other named arguments go to the + event handler(s). + + Returns the number of handlers called. + """ + handlers = _event_handlers[event] + for handler in handlers: + handler(**arguments) + return len(handlers) diff --git a/beets/ui/__init__.py b/beets/ui/__init__.py index e5af464ab..d7aba7660 100644 --- a/beets/ui/__init__.py +++ b/beets/ui/__init__.py @@ -406,7 +406,8 @@ def main(): # Load requested plugins. plugnames = config_val(config, 'beets', 'plugins', '') plugins.load_plugins(plugnames.split()) - events.send("pluginload") + plugins.load_listeners() + plugins.send("pluginload") # Construct the root parser. commands = list(default_commands)