import json import sys from typing import List, Tuple, Dict import click import requests from ..operation_strings import descriptions as op_desc class Abort(click.ClickException): """Abort silently.""" def __init__(self, exit_code=1): super().__init__('') self.exit_code = exit_code def show(self): pass def print_colon_kv(pairs: List[Tuple[str, str]]): """ Pretty-print a list of key-value pairs such that the key and value columns align. Example: key1: value1 key1000: value2 """ maxlen = max(len(key) for key, val in pairs) for key, val in pairs: click.echo(key + ': ', nl=False) extra_space = ' ' * (maxlen - len(key)) click.echo(extra_space, nl=False) click.echo(val) def handle_stream_response(resp: requests.Response, operations: List[str]) -> List[Dict]: """ Print output to the console while operations are being streamed from the server over HTTP. Returns the parsed JSON data streamed from the server. """ if resp.status_code != 200: click.echo('An error occurred:') click.echo(resp.text.rstrip()) raise Abort() click.echo(op_desc[operations[0]] + '... ', nl=False) idx = 0 data = [] for line in resp.iter_lines(decode_unicode=True, chunk_size=8): d = json.loads(line) data.append(d) if d['status'] == 'aborted': click.echo(click.style('ABORTED', fg='red')) click.echo('The transaction was rolled back.') click.echo('The error was: ' + d['error']) click.echo('Please check the ceod logs.') sys.exit(1) elif d['status'] == 'completed': click.echo('Transaction successfully completed.') return data operation = d['operation'] oper_failed = False err_msg = None prefix = 'failed_to_' if operation.startswith(prefix): operation = operation[len(prefix):] oper_failed = True # sometimes the operation looks like # "failed_to_do_something: error message" if ':' in operation: operation, err_msg = operation.split(': ', 1) while idx < len(operations) and operations[idx] != operation: click.echo('Skipped') idx += 1 if idx == len(operations): break click.echo(op_desc[operations[idx]] + '... ', nl=False) if idx == len(operations): click.echo('Unrecognized operation: ' + operation) continue if oper_failed: click.echo(click.style('Failed', fg='red')) if err_msg is not None: click.echo(' Error message: ' + err_msg) else: click.echo(click.style('Done', fg='green')) idx += 1 if idx < len(operations): click.echo(op_desc[operations[idx]] + '... ', nl=False) raise Exception('server response ended abruptly') def handle_sync_response(resp: requests.Response): """ Exit the program if the request was not successful. Returns the parsed JSON response. """ if resp.status_code != 200: click.echo('An error occurred:') click.echo(resp.text.rstrip()) raise Abort() return resp.json()