Browse Source

pyln: Add command notification support for plugins

Changelog-Added: pyln-client: Plugin methods can now report progress or status via the `Request.notify` function
ppa
Christian Decker 4 years ago
parent
commit
84b3653606
  1. 55
      contrib/pyln-client/pyln/client/plugin.py
  2. 15
      tests/test_plugin.py

55
contrib/pyln-client/pyln/client/plugin.py

@ -141,6 +141,47 @@ class Request(dict):
def _write_result(self, result: dict) -> None: def _write_result(self, result: dict) -> None:
self.plugin._write_locked(result) self.plugin._write_locked(result)
def _notify(self, method: str, params: JSONType) -> None:
"""Send a notification to the caller.
Can contain a variety of things, but is usually used to report
progress or command status.
"""
self._write_result({
'jsonrpc': '2.0',
'params': params,
"method": method,
})
def notify(self, message: str, level: str = 'info') -> None:
"""Send a message notification to the caller.
"""
self._notify(
"message",
params={
'id': self.id,
'level': level,
'message': message,
}
)
def progress(self,
progress: int,
total: int,
stage: Optional[int] = None,
stage_total: Optional[int] = None
) -> None:
d: Dict[str, JSONType] = {
"id": self.id,
"num": progress,
"total": total,
}
if stage is not None and stage_total is not None:
d['stage'] = {"num": stage, "total": stage_total}
self._notify("progress", d)
# If a hook call fails we need to coerce it into something the main daemon can # If a hook call fails we need to coerce it into something the main daemon can
# handle. Returning an error is not an option since we explicitly do not allow # handle. Returning an error is not an option since we explicitly do not allow
@ -639,22 +680,14 @@ class Plugin(object):
def notify_message(self, request: Request, message: str, def notify_message(self, request: Request, message: str,
level: str = 'info') -> None: level: str = 'info') -> None:
"""Send a notification message to sender of this request""" """Send a notification message to sender of this request"""
self.notify("message", {"id": request.id, request.notify(message=message)
"level": level,
"message": message})
def notify_progress(self, request: Request, def notify_progress(self, request: Request,
progress: int, progress_total: int, progress: int, progress_total: int,
stage: Optional[int] = None, stage: Optional[int] = None,
stage_total: Optional[int] = None) -> None: stage_total: Optional[int] = None) -> None:
"""Send a progerss message to sender of this request: if more than one stage, set stage and stage_total""" """Send a progress message to sender of this request: if more than one stage, set stage and stage_total"""
d: Dict[str, Any] = {"id": request.id, request.progress(progress, progress_total, stage, stage_total)
"num": progress,
"total": progress_total}
if stage_total is not None:
d['stage'] = {"num": stage, "total": stage_total}
self.notify("progress", d)
def _parse_request(self, jsrequest: Dict[str, JSONType]) -> Request: def _parse_request(self, jsrequest: Dict[str, JSONType]) -> Request:
i = jsrequest.get('id', None) i = jsrequest.get('id', None)

15
tests/test_plugin.py

@ -2027,15 +2027,18 @@ def test_notify(node_factory):
assert out[2 + i].endswith("|\n") assert out[2 + i].endswith("|\n")
else: else:
assert out[2 + i].endswith("|\r") assert out[2 + i].endswith("|\r")
assert out[102] == '\r'
assert out[102] == '# Beginning stage 2\n'
assert out[103] == '\r'
for i in range(10): for i in range(10):
assert out[103 + i].startswith("# Stage 2/2 {:>2}/10 |".format(1 + i)) assert out[104 + i].startswith("# Stage 2/2 {:>2}/10 |".format(1 + i))
if i == 9: if i == 9:
assert out[103 + i].endswith("|\n") assert out[104 + i].endswith("|\n")
else: else:
assert out[103 + i].endswith("|\r") assert out[104 + i].endswith("|\r")
assert out[113] == '"This worked"\n' assert out[114] == '"This worked"\n'
assert len(out) == 114 assert len(out) == 115
# At debug level, we get the second prompt. # At debug level, we get the second prompt.
out = subprocess.check_output(['cli/lightning-cli', out = subprocess.check_output(['cli/lightning-cli',

Loading…
Cancel
Save