<commit_before>import json
import sys

from cmd import Cmd

from reflectrpc import RpcClient
from reflectrpc import RpcError
import reflectrpc

def print_types(types):
    for t in types:
        if t['type'] == 'enum':
            print('enum: %s' % (t['name']))
            print('Description: %s' % (t['description']))
            for value in t['values']:
                print('    [%d] %s - %s' % (value['intvalue'], value['name'], value['description']))
        elif t['type'] == 'hash':
            print('hash: %s' % (t['name']))
            print('Description: %s' % (t['description']))
            for field in t['fields']:
                print('    [%s] %s - %s' % (field['type'], field['name'], field['description']))
        else:
            print('Unknown class of custom type: %s' % (t['type']))

def print_functions(functions):
    for func_desc in functions:
        paramlist = [param['name'] for param in func_desc['params']]
        paramlist = ', '.join(paramlist)

        print("%s(%s) - %s" % (func_desc['name'], paramlist, func_desc['description']))
        for param in func_desc['params']:
            print("    [%s] %s - %s" % (param['type'], param['name'], param['description']))
        print("    Result: %s - %s" % (func_desc['result_type'], func_desc['result_desc']))

def split_exec_line(line):
    tokens = []
    inquotes = False
    curtoken = ''
    intoken = False
    instring = False
    lastc = ''
    arraylevel = 0
    hashlevel = 0

    for c in line:
        if c.isspace():
            if not intoken:
                lastc = c
                continue

            # end of token?
            if not arraylevel and not hashlevel and not instring:
                tokens.append(curtoken.strip())
                curtoken = ''
                intoken = False
        else:
            intoken = True

        if intoken:
            curtoken += c

        if c == '"':
            if lastc != '\\':
                instring = not instring
        elif c == '[':
            if not instring:
                arraylevel += 1
        elif c == ']':
            if not instring:
                arraylevel -= 1
        elif c == '{':
            if not instring:
                hashlevel += 1
        elif c == '}':
            if not instring:
                hashlevel -= 1

        lastc = c

    if len(curtoken.strip()):
        tokens.append(curtoken.strip())

    # type casting
    itertokens = iter(tokens)
    next(itertokens) # skip first token which is the method name
    for i, t in enumerate(itertokens):
        i += 1
        try:
            tokens[i] = json.loads(t)
        except ValueError as e:
            print("Invalid JSON in parameter %i:" % (i))
            print("'%s'" % (t))
            return None

    return tokens

class ReflectRpcShell(Cmd):
    def __init__(self, host, port):
        super().__init__()

        self.client = RpcClient(host, port)

        try:
            self.service_description = self.client.rpc_call('__describe_service')
        except RpcError:
            self.service_description = ''

        try:
            self.functions = self.client.rpc_call('__describe_functions')
        except RpcError:
            self.functions = []

        try:
            self.custom_types = self.client.rpc_call('__describe_custom_types')
        except:
            self.custom_types = []

        self.prompt = '(rpc) '
        self.intro = "ReflectRPC Shell\n================\n\nType 'help' for available commands\n\nRPC server: %s:%i" % (host, port)

        if self.service_description:
            self.intro += "\n\nSelf-description of Service:\n============================\n" + self.service_description

        self.host = host
        self.port = port

    def do_help(self, line):
        if not line:
            print("list - List all RPC functions advertised by the server")
            print("doc  - Shows the documentation of a RPC function")
            print("type - Shows the documentation of a custom RPC type")
            print("exec - Execute RPC call")
            print("raw  - Directly send a raw JSON-RPC message to the server")
            print("quit - Quit this program")
            print("help - Print this message. 'help [command]' prints a\n       detailed help message for a command")
            return

        if line == 'exec':
            print("Examples:")
            print("    exec echo \"Hello RPC server\"")
            print("    exec add 4 8")
        elif line == 'raw':
            pass<commit_msg>Handles connection refuesed error on shell startup<commit_after>import json
import sys

from cmd import Cmd

from reflectrpc import RpcClient
from reflectrpc import RpcError
import reflectrpc

