1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
class DuplicatePluginName(Exception):
pass
class PluginDict(object):
"""Helper for GenericPluginMeta class
Behaves basically like a standard dict, but will raise an exception
when asked to update an existing value.
"""
def __init__(self):
self.dict = {}
def __getitem__(self, *args):
return self.dict.__getitem__(*args)
def __setitem__(self, key, value):
if self.dict.has_key(key):
raise DuplicatePluginName()
else:
self.dict[key] = value
def items(self): return self.dict.items()
def keys(self): return self.dict.keys()
def values(self): return self.dict.values()
def __iter__(self): return self.dict.__iter__()
def __str__(self): return self.dict.__str__()
def __repr__(self): return self.dict.__repr__()
def __len__(self): return self.dict.__len__()
def has_key(self, key): return self.dict.has_key(key)
########################################################################
# Generic plugin system
########################################################################
# Plugin architecture (metaclass tricks) by Marty Alchin from
# http://gulopine.gamemusic.org/2008/jan/10/simple-plugin-framework/
# Slightly modified go store plugins as dict.
########################################################################
class GenericPluginMeta(type):
def __init__(cls, name, bases, attrs):
if not hasattr(cls, 'plugins'):
# This branch only executes when processing the mount point itself.
# So, since this is a new plugin type, not an implementation, this
# class shouldn't be registered as a plugin. Instead, it sets up a
# list where plugins can be registered later.
cls.plugins = PluginDict()
elif hasattr(cls, 'name'):
# This must be a plugin implementation, which should be registered.
# Simply appending it to the list is all that's needed to keep
# track of it later.
cls.plugins[cls.name] = cls
else:
# This must be an abstract subclass of plugins.
pass
|