import logging import time from collections import deque from typing import List, Union, Dict, Optional, Mapping, Tuple from zeno.common.motor import Motor from zeno.common.request_types import Request, Reply, OP_FIELD_NAME, f from zeno.common.startable import Status from zeno.common.txn import REPLY from zeno.common.util import getMaxFailures, getlogger from raet.raeting import AutoMode from zeno.client.signer import Signer, SimpleSigner from zeno.common.stacked import NodeStacked, HA logger = getlogger() class Client(NodeStacked, Motor): def __init__(self, clientId: str, nodeReg: Dict[str, HA]=None, ha: Union[HA, Tuple[str, int]]=None, lastReqId: int = 0, signer: Signer=None, basedirpath: str=None): """ Creates a new client. :param clientId: unique identifier for the client
def __init__(self, looper, tmpdir, nodeReg, cliNodeReg): self.curClientPort = None logging.root.addHandler(CliHandler(self.out)) self.looper = looper self.tmpdir = tmpdir self.nodeReg = nodeReg self.cliNodeReg = cliNodeReg # Used to store created clients self.clients = {} # clientId -> Client # To store the created requests self.requests = {} # To store the nodes created self.nodes = {} self.cliCmds = {'new', 'status', 'list'} self.nodeCmds = {'new', 'status', 'list', 'keyshare'} self.helpablesCommands = self.cliCmds | self.nodeCmds self.simpleCmds = {'status', 'help', 'exit', 'quit', 'license'} self.commands = {'list'} | self.simpleCmds self.cliActions = {'send', 'show'} self.commands.update(self.cliCmds) self.commands.update(self.nodeCmds) self.node_or_cli = ['node', 'client'] self.nodeNames = list(self.nodeReg.keys()) + ["all"] ''' examples: status new node Alpha new node all new client Joe client Joe send <msg> client Joe show 1 ''' def re(seq): return '(' + '|'.join(seq) + ')' grams = [ "(\s* (?P<simple>{}) \s*) |".format(re(self.simpleCmds)), "(\s* (?P<command>{}) \s*) |".format(re(self.commands)), "(\s* (?P<client_command>{}) \s+ (?P<node_or_cli>clients?) \s+ (?P<client_name>[a-zA-Z0-9]+) \s*) |".format(re(self.cliCmds)), "(\s* (?P<node_command>{}) \s+ (?P<node_or_cli>nodes?) \s+ (?P<node_name>[a-zA-Z0-9]+) \s*) |".format(re(self.nodeCmds)), "(\s* (?P<client>client) \s+ (?P<client_name>[a-zA-Z0-9]+) \s+ (?P<cli_action>send) \s+ (?P<msg>\{\s*\".*\}) \s*) |", "(\s* (?P<client>client) \s+ (?P<client_name>[a-zA-Z0-9]+) \s+ (?P<cli_action>show) \s+ (?P<req_id>[0-9]+) \s*) " # "(\s* (?P<command>help) \s+ (?P<helpable>[a-zA-Z0-9]+) \s*) |", # "(\s* (?P<command>[a-z]+) \s+ (?P<arg1>[a-zA-Z0-9]+) \s*) |", # "(\s* (?P<command>[a-z]+) \s+ (?P<arg1>client) \s+ (?P<arg2>[a-zA-Z0-9]+) \s*) |", # "(\s* (?P<command>[a-z]+) \s+ (?P<arg1>[a-zA-Z0-9]+) \s+ (?P<arg2>\{\s*\".*\}) \s*) |", # "(\s* (?P<client_name>[a-z]+) \s+ (?P<cli_action>[a-zA-Z0-9]+) \s+ (?P<msg>\{\s*\".*\}) \s*) " ] self.grammar = compile("".join(grams)) lexer = GrammarLexer(self.grammar, lexers={ 'node_command': SimpleLexer(Token.Keyword), 'command': SimpleLexer(Token.Keyword), 'node_or_cli': SimpleLexer(Token.Keyword), 'arg2': SimpleLexer(Token.Name), 'node_name': SimpleLexer(Token.Name), 'simple': SimpleLexer(Token.Keyword), 'client_command': SimpleLexer(Token.Keyword), }) self.clientWC = WordCompleter([]) completer = GrammarCompleter(self.grammar, { 'node_command': WordCompleter(self.nodeCmds), 'client_command': WordCompleter(self.cliCmds), 'client': WordCompleter(['client']), 'command': WordCompleter(self.commands), 'node_or_cli': WordCompleter(self.node_or_cli), 'node_name': WordCompleter(self.nodeNames), 'helpable': WordCompleter(self.helpablesCommands), 'client_name': self.clientWC, 'cli_action': WordCompleter(self.cliActions), 'simple': WordCompleter(self.simpleCmds) }) self.style = PygmentsStyle.from_defaults({ Token.Operator: '#33aa33 bold', Token.Number: '#aa3333 bold', Token.Name: '#ffff00 bold', Token.Heading: 'bold', Token.TrailingInput: 'bg:#662222 #ffffff', Token.BoldGreen: '#33aa33 bold', Token.BoldOrange: '#ff4f2f bold', Token.BoldBlue: '#095cab bold'}) self.functionMappings = self.createFunctionMappings() # Create an asyncio `EventLoop` object. This is a wrapper around the # asyncio loop that can be passed into prompt_toolkit. eventloop = create_asyncio_eventloop(looper.loop) pers_hist = FileHistory('.zeno-cli-history') # Create interface. app = create_prompt_application('zeno> ', lexer=lexer, completer=completer, style=self.style, history=pers_hist) self.cli = CommandLineInterface( application=app, eventloop=eventloop, output=CustomOutput.from_pty(sys.__stdout__, true_color=True)) # Patch stdout in something that will always print *above* the prompt # when something is written to stdout. sys.stdout = self.cli.stdout_proxy() setupLogging(TRACE_LOG_LEVEL, Console.Wordage.mute, filename="log/cli.log") self.logger = getlogger("cli") print("\nzeno-CLI (c) 2016 Evernym, Inc.") print("Node registry loaded.") print("None of these are created or running yet.") self.showNodeRegistry() print("Type 'help' for more information.")