From 24a612fca77fc893fae34bb4756e0e0b07c92142 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Mon, 17 Oct 2022 18:37:23 +0000 Subject: [PATCH] aiohttp: initialize session in backend --- mmgen/globalvars.py | 6 ++---- mmgen/proto/btc/rpc.py | 2 +- mmgen/proto/eth/rpc.py | 2 +- mmgen/rpc.py | 36 +++++++++++++++++++++++++++--------- mmgen/util.py | 16 ++-------------- test/test_py_d/ts_ethdev.py | 8 +++----- test/test_py_d/ts_main.py | 2 +- test/test_py_d/ts_regtest.py | 2 +- test/unit_tests_d/ut_rpc.py | 2 +- 9 files changed, 39 insertions(+), 37 deletions(-) diff --git a/mmgen/globalvars.py b/mmgen/globalvars.py index 8ed45ac2..ed4968b5 100755 --- a/mmgen/globalvars.py +++ b/mmgen/globalvars.py @@ -40,7 +40,7 @@ class GlobalContext(Lockable): 3 - command line """ _autolock = False - _set_ok = ('session',) + _set_ok = () _reset_ok = ('stdout','stderr','accept_defaults') _use_class_attr = True @@ -99,7 +99,6 @@ class GlobalContext(Lockable): monero_wallet_rpc_user = 'monero' monero_wallet_rpc_password = '' aiohttp_rpc_queue_len = 16 - session = None cached_balances = False # regtest: @@ -181,7 +180,6 @@ class GlobalContext(Lockable): 'ignore_daemon_version', 'no_license', 'regtest', - 'rpc_backend', 'rpc_host', 'rpc_password', 'rpc_port', @@ -313,7 +311,7 @@ class GlobalContext(Lockable): stdin_tty = True if prog_name == 'unit_tests.py': _set_ok += ('debug_subseed',) - _reset_ok += ('force_standalone_scrypt_module','session') + _reset_ok += ('force_standalone_scrypt_module',) if os.getenv('MMGEN_DEBUG_ALL'): for name in env_opts: diff --git a/mmgen/proto/btc/rpc.py b/mmgen/proto/btc/rpc.py index 995cbb27..c2ef9b23 100755 --- a/mmgen/proto/btc/rpc.py +++ b/mmgen/proto/btc/rpc.py @@ -90,7 +90,7 @@ class BitcoinRPCClient(RPCClient,metaclass=AsyncInit): port = daemon.rpc_port ) self.set_auth() # set_auth() requires cookie, so must be called after __init__() tests daemon is listening - self.set_backend(backend) # backend requires self.auth + await self.set_backend_async(backend) # backend requires self.auth self.cached = {} diff --git a/mmgen/proto/eth/rpc.py b/mmgen/proto/eth/rpc.py index e01edf25..877627cf 100755 --- a/mmgen/proto/eth/rpc.py +++ b/mmgen/proto/eth/rpc.py @@ -44,7 +44,7 @@ class EthereumRPCClient(RPCClient,metaclass=AsyncInit): host = 'localhost' if g.test_suite else (g.rpc_host or 'localhost'), port = daemon.rpc_port ) - self.set_backend(backend) + await self.set_backend_async(backend) vi,bh,ci = await self.gathered_call(None, ( ('web3_clientVersion',()), diff --git a/mmgen/rpc.py b/mmgen/rpc.py index 1ffb4108..b52d1300 100755 --- a/mmgen/rpc.py +++ b/mmgen/rpc.py @@ -25,6 +25,7 @@ from decimal import Decimal from collections import namedtuple from .common import * +from .base_obj import AsyncInit from .objmethods import Hilite,InitErrors auth_data = namedtuple('rpc_auth_data',['user','passwd']) @@ -114,18 +115,28 @@ class RPCBackends: self.http_hdrs = caller.http_hdrs self.name = type(self).__name__ - class aiohttp(base): + class aiohttp(base,metaclass=AsyncInit): """ Contrary to the requests library, aiohttp won’t read environment variables by default. But you can do so by passing trust_env=True into aiohttp.ClientSession constructor to honor HTTP_PROXY, HTTPS_PROXY, WS_PROXY or WSS_PROXY environment variables (all are case insensitive). """ - def __init__(self,caller): + + def __del__(self): + self.connector.close() + self.session.detach() + del self.session + + async def __init__(self,caller): super().__init__(caller) - self.session = g.session + import aiohttp + self.connector = aiohttp.TCPConnector(limit_per_host=g.aiohttp_rpc_queue_len) + self.session = aiohttp.ClientSession( + headers = { 'Content-Type': 'application/json' }, + connector = self.connector, + ) if caller.auth_type == 'basic': - import aiohttp self.auth = aiohttp.BasicAuth(*caller.auth,encoding='UTF-8') else: self.auth = None @@ -293,12 +304,19 @@ class RPCClient(MMGenObject): self.timeout = g.http_timeout self.auth = None - def set_backend(self,backend=None): - bn = backend or opt.rpc_backend - if bn == 'auto': - self.backend = {'linux':RPCBackends.httplib,'win':RPCBackends.requests}[g.platform](self) + def _get_backend(self,backend): + backend_id = backend or opt.rpc_backend + if backend_id == 'auto': + return {'linux':RPCBackends.httplib,'win':RPCBackends.requests}[g.platform](self) else: - self.backend = getattr(RPCBackends,bn)(self) + return getattr(RPCBackends,backend_id)(self) + + def set_backend(self,backend=None): + self.backend = self._get_backend(backend) + + async def set_backend_async(self,backend=None): + ret = self._get_backend(backend) + self.backend = (await ret) if type(ret).__name__ == 'coroutine' else ret def set_auth(self): """ diff --git a/mmgen/util.py b/mmgen/util.py index 97e740d0..550aa122 100755 --- a/mmgen/util.py +++ b/mmgen/util.py @@ -383,21 +383,9 @@ def get_subclasses(cls,names=False): yield j return tuple((c.__name__ for c in gen(cls)) if names else gen(cls)) -def run_session(callback,backend=None): - - async def do(): - if (backend or opt.rpc_backend) == 'aiohttp': - import aiohttp - async with aiohttp.ClientSession( - headers = { 'Content-Type': 'application/json' }, - connector = aiohttp.TCPConnector(limit_per_host=g.aiohttp_rpc_queue_len), - ) as g.session: - return await callback - else: - return await callback - +def run_session(coro): import asyncio - return asyncio.run(do()) + return asyncio.run(coro) def wrap_ripemd160(called=[]): if not called: diff --git a/test/test_py_d/ts_ethdev.py b/test/test_py_d/ts_ethdev.py index 1db31d7f..6ddf9933 100755 --- a/test/test_py_d/ts_ethdev.py +++ b/test/test_py_d/ts_ethdev.py @@ -127,7 +127,7 @@ coin = g.coin class TestSuiteEthdev(TestSuiteBase,TestSuiteShared): 'Ethereum transacting, token deployment and tracking wallet operations' networks = ('eth','etc') - passthru_opts = ('coin','daemon_id','http_timeout') + passthru_opts = ('coin','daemon_id','http_timeout','rpc_backend') extra_spawn_args = ['--regtest=1'] tmpdir_nums = [22] color = True @@ -407,10 +407,8 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared): @property async def rpc(self): - if not hasattr(self,'_rpc'): - from mmgen.rpc import rpc_init - self._rpc = await rpc_init(self.proto) - return self._rpc + from mmgen.rpc import rpc_init + return await rpc_init(self.proto) async def setup(self): self.spawn('',msg_only=True) diff --git a/test/test_py_d/ts_main.py b/test/test_py_d/ts_main.py index 742f99ea..67746498 100755 --- a/test/test_py_d/ts_main.py +++ b/test/test_py_d/ts_main.py @@ -69,7 +69,7 @@ class TestSuiteMain(TestSuiteBase,TestSuiteShared): 'basic operations with emulated tracking wallet' tmpdir_nums = [1,2,3,4,5,14,15,16,20,21] networks = ('btc','btc_tn','ltc','ltc_tn','bch','bch_tn') - passthru_opts = ('daemon_data_dir','rpc_port','coin','testnet') + passthru_opts = ('daemon_data_dir','rpc_port','coin','testnet','rpc_backend') segwit_opts_ok = True color = True need_daemon = True diff --git a/test/test_py_d/ts_regtest.py b/test/test_py_d/ts_regtest.py index dbf6494c..7e62bebc 100755 --- a/test/test_py_d/ts_regtest.py +++ b/test/test_py_d/ts_regtest.py @@ -145,7 +145,7 @@ from .ts_shared import * class TestSuiteRegtest(TestSuiteBase,TestSuiteShared): 'transacting and tracking wallet operations via regtest mode' networks = ('btc','ltc','bch') - passthru_opts = ('coin',) + passthru_opts = ('coin','rpc_backend') extra_spawn_args = ['--regtest=1'] tmpdir_nums = [17] color = True diff --git a/test/unit_tests_d/ut_rpc.py b/test/unit_tests_d/ut_rpc.py index 091bcab6..308ead72 100755 --- a/test/unit_tests_d/ut_rpc.py +++ b/test/unit_tests_d/ut_rpc.py @@ -96,7 +96,7 @@ def run_test(network_ids,test_cf_auth=False,daemon_ids=None): for n,backend in enumerate(g.autoset_opts['rpc_backend'].choices): test = getattr(init_test,d.proto.coin.lower()) - rpc = run_session(test(d.proto,backend,d),backend=backend) + rpc = run_session(test(d.proto,backend,d)) if not n and opt.verbose: print_daemon_info(rpc)