diff --git a/lbrynet/extras/cli.py b/lbrynet/extras/cli.py index df57384a1..41f5ed84b 100644 --- a/lbrynet/extras/cli.py +++ b/lbrynet/extras/cli.py @@ -2,63 +2,20 @@ import sys import json import asyncio import argparse -import typing +import logging import logging.handlers -import aiohttp from docopt import docopt from textwrap import dedent +import aiohttp + from lbrynet import __name__ as lbrynet_name, __version__ as lbrynet_version +from lbrynet.extras.daemon.loggly_handler import get_loggly_handler from lbrynet.conf import Config, CLIConfig from lbrynet.extras.daemon.Daemon import Daemon -from lbrynet.extras.daemon.client import LBRYAPIClient, JSONRPCException -from lbrynet.extras.daemon.loggly_handler import get_loggly_handler log = logging.getLogger(lbrynet_name) log.addHandler(logging.NullHandler()) -default_formatter = logging.Formatter("%(asctime)s %(levelname)-8s %(name)s:%(lineno)d: %(message)s") - -optional_path_getter_type = typing.Optional[typing.Callable[[], str]] - - -async def start_daemon(conf: Config, args): - file_handler = logging.handlers.RotatingFileHandler(conf.log_file_path, - maxBytes=2097152, backupCount=5) - file_handler.setFormatter(default_formatter) - log.addHandler(file_handler) - - if not args.quiet: - handler = logging.StreamHandler() - handler.setFormatter(default_formatter) - log.addHandler(handler) - - # mostly disable third part logging - logging.getLogger('urllib3').setLevel(logging.CRITICAL) - logging.getLogger('BitcoinRPC').setLevel(logging.INFO) - logging.getLogger('aioupnp').setLevel(logging.WARNING) - logging.getLogger('aiohttp').setLevel(logging.CRITICAL) - - if args.verbose: - log.setLevel(logging.DEBUG) - else: - log.setLevel(logging.INFO) - - if conf.share_usage_data: - loggly_handler = get_loggly_handler() - loggly_handler.setLevel(logging.ERROR) - log.addHandler(loggly_handler) - - log.info("Starting lbrynet-daemon from command line") - daemon = Daemon(conf) - try: - await daemon.start_listening() - except (OSError, asyncio.CancelledError): - return 1 - try: - await daemon.server.wait_closed() - except (KeyboardInterrupt, asyncio.CancelledError): - await daemon.shutdown() - return 0 def display(data): @@ -66,21 +23,30 @@ def display(data): async def execute_command(conf, method, params): - client = LBRYAPIClient(conf) - try: - result = await getattr(client, method)(params) - print(display(result)) - except aiohttp.ClientConnectionError: - print("Could not connect to daemon. Are you sure it's running?") - except JSONRPCException as err: - print(err) + async with aiohttp.ClientSession() as session: + try: + message = {'method': method, 'params': params} + async with session.get(conf.api_connection_url, json=message) as resp: + try: + data = await resp.json() + if 'result' in data: + display(data['result']) + elif 'error' in data: + if 'message' in data['error']: + display(data['error']['message']) + else: + display(data['error']) + except Exception as e: + log.exception('Could not process response from server:', exc_info=e) + except aiohttp.ClientConnectionError: + print("Could not connect to daemon. Are you sure it's running?") def print_help(): print(dedent(""" NAME lbrynet - LBRY command line client. - + USAGE lbrynet [--data_dir=] [--wallet_dir=] [--download_dir=] [] @@ -211,36 +177,71 @@ def main(argv=None): argv = argv or sys.argv[1:] parser = get_argument_parser() args, command_args = parser.parse_known_args(argv) + conf = Config.create_from_arguments(args) if args.cli_version: print(f"{lbrynet_name} {lbrynet_version}") + return 0 + elif args.command == 'start': + if args.help: args.start_parser.print_help() return 0 - try: - asyncio.run(start_daemon(conf, args)) - except (KeyboardInterrupt, asyncio.CancelledError): - return 0 + default_formatter = logging.Formatter("%(asctime)s %(levelname)-8s %(name)s:%(lineno)d: %(message)s") + file_handler = logging.handlers.RotatingFileHandler(conf.log_file_path, maxBytes = 2097152, backupCount = 5) + file_handler.setFormatter(default_formatter) + log.addHandler(file_handler) + + if not args.quiet: + handler = logging.StreamHandler() + handler.setFormatter(default_formatter) + log.addHandler(handler) + # mostly disable third part logging + logging.getLogger('urllib3').setLevel(logging.CRITICAL) + logging.getLogger('BitcoinRPC').setLevel(logging.INFO) + logging.getLogger('aioupnp').setLevel(logging.WARNING) + logging.getLogger('aiohttp').setLevel(logging.CRITICAL) + + if args.verbose: + log.setLevel(logging.DEBUG) + else: + log.setLevel(logging.INFO) + if conf.share_usage_data: + loggly_handler = get_loggly_handler() + loggly_handler.setLevel(logging.ERROR) + log.addHandler(loggly_handler) + + log.debug('Final Settings: %s', conf.settings_dict) + log.info("Starting lbrynet-daemon from command line") + + daemon = Daemon(conf) + asyncio.run(daemon.start()) + elif args.command is not None: + doc = args.doc api_method_name = args.api_method_name if args.replaced_by: print(f"{args.api_method_name} is deprecated, using {args.replaced_by['api_method_name']}.") doc = args.replaced_by['doc'] api_method_name = args.replaced_by['api_method_name'] + if args.help: print(doc) - return 0 else: parsed = docopt(doc, command_args) params = set_kwargs(parsed) - asyncio.run(execute_command(conf, api_method_name, params)) + loop = asyncio.get_event_loop() + loop.run_until_complete(execute_command(conf, api_method_name, params)) + elif args.group is not None: args.group_parser.print_help() + else: parser.print_help() + return 0 diff --git a/lbrynet/extras/daemon/Daemon.py b/lbrynet/extras/daemon/Daemon.py index 6cd0894b1..c68819716 100644 --- a/lbrynet/extras/daemon/Daemon.py +++ b/lbrynet/extras/daemon/Daemon.py @@ -379,7 +379,7 @@ class Daemon(metaclass=JSONRPCServerType): if not os.path.isdir(self.conf.download_dir): os.makedirs(self.conf.download_dir) - async def start_listening(self): + async def start(self): try: self.server = await asyncio.get_event_loop().create_server( self.handler, self.conf.api_host, self.conf.api_port diff --git a/lbrynet/extras/daemon/client.py b/lbrynet/extras/daemon/client.py index 2a02c37c7..a9796d12f 100644 --- a/lbrynet/extras/daemon/client.py +++ b/lbrynet/extras/daemon/client.py @@ -16,18 +16,12 @@ class JSONRPCException(Exception): self.error = rpc_error -class LBRYAPIClient: - def __init__(self, conf: Config): - self._conf = conf - - def __getattr__(self, method): - async def f(*args, **kwargs): - async with aiohttp.ClientSession() as session: - message = {'method': method, 'params': [args, kwargs]} - async with session.get(self._conf.api_connection_url, json=message) as resp: - data = await resp.json() - if 'result' in data: - return data['result'] - elif 'error' in data: - raise JSONRPCException(data['error']) - return f +async def daemon_rpc(conf: Config, method: str, *args, **kwargs): + async with aiohttp.ClientSession() as session: + message = {'method': method, 'params': [args, kwargs]} + async with session.get(conf.api_connection_url, json=message) as resp: + data = await resp.json() + if 'result' in data: + return data['result'] + elif 'error' in data: + raise JSONRPCException(data['error']) diff --git a/scripts/dht_monitor.py b/scripts/dht_monitor.py index ad5268b53..944f21dfe 100644 --- a/scripts/dht_monitor.py +++ b/scripts/dht_monitor.py @@ -2,7 +2,7 @@ import curses import time import asyncio from lbrynet.conf import Config -from lbrynet.extras.daemon.client import LBRYAPIClient +from lbrynet.extras.daemon.client import daemon_rpc stdscr = curses.initscr() @@ -47,13 +47,12 @@ def refresh(routing_table_info): async def main(): - api = LBRYAPIClient(Config()) - + conf = Config() try: init_curses() c = None while c not in [ord('q'), ord('Q')]: - routing_info = await api.routing_table_get() + routing_info = await daemon_rpc(conf, 'routing_table_get') refresh(routing_info) c = stdscr.getch() time.sleep(0.1) diff --git a/scripts/time_to_first_byte.py b/scripts/time_to_first_byte.py index 8c8c5d44e..77b49ad41 100644 --- a/scripts/time_to_first_byte.py +++ b/scripts/time_to_first_byte.py @@ -9,7 +9,7 @@ from aiohttp import ClientConnectorError from lbrynet import __version__ from lbrynet.conf import Config from lbrynet.schema.uri import parse_lbry_uri -from lbrynet.extras.daemon.client import LBRYAPIClient +from lbrynet.extras.daemon.client import daemon_rpc from lbrynet.extras import system_info, cli @@ -80,10 +80,10 @@ async def wait_for_done(api, uri): async def main(start_daemon=True, uris=None): if not uris: uris = await get_frontpage_uris() - api = LBRYAPIClient(Config()) + conf = Config() daemon = None try: - await api.status() + await daemon_rpc(conf, 'status') except (ClientConnectorError, ConnectionError): print("Could not connect to daemon") return 1 @@ -92,7 +92,7 @@ async def main(start_daemon=True, uris=None): resolvable = [] for name in uris: - resolved = await api.resolve(uri=name) + resolved = await daemon_rpc(conf, 'resolve', uri=name) if 'error' not in resolved.get(name, {}): resolvable.append(name) @@ -104,12 +104,12 @@ async def main(start_daemon=True, uris=None): download_failures = [] for uri in resolvable: - await api.file_delete(delete_from_download_dir=True, claim_name=parse_lbry_uri(uri).name) + await daemon_rpc(conf, 'file_delete', delete_from_download_dir=True, claim_name=parse_lbry_uri(uri).name) for i, uri in enumerate(resolvable): start = time.time() try: - await api.get(uri) + await daemon_rpc(conf, 'get', uri) first_byte = time.time() first_byte_times.append(first_byte - start) print(f"{i + 1}/{len(resolvable)} - {first_byte - start} {uri}") @@ -123,7 +123,7 @@ async def main(start_daemon=True, uris=None): except: print(f"{i + 1}/{len(uris)} - timeout in {time.time() - start} {uri}") failures.append(uri) - await api.file_delete(delete_from_download_dir=True, claim_name=parse_lbry_uri(uri).name) + await daemon_rpc(conf, 'file_delete', delete_from_download_dir=True, claim_name=parse_lbry_uri(uri).name) await asyncio.sleep(0.1) print("**********************************************")