move event-handling logic into plugin system

This commit is contained in:
Adrian Sampson 2010-08-30 12:50:17 -07:00
parent 5bf2d86221
commit 00300cdf81
3 changed files with 61 additions and 59 deletions

View file

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

View file

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

View file

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