mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-23 06:55:13 +01:00
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>
This commit is contained in:
parent
71934f983a
commit
a707ae091d
1 changed files with 37 additions and 5 deletions
|
@ -1,5 +1,6 @@
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from lightning import LightningRpc
|
from lightning import LightningRpc
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
import json
|
import json
|
||||||
|
@ -9,6 +10,11 @@ import sys
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
|
class MethodType(Enum):
|
||||||
|
RPCMETHOD = 0
|
||||||
|
HOOK = 1
|
||||||
|
|
||||||
|
|
||||||
class Plugin(object):
|
class Plugin(object):
|
||||||
"""Controls interactions with lightningd, and bundles functionality.
|
"""Controls interactions with lightningd, and bundles functionality.
|
||||||
|
|
||||||
|
@ -66,7 +72,7 @@ class Plugin(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Register the function with the name
|
# Register the function with the name
|
||||||
self.methods[name] = func
|
self.methods[name] = (func, MethodType.RPCMETHOD)
|
||||||
|
|
||||||
def add_subscription(self, topic, func):
|
def add_subscription(self, topic, func):
|
||||||
"""Add a subscription to our list of subscriptions.
|
"""Add a subscription to our list of subscriptions.
|
||||||
|
@ -133,6 +139,25 @@ class Plugin(object):
|
||||||
return f
|
return f
|
||||||
return decorator
|
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):
|
def _exec_func(self, func, request):
|
||||||
params = request['params']
|
params = request['params']
|
||||||
sig = inspect.signature(func)
|
sig = inspect.signature(func)
|
||||||
|
@ -173,7 +198,7 @@ class Plugin(object):
|
||||||
|
|
||||||
if name not in self.methods:
|
if name not in self.methods:
|
||||||
raise ValueError("No method {} found.".format(name))
|
raise ValueError("No method {} found.".format(name))
|
||||||
func = self.methods[name]
|
func, _ = self.methods[name]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = {
|
result = {
|
||||||
|
@ -244,7 +269,7 @@ class Plugin(object):
|
||||||
# then unstash this and call it.
|
# then unstash this and call it.
|
||||||
if 'init' in self.methods:
|
if 'init' in self.methods:
|
||||||
self.init = self.methods['init']
|
self.init = self.methods['init']
|
||||||
self.methods['init'] = self._init
|
self.methods['init'] = (self._init, MethodType.RPCMETHOD)
|
||||||
|
|
||||||
partial = ""
|
partial = ""
|
||||||
for l in self.stdin:
|
for l in self.stdin:
|
||||||
|
@ -258,11 +283,17 @@ class Plugin(object):
|
||||||
|
|
||||||
def _getmanifest(self):
|
def _getmanifest(self):
|
||||||
methods = []
|
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
|
# Skip the builtin ones, they don't get reported
|
||||||
if name in ['getmanifest', 'init']:
|
if name in ['getmanifest', 'init']:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if typ == MethodType.HOOK:
|
||||||
|
hooks.append(name)
|
||||||
|
continue
|
||||||
|
|
||||||
doc = inspect.getdoc(func)
|
doc = inspect.getdoc(func)
|
||||||
doc = re.sub('\n+', ' ', doc)
|
doc = re.sub('\n+', ' ', doc)
|
||||||
if not doc:
|
if not doc:
|
||||||
|
@ -280,6 +311,7 @@ class Plugin(object):
|
||||||
'options': list(self.options.values()),
|
'options': list(self.options.values()),
|
||||||
'rpcmethods': methods,
|
'rpcmethods': methods,
|
||||||
'subscriptions': list(self.subscriptions.keys()),
|
'subscriptions': list(self.subscriptions.keys()),
|
||||||
|
'hooks': hooks,
|
||||||
}
|
}
|
||||||
|
|
||||||
def _init(self, options, configuration, request):
|
def _init(self, options, configuration, request):
|
||||||
|
@ -293,7 +325,7 @@ class Plugin(object):
|
||||||
# Swap the registered `init` method handler back in and
|
# Swap the registered `init` method handler back in and
|
||||||
# re-dispatch
|
# re-dispatch
|
||||||
if self.init:
|
if self.init:
|
||||||
self.methods['init'] = self.init
|
self.methods['init'], _ = self.init
|
||||||
self.init = None
|
self.init = None
|
||||||
return self._exec_func(self.methods['init'], request)
|
return self._exec_func(self.methods['init'], request)
|
||||||
return None
|
return None
|
||||||
|
|
Loading…
Add table
Reference in a new issue