def print_types(types):
    for t in types:
        if t['type'] == 'enum':
            print('enum: %s' % (t['name']))
            print('Description: %s' % (t['description']))
            for value in t['values']:
                print('    [%d] %s - %s' % (value['intvalue'], value['name'], value['description']))
        elif t['type'] == 'hash':
            print('hash: %s' % (t['name']))
            print('Description: %s' % (t['description']))
            for field in t['fields']:
                print('    [%s] %s - %s' % (field['type'], field['name'], field['description']))
        else:
            print('Unknown class of custom type: %s' % (t['type']))

def print_functions(functions):
    for func_desc in functions:
        paramlist = [param['name'] for param in func_desc['params']]
        paramlist = ', '.join(paramlist)

        print("%s(%s) - %s" % (func_desc['name'], paramlist, func_desc['description']))
        for param in func_desc['params']:
            print("    [%s] %s - %s" % (param['type'], param['name'], param['description']))
        print("    Result: %s - %s" % (func_desc['result_type'], func_desc['result_desc']))

def split_exec_line(line):
    tokens = []
    inquotes = False
    curtoken = ''
    intoken = False
    instring = False
    lastc = ''
    arraylevel = 0
    hashlevel = 0

    for c in line:
        if c.isspace():
            if not intoken:
                lastc = c
                continue

            # end of token?
            if not arraylevel and not hashlevel and not instring:
                tokens.append(curtoken.strip())
                curtoken = ''
                intoken = False
        else:
            intoken = True

        if intoken:
            curtoken += c

        if c == '"':
            if lastc != '\\':
                instring = not instring
        elif c == '[':
            if not instring:
                arraylevel += 1
        elif c == ']':
            if not instring:
                arraylevel -= 1
        elif c == '{':
            if not instring:
                hashlevel += 1
        elif c == '}':
            if not instring:
                hashlevel -= 1

        lastc = c

    if len(curtoken.strip()):
        tokens.append(curtoken.strip())

    # type casting
    itertokens = iter(tokens)
    next(itertokens) # skip first token which is the method name
    for i, t in enumerate(itertokens):
        i += 1
        try:
            tokens[i] = json.loads(t)
        except ValueError as e:
            print("Invalid JSON in parameter %i:" % (i))
            print("'%s'" % (t))
            return None

    return tokens

class ReflectRpcShell(Cmd):
    def __init__(self, host, port):
        super().__init__()

        self.client = RpcClient(host, port)

        try:
            self.retrieve_service_description()
            self.retrieve_functions()
            self.retrieve_custom_types()
        except ConnectionRefusedError:
            self.connection_refused_error(True)

        self.prompt = '(rpc) '
        self.intro = "ReflectRPC Shell\n================\n\nType 'help' for available commands\n\nRPC server: %s:%i" % (host, port)

        if self.service_description:
            self.intro += "\n\nSelf-description of Service:\n============================\n" + self.service_description

        self.host = host
        self.port = port

    def retrieve_service_description(self):
        self.service_description = ''
        try:
            self.service_description = self.client.rpc_call('__describe_service')
        except RpcError:
            pass

    def retrieve_functions(self):
        self.functions = []
        try:
            self.functions = self.client.rpc_call('__describe_functions')
        except RpcError:
            pass

    def retrieve_custom_types(self):
        self.custom_types = []
        try:
            self.custom_types = self.client.rpc_call('__describe_custom_types')
        except RpcError:
            pass

    def connection_refused_error(self, exit=False):
        print("Failed to connect to %s on TCP port %d" % (self.client.host, self.client.port))
        if exit:
            sys.exit(1)

    def do_help(self, line):
        if not line:
            print("list - List all RPC functions advertised by the server")
            print("doc  - Shows the documentation of a RPC function")
            print("type - Shows the documentation of a custom RPC type")
            print("exec - Execute RPC call")
            print("raw  - Directly send a raw JSON-RPC message to the server")
            print("quit - Quit this program")
            print("help - Print this message. 'help [command]' prints a\n       detailed help message for a command")
            return

        if line == 'exec':
            print("Examples:")
            print("    exec echo \"Hello RPC server\"")
            print("    exec add 4 8")
        elif line == 'raw':
            pass
{'fraction_non_alphanumeric': 0.1322484292924091, 'fraction_numerical': 0.0019569471624266144, 'mean_word_length': 1.823495202093632, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1505771', 'n_tokens_mistral': 2778, 'n_tokens_neox': 2677, 'n_words': 783}