forked from platypush/platypush
Plugin action decorators can now be inherited from parent classes
This commit is contained in:
parent
35c5e2d8f7
commit
95d86829aa
2 changed files with 26 additions and 8 deletions
|
@ -36,7 +36,10 @@ class Plugin(object):
|
||||||
if 'logging' in kwargs:
|
if 'logging' in kwargs:
|
||||||
self.logger.setLevel(getattr(logging, kwargs['logging'].upper()))
|
self.logger.setLevel(getattr(logging, kwargs['logging'].upper()))
|
||||||
|
|
||||||
self.registered_actions = set(get_decorators(self.__class__).get('action', []))
|
self.registered_actions = set(
|
||||||
|
get_decorators(self.__class__, climb_class_hierarchy=True)
|
||||||
|
.get('action', [])
|
||||||
|
)
|
||||||
|
|
||||||
def run(self, method, *args, **kwargs):
|
def run(self, method, *args, **kwargs):
|
||||||
if method not in self.registered_actions:
|
if method not in self.registered_actions:
|
||||||
|
|
|
@ -73,12 +73,16 @@ def get_hash(s):
|
||||||
return hashlib.sha256(s.encode('utf-8')).hexdigest()
|
return hashlib.sha256(s.encode('utf-8')).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
def get_decorators(cls):
|
def get_decorators(cls, climb_class_hierarchy=False):
|
||||||
target = cls
|
"""
|
||||||
|
Get the decorators of a class as a {"decorator_name": [list of methods]} dictionary
|
||||||
|
:param climb_class_hierarchy: If set to True (default: False), it will search return the decorators in the parent classes as well
|
||||||
|
:type climb_class_hierarchy: bool
|
||||||
|
"""
|
||||||
|
|
||||||
decorators = {}
|
decorators = {}
|
||||||
|
|
||||||
def visit_FunctionDef(node):
|
def visit_FunctionDef(node):
|
||||||
# decorators[node.name] = []
|
|
||||||
for n in node.decorator_list:
|
for n in node.decorator_list:
|
||||||
name = ''
|
name = ''
|
||||||
if isinstance(n, ast.Call):
|
if isinstance(n, ast.Call):
|
||||||
|
@ -86,13 +90,24 @@ def get_decorators(cls):
|
||||||
else:
|
else:
|
||||||
name = n.attr if isinstance(n, ast.Attribute) else n.id
|
name = n.attr if isinstance(n, ast.Attribute) else n.id
|
||||||
|
|
||||||
decorators[name] = decorators.get(name, [])
|
decorators[name] = decorators.get(name, set())
|
||||||
# decorators[node.name].append(name)
|
decorators[name].add(node.name)
|
||||||
decorators[name].append(node.name)
|
|
||||||
|
if climb_class_hierarchy:
|
||||||
|
targets = inspect.getmro(cls)
|
||||||
|
else:
|
||||||
|
targets = [cls]
|
||||||
|
|
||||||
node_iter = ast.NodeVisitor()
|
node_iter = ast.NodeVisitor()
|
||||||
node_iter.visit_FunctionDef = visit_FunctionDef
|
node_iter.visit_FunctionDef = visit_FunctionDef
|
||||||
node_iter.visit(ast.parse(inspect.getsource(target)))
|
|
||||||
|
for target in targets:
|
||||||
|
try:
|
||||||
|
node_iter.visit(ast.parse(inspect.getsource(target)))
|
||||||
|
except TypeError:
|
||||||
|
# Ignore built-in classes
|
||||||
|
pass
|
||||||
|
|
||||||
return decorators
|
return decorators
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue