Browse Source

pylightning: Add hooks as a new type of method

Instead of creating a new map I opted to re-use the Plugin.methods
map, since the semantics are really similar and we don't allow
duplicates. The only difference is in how they are announced to
lightningd, so we use an enum to differentiate rpcmethods from hooks,
since only the former will get added to the JSON-RPC dispatch table in
lightningd.

Signed-off-by: Christian Decker <decker.christian@gmail.com>
plugin-timeout-inc
Christian Decker 6 years ago
committed by Rusty Russell
parent
commit
a707ae091d
  1. 42
      contrib/pylightning/lightning/plugin.py

42
contrib/pylightning/lightning/plugin.py

@ -1,5 +1,6 @@
from collections import OrderedDict
from lightning import LightningRpc
from enum import Enum
import inspect
import json
@ -9,6 +10,11 @@ import sys
import traceback
class MethodType(Enum):
RPCMETHOD = 0
HOOK = 1
class Plugin(object):
"""Controls interactions with lightningd, and bundles functionality.
@ -66,7 +72,7 @@ class Plugin(object):
)
# Register the function with the name
self.methods[name] = func
self.methods[name] = (func, MethodType.RPCMETHOD)
def add_subscription(self, topic, func):
"""Add a subscription to our list of subscriptions.
@ -133,6 +139,25 @@ class Plugin(object):
return f
return decorator
def add_hook(self, name, func):
"""Register a hook that is called synchronously by lightningd on events
"""
if name in self.methods:
raise ValueError(
"Method {} was already registered".format(name, self.methods[name])
)
self.methods[name] = (func, MethodType.HOOK)
def hook(self, method_name):
"""Decorator to add a plugin hook to the dispatch table.
Internally uses add_hook.
"""
def decorator(f):
self.add_hook(method_name, f)
return f
return decorator
def _exec_func(self, func, request):
params = request['params']
sig = inspect.signature(func)
@ -173,7 +198,7 @@ class Plugin(object):
if name not in self.methods:
raise ValueError("No method {} found.".format(name))
func = self.methods[name]
func, _ = self.methods[name]
try:
result = {
@ -244,7 +269,7 @@ class Plugin(object):
# then unstash this and call it.
if 'init' in self.methods:
self.init = self.methods['init']
self.methods['init'] = self._init
self.methods['init'] = (self._init, MethodType.RPCMETHOD)
partial = ""
for l in self.stdin:
@ -258,11 +283,17 @@ class Plugin(object):
def _getmanifest(self):
methods = []
for name, func in self.methods.items():
hooks = []
for name, entry in self.methods.items():
func, typ = entry
# Skip the builtin ones, they don't get reported
if name in ['getmanifest', 'init']:
continue
if typ == MethodType.HOOK:
hooks.append(name)
continue
doc = inspect.getdoc(func)
doc = re.sub('\n+', ' ', doc)
if not doc:
@ -280,6 +311,7 @@ class Plugin(object):
'options': list(self.options.values()),
'rpcmethods': methods,
'subscriptions': list(self.subscriptions.keys()),
'hooks': hooks,
}
def _init(self, options, configuration, request):
@ -293,7 +325,7 @@ class Plugin(object):
# Swap the registered `init` method handler back in and
# re-dispatch
if self.init:
self.methods['init'] = self.init
self.methods['init'], _ = self.init
self.init = None
return self._exec_func(self.methods['init'], request)
return None

Loading…
Cancel
Save