def test_method_exceptions(): """A bunch of tests that should fail calling the methods.""" p = Plugin(autopatch=False) def fake_write_result(resultdict): global result_dict result_dict = resultdict @p.method("test_raise") def test_raise(): raise RpcException("testing RpcException", code=-1000) req = Request(p, 1, "test_raise", {}) req._write_result = fake_write_result p._dispatch_request(req) assert result_dict['jsonrpc'] == '2.0' assert result_dict['id'] == 1 assert result_dict['error']['code'] == -1000 assert result_dict['error']['message'] == "testing RpcException" @p.method("test_raise2") def test_raise2(): raise Exception("normal exception") req = Request(p, 1, "test_raise2", {}) req._write_result = fake_write_result p._dispatch_request(req) assert result_dict['jsonrpc'] == '2.0' assert result_dict['id'] == 1 assert result_dict['error']['code'] == -32600 assert result_dict['error'][ 'message'] == "Error while processing test_raise2: normal exception"
def get_stub(): plugin = Plugin() plugin.avail_interval = 60 plugin.avail_window = 3600 plugin.persist = {} plugin.persist['peerstate'] = {} plugin.persist['availcount'] = 0 return plugin
def test_argument_coercion(): p = Plugin(autopatch=False) def test1(msat: Millisatoshi): assert isinstance(msat, Millisatoshi) ba = p._bind_kwargs(test1, {"msat": "100msat"}, None) test1(*ba.args) ba = p._bind_pos(test1, ["100msat"], None) test1(*ba.args, **ba.kwargs)
def test_duplicate_result(): p = Plugin(autopatch=False) def test1(request): request.set_result(1) # MARKER1 request.set_result(1) req = Request(p, req_id=1, method="test1", params=[]) ba = p._bind_kwargs(test1, {}, req) with pytest.raises( ValueError, match=r'current state is RequestState\.FINISHED(.*\n.*)*MARKER1'): test1(*ba.args) def test2(request): request.set_exception(1) # MARKER2 request.set_exception(1) req = Request(p, req_id=2, method="test2", params=[]) ba = p._bind_kwargs(test2, {}, req) with pytest.raises( ValueError, match=r'current state is RequestState\.FAILED(.*\n*.*)*MARKER2'): test2(*ba.args) def test3(request): request.set_exception(1) # MARKER3 request.set_result(1) req = Request(p, req_id=3, method="test3", params=[]) ba = p._bind_kwargs(test3, {}, req) with pytest.raises( ValueError, match=r'current state is RequestState\.FAILED(.*\n*.*)*MARKER3'): test3(*ba.args) def test4(request): request.set_result(1) # MARKER4 request.set_exception(1) req = Request(p, req_id=4, method="test4", params=[]) ba = p._bind_kwargs(test4, {}, req) with pytest.raises( ValueError, match=r'current state is RequestState\.FINISHED(.*\n*.*)*MARKER4'): test4(*ba.args)
from tqdm import tqdm from typing import Mapping, Type, Iterator from urllib.parse import urlparse import json import logging import os import re import shutil import struct import sys import sqlite3 import tempfile import time import psutil plugin = Plugin() root = logging.getLogger() root.setLevel(logging.INFO) handler = logging.StreamHandler(sys.stdout) handler.setLevel(logging.DEBUG) formatter = logging.Formatter('%(message)s') handler.setFormatter(formatter) root.addHandler(handler) # A change that was proposed by c-lightning that needs saving to the # backup. `version` is the database version before the transaction was # applied. The optional snapshot reqpresents a complete copy of the database, # as it was before applying the `transaction`. This is used by the plugin from # time to time to allow the backend to compress the changelog and forms a new
#!/usr/bin/env python3 from pyln.client import Plugin, Millisatoshi from packaging import version from collections import namedtuple from summary_avail import * import pyln.client from math import floor, log10 import requests import shelve import threading import time plugin = Plugin(autopatch=True) have_utf8 = False # __version__ was introduced in 0.0.7.1, with utf8 passthrough support. try: if version.parse(pyln.client.__version__) >= version.parse("0.0.7.1"): have_utf8 = True except Exception: pass Channel = namedtuple('Channel', ['total', 'ours', 'theirs', 'pid', 'private', 'connected', 'scid', 'avail']) Charset = namedtuple('Charset', ['double_left', 'left', 'bar', 'mid', 'right', 'double_right', 'empty']) if have_utf8: draw = Charset('╟', '├', '─', '┼', '┤', '╢', '║') else: draw = Charset('#', '[', '-', '/', ']', '#', '|') summary_description = "Gets summary information about this node.\n"\
#!/usr/bin/env python3 from pyln.client import Plugin # Register a different set feature of feature bits for each location so we can # later check that they are being passed correctly. plugin = Plugin( dynamic=False, init_features=1 << 201, node_features=1 << 203, invoice_features=1 << 205, ) plugin.run()
#!/usr/bin/env python3 from pyln.client import Plugin import json import psutil import subprocess import threading import time import os try: # C-lightning v0.7.2 plugin = Plugin(dynamic=False) except: plugin = Plugin() class ChildPlugin(object): def __init__(self, path, plugin): self.path = path self.plugin = plugin self.status = 'stopped' self.proc = None self.iolock = threading.Lock() self.decoder = json.JSONDecoder() self.manifest = None self.init = None self.reader = None def watch(self): last = os.path.getmtime(self.path) while True:
private_key: str redeem_script: str private: bool invoice_amount: int inbound_percentage: int invoice_label: str preimage_hash: str address: str expected_amount: int bip21: str PLUGIN = Plugin() def print_error(message: str): print(message) return { "error": message[0].lower() + message[1:], } def get_keys(): private_key = bytes.fromhex(binascii.hexlify(urandom(32)).decode()) signing_key = ecdsa.SigningKey.from_string(private_key, curve=ecdsa.SECP256k1) public_key = signing_key.get_verifying_key()
def test_simple_methods(): """Test the dispatch of methods, with a variety of bindings. """ call_list = [] p = Plugin(autopatch=False) @p.method("test1") def test1(name): """Has a single positional argument.""" assert name == 'World' call_list.append(test1) request = p._parse_request({ 'id': 1, 'jsonrpc': '2.0', 'method': 'test1', 'params': { 'name': 'World' } }) p._dispatch_request(request) assert call_list == [test1] @p.method("test2") def test2(name, plugin): """Also asks for the plugin instance. """ assert plugin == p call_list.append(test2) request = p._parse_request({ 'id': 1, 'jsonrpc': '2.0', 'method': 'test2', 'params': { 'name': 'World' } }) p._dispatch_request(request) assert call_list == [test1, test2] @p.method("test3") def test3(name, request): """Also asks for the request instance. """ assert request is not None call_list.append(test3) request = p._parse_request({ 'id': 1, 'jsonrpc': '2.0', 'method': 'test3', 'params': { 'name': 'World' } }) p._dispatch_request(request) assert call_list == [test1, test2, test3] @p.method("test4") def test4(name): """Try the positional arguments.""" assert name == 'World' call_list.append(test4) request = p._parse_request({ 'id': 1, 'jsonrpc': '2.0', 'method': 'test4', 'params': ['World'] }) p._dispatch_request(request) assert call_list == [test1, test2, test3, test4] @p.method("test5") def test5(name, request, plugin): """Try the positional arguments, mixing in the request and plugin.""" assert name == 'World' assert request is not None assert p == plugin call_list.append(test5) request = p._parse_request({ 'id': 1, 'jsonrpc': '2.0', 'method': 'test5', 'params': ['World'] }) p._dispatch_request(request) assert call_list == [test1, test2, test3, test4, test5] answers = [] @p.method("test6") def test6(name, answer=42): """This method has a default value for one of its params""" assert name == 'World' answers.append(answer) call_list.append(test6) # Both calls should work (with and without the default param request = p._parse_request({ 'id': 1, 'jsonrpc': '2.0', 'method': 'test6', 'params': ['World'] }) p._dispatch_request(request) assert call_list == [test1, test2, test3, test4, test5, test6] assert answers == [42] request = p._parse_request({ 'id': 1, 'jsonrpc': '2.0', 'method': 'test6', 'params': ['World', 31337] }) p._dispatch_request(request) assert call_list == [test1, test2, test3, test4, test5, test6, test6] assert answers == [42, 31337]
def test_bind_kwargs(): p = Plugin(autopatch=False) req = object() params = {'name': 'World'} def test1(name): assert name == 'World' bound = p._bind_kwargs(test1, params, req) test1(*bound.args, **bound.kwargs) def test2(name, plugin): assert name == 'World' assert plugin == p bound = p._bind_kwargs(test2, params, req) test2(*bound.args, **bound.kwargs) def test3(plugin, name): assert name == 'World' assert plugin == p bound = p._bind_kwargs(test3, params, req) test3(*bound.args, **bound.kwargs) def test4(plugin, name, request): assert name == 'World' assert plugin == p assert request == req bound = p._bind_kwargs(test4, params, req) test4(*bound.args, **bound.kwargs) def test5(request, name, plugin): assert name == 'World' assert plugin == p assert request == req bound = p._bind_kwargs(test5, params, req) test5(*bound.args, **bound.kwargs) def test6(request, name, plugin, answer=42): assert name == 'World' assert plugin == p assert request == req assert answer == 42 bound = p._bind_kwargs(test6, params, req) test6(*bound.args, **bound.kwargs) # Now mix in a catch-all parameter that needs to be assigned def test6(request, name, plugin, *args, **kwargs): assert name == 'World' assert plugin == p assert request == req assert args == () assert kwargs == {'answer': 42} bound = p._bind_kwargs(test6, {'name': 'World', 'answer': 42}, req) test6(*bound.args, **bound.kwargs)
def test_positional_inject(): p = Plugin() rdict = Request(plugin=p, req_id=1, method='func', params={ 'a': 1, 'b': 2, 'kwa': 3, 'kwb': 4 }) rarr = Request( plugin=p, req_id=1, method='func', params=[1, 2, 3, 4], ) def pre_args(plugin, a, b, kwa=3, kwb=4): assert (plugin, a, b, kwa, kwb) == (p, 1, 2, 3, 4) def in_args(a, plugin, b, kwa=3, kwb=4): assert (plugin, a, b, kwa, kwb) == (p, 1, 2, 3, 4) def post_args(a, b, plugin, kwa=3, kwb=4): assert (plugin, a, b, kwa, kwb) == (p, 1, 2, 3, 4) def post_kwargs(a, b, kwa=3, kwb=4, plugin=None): assert (plugin, a, b, kwa, kwb) == (p, 1, 2, 3, 4) def in_multi_args(a, request, plugin, b, kwa=3, kwb=4): assert request in [rarr, rdict] assert (plugin, a, b, kwa, kwb) == (p, 1, 2, 3, 4) def in_multi_mix_args(a, plugin, b, request=None, kwa=3, kwb=4): assert request in [rarr, rdict] assert (plugin, a, b, kwa, kwb) == (p, 1, 2, 3, 4) def extra_def_arg(a, b, c, d, e=42): """ Also uses a different name for kwa and kwb """ assert (a, b, c, d, e) == (1, 2, 3, 4, 42) def count(plugin, count, request): assert count == 42 and plugin == p funcs = [pre_args, in_args, post_args, post_kwargs, in_multi_args] for func, request in itertools.product(funcs, [rdict, rarr]): p._exec_func(func, request) p._exec_func(extra_def_arg, rarr) p._exec_func(count, Request( plugin=p, req_id=1, method='func', params=[42], )) # This should fail since it is missing one positional argument with pytest.raises(TypeError): p._exec_func(count, Request(plugin=p, req_id=1, method='func', params=[]))
def test_methods_errors(): """A bunch of tests that should fail calling the methods.""" call_list = [] p = Plugin(autopatch=False) # Fails because we haven't added the method yet request = p._parse_request({ 'id': 1, 'jsonrpc': '2.0', 'method': 'test1', 'params': {} }) with pytest.raises(ValueError): p._dispatch_request(request) assert call_list == [] @p.method("test1") def test1(name): call_list.append(test1) # Attempting to add it twice should fail with pytest.raises(ValueError): p.add_method("test1", test1) # Fails because it is missing the 'name' argument request = p._parse_request({ 'id': 1, 'jsonrpc': '2.0', 'method': 'test1', 'params': {} }) with pytest.raises(TypeError): p._exec_func(test1, request) assert call_list == [] # The same with positional arguments request = p._parse_request({ 'id': 1, 'jsonrpc': '2.0', 'method': 'test1', 'params': [] }) with pytest.raises(TypeError): p._exec_func(test1, request) assert call_list == [] # Fails because we have a non-matching argument request = p._parse_request({ 'id': 1, 'jsonrpc': '2.0', 'method': 'test1', 'params': { 'name': 'World', 'extra': 1 } }) with pytest.raises(TypeError): p._exec_func(test1, request) assert call_list == [] request = p._parse_request({ 'id': 1, 'jsonrpc': '2.0', 'method': 'test1', 'params': ['World', 1] }) with pytest.raises(TypeError): p._exec_func(test1, request) assert call_list == []