Ich habe viel Zeit damit verbracht, ein kleines Plugin-System für Python zu finden, das für meine Bedürfnisse geeignet ist. Aber dann dachte ich nur, wenn es bereits eine Vererbung, die natürlich und flexibel ist, warum nicht verwenden Sie es.
Das einzige Problem bei der Verwendung von Vererbung für Plugins ist, dass Sie nicht wissen, was die spezifischsten (die niedrigste auf Vererbung Baum) Plugin-Klassen sind.
Dies könnte jedoch mit einer Metaklasse gelöst werden, die die Vererbung der Basisklasse verfolgt und möglicherweise eine Klasse erstellen könnte, die von den meisten spezifischen Plugins erbt ('Root extended' in der Abbildung unten)
![enter image description here]()
Ich habe also eine Lösung gefunden, indem ich eine solche Metaklasse kodiert habe:
class PluginBaseMeta(type):
def __new__(mcls, name, bases, namespace):
cls = super(PluginBaseMeta, mcls).__new__(mcls, name, bases, namespace)
if not hasattr(cls, '__pluginextensions__'): # parent class
cls.__pluginextensions__ = {cls} # set reflects lowest plugins
cls.__pluginroot__ = cls
cls.__pluginiscachevalid__ = False
else: # subclass
assert not set(namespace) & {'__pluginextensions__',
'__pluginroot__'} # only in parent
exts = cls.__pluginextensions__
exts.difference_update(set(bases)) # remove parents
exts.add(cls) # and add current
cls.__pluginroot__.__pluginiscachevalid__ = False
return cls
@property
def PluginExtended(cls):
# After PluginExtended creation we'll have only 1 item in set
# so this is used for caching, mainly not to create same PluginExtended
if cls.__pluginroot__.__pluginiscachevalid__:
return next(iter(cls.__pluginextensions__)) # only 1 item in set
else:
name = cls.__pluginroot__.__name__ + 'PluginExtended'
extended = type(name, tuple(cls.__pluginextensions__), {})
cls.__pluginroot__.__pluginiscachevalid__ = True
return extended
Wenn Sie also eine Root-Basis haben, die mit einer Metaklasse erstellt wurde, und einen Baum von Plugins haben, die davon erben, können Sie automatisch eine Klasse erhalten, die von den spezifischsten Plugins erbt, indem Sie einfach eine Unterklasse bilden:
class RootExtended(RootBase.PluginExtended):
... your code here ...
Die Codebasis ist ziemlich klein (~30 Zeilen reiner Code) und so flexibel, wie es die Vererbung erlaubt.
Wenn Sie interessiert sind, machen Sie mit @ https://github.com/thodnev/pluginlib