feat: simplify node selection, enhance gRPC execution logic, and improve CLI aggregate summaries

This commit is contained in:
2026-04-30 14:18:41 -03:00
parent 96049b4028
commit 7967c413c9
71 changed files with 1762 additions and 524 deletions
+2 -7
View File
@@ -153,9 +153,7 @@ tasks:
nodes: #List of nodes to work on. Mandatory nodes: #List of nodes to work on. Mandatory
- 'router1@office' #You can add specific nodes - 'router1@office' #You can add specific nodes
- '@aws' #entire folders or subfolders - '@aws' #entire folders or subfolders
- '@office': #or filter inside a folder or subfolder - 'router.*@office' #or use regex to filter inside a folder
- 'router2'
- 'router7'
commands: #List of commands to send, use {name} to pass variables commands: #List of commands to send, use {name} to pass variables
- 'term len 0' - 'term len 0'
@@ -181,7 +179,7 @@ tasks:
vrouterN@aws: vrouterN@aws:
id: 5 id: 5
output: /home/user/logs #Type of output, if null you only get Connection and test result. Choices are: null,stdout,/path/to/folder. Folder path only works on 'run' action. output: /home/user/logs #Type of output, if null you only get Connection and test result. Choices are: null,stdout,/path/to/folder. Folder path works on both 'run' and 'test' actions.
options: options:
prompt: r'>$|#$|\$$|>.$|#.$|\$.$' #Optional prompt to check on your devices, default should work on most devices. prompt: r'>$|#$|\$$|>.$|#.$|\$.$' #Optional prompt to check on your devices, default should work on most devices.
@@ -193,9 +191,6 @@ tasks:
nodes: nodes:
- 'router1@office' - 'router1@office'
- '@aws' - '@aws'
- '@office':
- 'router2'
- 'router7'
commands: commands:
- 'ping 10.100.100.{id}' - 'ping 10.100.100.{id}'
expected: '!' #Expected text to find when running test action. Mandatory for 'test' expected: '!' #Expected text to find when running test action. Mandatory for 'test'
+78 -31
View File
@@ -1,6 +1,7 @@
import os import os
import sys import sys
import yaml import yaml
import threading
from rich.rule import Rule from rich.rule import Rule
from .. import printer from .. import printer
from ..services.exceptions import ConnpyError from ..services.exceptions import ConnpyError
@@ -9,6 +10,7 @@ from .help_text import get_instructions
class RunHandler: class RunHandler:
def __init__(self, app): def __init__(self, app):
self.app = app self.app = app
self.print_lock = threading.Lock()
def dispatch(self, args): def dispatch(self, args):
if len(args.data) > 1: if len(args.data) > 1:
@@ -19,22 +21,43 @@ class RunHandler:
def node_run(self, args): def node_run(self, args):
nodes_filter = args.data[0] nodes_filter = args.data[0]
commands = [" ".join(args.data[1:])] commands = [" ".join(args.data[1:])]
try: try:
header_printed = False header_printed = False
# Inline execution with streaming results
def _on_node_complete(unique, node_output, node_status): if hasattr(args, 'test_expected') and args.test_expected:
nonlocal header_printed # Mode: Test
if not header_printed: def _on_node_complete(unique, node_output, node_status, node_result):
printer.console.print(Rule("OUTPUT", style="header")) nonlocal header_printed
header_printed = True with self.print_lock:
printer.node_panel(unique, node_output, node_status) if not header_printed:
printer.console.print(Rule("OUTPUT", style="header"))
self.app.services.execution.run_commands( header_printed = True
nodes_filter=nodes_filter, printer.test_panel(unique, node_output, node_status, node_result)
commands=commands,
on_node_complete=_on_node_complete results = self.app.services.execution.test_commands(
) nodes_filter=nodes_filter,
commands=commands,
expected=args.test_expected,
on_node_complete=_on_node_complete
)
printer.test_summary(results)
else:
# Mode: Normal Run
def _on_node_complete(unique, node_output, node_status):
nonlocal header_printed
with self.print_lock:
if not header_printed:
printer.console.print(Rule("OUTPUT", style="header"))
header_printed = True
printer.node_panel(unique, node_output, node_status)
results = self.app.services.execution.run_commands(
nodes_filter=nodes_filter,
commands=commands,
on_node_complete=_on_node_complete
)
printer.run_summary(results)
except ConnpyError as e: except ConnpyError as e:
printer.error(str(e)) printer.error(str(e))
@@ -55,36 +78,44 @@ class RunHandler:
try: try:
with open(path, "r") as f: with open(path, "r") as f:
playbook = yaml.load(f, Loader=yaml.FullLoader) playbook = yaml.load(f, Loader=yaml.FullLoader)
for task in playbook.get("tasks", []): for task in playbook.get("tasks", []):
self.cli_run(task) self.cli_run(task)
except Exception as e: except Exception as e:
printer.error(f"Failed to run playbook {path}: {e}") printer.error(f"Failed to run playbook {path}: {e}")
sys.exit(10) sys.exit(10)
def cli_run(self, script): def cli_run(self, script):
name = script.get("name", "Task")
try: try:
action = script["action"] action = script["action"]
nodelist = script["nodes"] nodelist = script["nodes"]
commands = script["commands"] commands = script["commands"]
variables = script.get("variables") variables = script.get("variables")
output_cfg = script["output"] output_cfg = script["output"]
name = script.get("name", "Task")
options = script.get("options", {}) options = script.get("options", {})
except KeyError as e: except KeyError as e:
printer.error(f"'{e.args[0]}' is mandatory in script") printer.error(f"[{name}] '{e.args[0]}' is mandatory in script")
sys.exit(11) sys.exit(11)
stdout = (output_cfg == "stdout") stdout = (output_cfg == "stdout")
folder = output_cfg if output_cfg not in [None, "stdout"] else None folder = output_cfg if output_cfg not in [None, "stdout"] else None
prompt = options.get("prompt") prompt = options.get("prompt")
printer.header(name.upper())
try: try:
header_printed = False
if action == "run": if action == "run":
# If stdout is true, we stream results as they arrive # If stdout is true, we stream results as they arrive
on_complete = printer.node_panel if stdout else None def _on_run_complete(unique, node_output, node_status):
nonlocal header_printed
if stdout:
with self.print_lock:
if not header_printed:
printer.console.print(Rule(name.upper(), style="header"))
header_printed = True
printer.node_panel(unique, node_output, node_status)
results = self.app.services.execution.run_commands( results = self.app.services.execution.run_commands(
nodes_filter=nodelist, nodes_filter=nodelist,
commands=commands, commands=commands,
@@ -93,16 +124,31 @@ class RunHandler:
timeout=options.get("timeout", 10), timeout=options.get("timeout", 10),
folder=folder, folder=folder,
prompt=prompt, prompt=prompt,
on_node_complete=on_complete on_node_complete=_on_run_complete
) )
# If not streaming, we could print a summary table here if needed # Final Summary
if not stdout: if not stdout and not folder:
for unique, output in results.items(): with self.print_lock:
printer.console.print(Rule(name.upper(), style="header"))
for unique, data in results.items():
output = data["output"] if isinstance(data, dict) else data
printer.node_panel(unique, output, 0) printer.node_panel(unique, output, 0)
# ALWAYS show the aggregate execution summary at the end
printer.run_summary(results)
elif action == "test": elif action == "test":
expected = script.get("expected", []) expected = script.get("expected", [])
on_complete = printer.test_panel if stdout else None # Show test_panel per node ONLY if stdout is True
def _on_test_complete(unique, node_output, node_status, node_result):
nonlocal header_printed
if stdout:
with self.print_lock:
if not header_printed:
printer.console.print(Rule(name.upper(), style="header"))
header_printed = True
printer.test_panel(unique, node_output, node_status, node_result)
results = self.app.services.execution.test_commands( results = self.app.services.execution.test_commands(
nodes_filter=nodelist, nodes_filter=nodelist,
commands=commands, commands=commands,
@@ -110,11 +156,12 @@ class RunHandler:
variables=variables, variables=variables,
parallel=options.get("parallel", 10), parallel=options.get("parallel", 10),
timeout=options.get("timeout", 10), timeout=options.get("timeout", 10),
folder=folder,
prompt=prompt, prompt=prompt,
on_node_complete=on_complete on_node_complete=_on_test_complete
) )
if not stdout: # ALWAYS show the aggregate summary at the end
printer.test_summary(results) printer.test_summary(results)
except ConnpyError as e: except ConnpyError as e:
printer.error(str(e)) printer.error(str(e))
+19 -4
View File
@@ -147,12 +147,27 @@ def _build_tree(nodes, folders, profiles, plugins, configdir):
"__extra__": lambda w: get_cwd(w, "import") "__extra__": lambda w: get_cwd(w, "import")
}) })
run_dict = {"--generate": None, "--help": None, "-g": None, "-h": None} # --- Run Loop ---
run_dict.update({ # After the first positional argument (Node filter or YAML file),
"*": run_dict, # we stop suggesting nodes and only allow flags or commands.
"__extra__": lambda w: get_cwd(w, "run") + list(nodes) run_after_node = {"--help": None, "-h": None}
run_after_node.update({
"--test": {"*": run_after_node},
"-t": {"*": run_after_node},
"*": run_after_node # Consume commands
}) })
run_dict = {
"--generate": {"__extra__": lambda w: get_cwd(w, "--generate")},
"-g": {"__extra__": lambda w: get_cwd(w, "-g")},
"--test": {"*": None},
"-t": {"*": None},
"--help": None,
"-h": None,
"__extra__": lambda w: get_cwd(w, "run") + list(nodes),
"*": run_after_node
}
# State Machine Definitions # State Machine Definitions
ai_dict = {"__exclude_used__": True, "--help": None, "-h": None} ai_dict = {"__exclude_used__": True, "--help": None, "-h": None}
for opt in ["--engineer-model", "--engineer-api-key", "--architect-model", "--architect-api-key"]: for opt in ["--engineer-model", "--engineer-api-key", "--architect-model", "--architect-api-key"]:
+16 -17
View File
@@ -400,15 +400,7 @@ class configfile:
if isinstance(uniques, str): if isinstance(uniques, str):
uniques = [uniques] uniques = [uniques]
for i in uniques: for i in uniques:
if isinstance(i, dict): if i.startswith("@"):
name = list(i.keys())[0]
mylist = i[name]
if not self.config["case"]:
name = name.lower()
mylist = [item.lower() for item in mylist]
this = self.getitem(name, mylist, extract = extract)
nodes.update(this)
elif i.startswith("@"):
if not self.config["case"]: if not self.config["case"]:
i = i.lower() i = i.lower()
this = self.getitem(i, extract = extract) this = self.getitem(i, extract = extract)
@@ -487,13 +479,17 @@ class configfile:
layer3 = [k + "@" + s + "@" + f for k,v in self.connections[f][s].items() if isinstance(v, dict) and v.get("type") == "connection"] layer3 = [k + "@" + s + "@" + f for k,v in self.connections[f][s].items() if isinstance(v, dict) and v.get("type") == "connection"]
nodes.extend(layer3) nodes.extend(layer3)
if filter: if filter:
flat_filter = []
if isinstance(filter, str): if isinstance(filter, str):
nodes = [item for item in nodes if re.search(filter, item)] flat_filter = [filter]
elif isinstance(filter, list): elif isinstance(filter, list):
nodes = [item for item in nodes if any(re.search(pattern, item) for pattern in filter)] for item in filter:
if isinstance(item, str):
flat_filter.append(item)
else: else:
printer.error("Invalid filter: must be a string or a list of strings.") printer.error("Filter must be a string or a list of strings")
sys.exit(1) sys.exit(1)
nodes = [item for item in nodes if any(re.search(pattern, item) for pattern in flat_filter)]
return nodes return nodes
@MethodHook @MethodHook
@@ -511,15 +507,18 @@ class configfile:
layer3 = {k + "@" + s + "@" + f:v for k,v in self.connections[f][s].items() if isinstance(v, dict) and v.get("type") == "connection"} layer3 = {k + "@" + s + "@" + f:v for k,v in self.connections[f][s].items() if isinstance(v, dict) and v.get("type") == "connection"}
nodes.update(layer3) nodes.update(layer3)
if filter: if filter:
flat_filter = []
if isinstance(filter, str): if isinstance(filter, str):
filter = "^(?!.*@).+$" if filter == "@" else filter flat_filter = [filter]
nodes = {k: v for k, v in nodes.items() if re.search(filter, k)}
elif isinstance(filter, list): elif isinstance(filter, list):
filter = ["^(?!.*@).+$" if item == "@" else item for item in filter] for item in filter:
nodes = {k: v for k, v in nodes.items() if any(re.search(pattern, k) for pattern in filter)} if isinstance(item, str):
flat_filter.append(item)
else: else:
printer.error("Invalid filter: must be a string or a list of strings.") printer.error("Filter must be a string or a list of strings")
sys.exit(1) sys.exit(1)
flat_filter = ["^(?!.*@).+$" if item == "@" else item for item in flat_filter]
nodes = {k: v for k, v in nodes.items() if any(re.search(pattern, k) for pattern in flat_filter)}
if extract: if extract:
for node, keys in nodes.items(): for node, keys in nodes.items():
for key, value in keys.items(): for key, value in keys.items():
+1
View File
@@ -289,6 +289,7 @@ class connapp:
runparser = subparsers.add_parser("run", help="Run scripts or commands on nodes", description="Run scripts or commands on nodes", formatter_class=RichHelpFormatter) runparser = subparsers.add_parser("run", help="Run scripts or commands on nodes", description="Run scripts or commands on nodes", formatter_class=RichHelpFormatter)
runparser.error = self._custom_error runparser.error = self._custom_error
runparser.add_argument("run", nargs='+', action=self._store_type, help=get_help("run"), default="run").completer = nodes_completer runparser.add_argument("run", nargs='+', action=self._store_type, help=get_help("run"), default="run").completer = nodes_completer
runparser.add_argument("-t", "--test", dest="test_expected", nargs='+', help="Expected text(s) to validate in output. Converts the action from 'run' to 'test'")
runparser.add_argument("-g","--generate", dest="action", action="store_const", help="Generate yaml file template", const="generate", default="run") runparser.add_argument("-g","--generate", dest="action", action="store_const", help="Generate yaml file template", const="generate", default="run")
runparser.set_defaults(func=self._run.dispatch) runparser.set_defaults(func=self._run.dispatch)
#APIPARSER #APIPARSER
+50 -8
View File
@@ -148,6 +148,10 @@ class node:
self.jumphost = f"-o ProxyCommand=\"{jumphost_cmd}\"" self.jumphost = f"-o ProxyCommand=\"{jumphost_cmd}\""
else: else:
self.jumphost = "" self.jumphost = ""
self.output = ""
self.status = 1
self.result = {}
@MethodHook @MethodHook
def _passtx(self, passwords, *, keyfile=None): def _passtx(self, passwords, *, keyfile=None):
@@ -548,7 +552,12 @@ class node:
self.child.logfile_read = self.mylog self.child.logfile_read = self.mylog
for c in commands: for c in commands:
if vars is not None: if vars is not None:
c = c.format(**vars) try:
c = c.format(**vars)
except KeyError as e:
self.output = f"Error: Variable {e} not defined in task or inventory"
self.status = 1
return self.output
result = self.child.expect(expects, timeout = timeout) result = self.child.expect(expects, timeout = timeout)
self.child.sendline(c) self.child.sendline(c)
if result == 2: if result == 2:
@@ -582,7 +591,7 @@ class node:
return connect return connect
@MethodHook @MethodHook
def test(self, commands, expected, vars = None,*, prompt = r'>$|#$|\$$|>.$|#.$|\$.$', timeout = 10, logger = None): def test(self, commands, expected, vars = None,*, folder = '', prompt = r'>$|#$|\$$|>.$|#.$|\$.$', timeout = 10, logger = None):
''' '''
Run a command or list of commands on the node, then check if expected value appears on the output after the last command. Run a command or list of commands on the node, then check if expected value appears on the output after the last command.
@@ -608,6 +617,9 @@ class node:
### Optional Named Parameters: ### Optional Named Parameters:
- folder (str): Path where output log should be stored, leave
empty to not store logs.
- prompt (str): Prompt to be expected after a command is finished - prompt (str): Prompt to be expected after a command is finished
running. Usually linux uses ">" or EOF while running. Usually linux uses ">" or EOF while
routers use ">" or "#". The default value should routers use ">" or "#". The default value should
@@ -622,6 +634,7 @@ class node:
false if prompt is found before. false if prompt is found before.
''' '''
now = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
connect = self._connect(timeout = timeout, logger = logger) connect = self._connect(timeout = timeout, logger = logger)
if connect == True: if connect == True:
if logger: if logger:
@@ -639,6 +652,7 @@ class node:
if "prompt" in self.tags: if "prompt" in self.tags:
prompt = self.tags["prompt"] prompt = self.tags["prompt"]
expects = [prompt, pexpect.EOF, pexpect.TIMEOUT] expects = [prompt, pexpect.EOF, pexpect.TIMEOUT]
output = '' output = ''
if not isinstance(commands, list): if not isinstance(commands, list):
commands = [commands] commands = [commands]
@@ -650,7 +664,12 @@ class node:
self.child.logfile_read = self.mylog self.child.logfile_read = self.mylog
for c in commands: for c in commands:
if vars is not None: if vars is not None:
c = c.format(**vars) try:
c = c.format(**vars)
except KeyError as e:
self.output = f"Error: Variable {e} not defined in task or inventory"
self.status = 1
return self.output
result = self.child.expect(expects, timeout = timeout) result = self.child.expect(expects, timeout = timeout)
self.child.sendline(c) self.child.sendline(c)
if result == 2: if result == 2:
@@ -659,6 +678,12 @@ class node:
result = self.child.expect(expects, timeout = timeout) result = self.child.expect(expects, timeout = timeout)
self.child.close() self.child.close()
output = self._logclean(self.mylog.getvalue().decode(), True) output = self._logclean(self.mylog.getvalue().decode(), True)
if logger:
logger("output", output)
if folder != '':
with open(folder + "/" + self.unique + "_" + now + ".txt", "w") as f:
f.write(output)
f.close()
self.output = output self.output = output
if result in [0, 1]: if result in [0, 1]:
# lastcommand = commands[-1] # lastcommand = commands[-1]
@@ -1020,8 +1045,15 @@ class nodes:
nodesargs[n.unique]["vars"] = {} nodesargs[n.unique]["vars"] = {}
if "__global__" in vars.keys(): if "__global__" in vars.keys():
nodesargs[n.unique]["vars"].update(vars["__global__"]) nodesargs[n.unique]["vars"].update(vars["__global__"])
if n.unique in vars.keys(): for var_key, var_val in vars.items():
nodesargs[n.unique]["vars"].update(vars[n.unique]) if var_key == "__global__":
continue
try:
if re.search(var_key, n.unique, re.IGNORECASE):
nodesargs[n.unique]["vars"].update(var_val)
except re.error:
if var_key == n.unique:
nodesargs[n.unique]["vars"].update(var_val)
# Pass the logger to the node # Pass the logger to the node
nodesargs[n.unique]["logger"] = logger nodesargs[n.unique]["logger"] = logger
@@ -1046,7 +1078,7 @@ class nodes:
return output return output
@MethodHook @MethodHook
def test(self, commands, expected, vars = None,*, prompt = None, parallel = 10, timeout = None, on_complete = None, logger = None): def test(self, commands, expected, vars = None,*, folder = None, prompt = None, parallel = 10, timeout = None, on_complete = None, logger = None):
''' '''
Run a command or list of commands on all the nodes in nodelist, then check if expected value appears on the output after the last command. Run a command or list of commands on all the nodes in nodelist, then check if expected value appears on the output after the last command.
@@ -1101,6 +1133,9 @@ class nodes:
nodesargs = {} nodesargs = {}
args["commands"] = commands args["commands"] = commands
args["expected"] = expected args["expected"] = expected
if folder != None:
args["folder"] = folder
Path(folder).mkdir(parents=True, exist_ok=True)
if prompt != None: if prompt != None:
args["prompt"] = prompt args["prompt"] = prompt
if timeout != None: if timeout != None:
@@ -1122,8 +1157,15 @@ class nodes:
nodesargs[n.unique]["vars"] = {} nodesargs[n.unique]["vars"] = {}
if "__global__" in vars.keys(): if "__global__" in vars.keys():
nodesargs[n.unique]["vars"].update(vars["__global__"]) nodesargs[n.unique]["vars"].update(vars["__global__"])
if n.unique in vars.keys(): for var_key, var_val in vars.items():
nodesargs[n.unique]["vars"].update(vars[n.unique]) if var_key == "__global__":
continue
try:
if re.search(var_key, n.unique, re.IGNORECASE):
nodesargs[n.unique]["vars"].update(var_val)
except re.error:
if var_key == n.unique:
nodesargs[n.unique]["vars"].update(var_val)
nodesargs[n.unique]["logger"] = logger nodesargs[n.unique]["logger"] = logger
if on_complete: if on_complete:
File diff suppressed because one or more lines are too long
+1 -2
View File
@@ -2,8 +2,7 @@
"""Client and server classes corresponding to protobuf-defined services.""" """Client and server classes corresponding to protobuf-defined services."""
import grpc import grpc
import warnings import warnings
from . import connpy_pb2 as connpy__pb2
import connpy_pb2 as connpy__pb2
from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2
GRPC_GENERATED_VERSION = '1.80.0' GRPC_GENERATED_VERSION = '1.80.0'
+17 -5
View File
@@ -388,14 +388,20 @@ class ExecutionServicer(connpy_pb2_grpc.ExecutionServiceServicer):
def _worker(): def _worker():
try: try:
# Set task name in thread state for printer if available
if request.name:
printer.console.print(f"[debug][DEBUG][/debug] Executing task: [bold cyan]{request.name}[/bold cyan]")
self.service.run_commands( self.service.run_commands(
nodes_filter=nodes_filter, nodes_filter=nodes_filter,
commands=list(request.commands), commands=list(request.commands),
folder=request.folder if request.folder else None, folder=request.folder if request.folder else None,
prompt=request.prompt if request.prompt else None, prompt=request.prompt if request.prompt else None,
parallel=request.parallel, parallel=request.parallel,
timeout=request.timeout if request.timeout > 0 else 10,
variables=from_struct(request.vars) if request.HasField("vars") else None, variables=from_struct(request.vars) if request.HasField("vars") else None,
on_node_complete=_on_complete on_node_complete=_on_complete,
name=request.name if request.name else None
) )
except Exception as e: except Exception as e:
# Optionally pass error to stream, but handle_errors decorator covers top-level. # Optionally pass error to stream, but handle_errors decorator covers top-level.
@@ -428,20 +434,26 @@ class ExecutionServicer(connpy_pb2_grpc.ExecutionServiceServicer):
q = queue.Queue() q = queue.Queue()
def _on_complete(unique, output, status, result): def _on_complete(unique, node_output, node_status, node_result):
q.put({"unique_id": unique, "output": output, "status": status, "result": result}) q.put({"unique_id": unique, "output": node_output, "status": node_status, "result": node_result})
def _worker(): def _worker():
try: try:
# Set task name in thread state for printer if available
if request.name:
printer.console.print(f"[debug][DEBUG][/debug] Executing task: [bold cyan]{request.name}[/bold cyan]")
self.service.test_commands( self.service.test_commands(
nodes_filter=nodes_filter, nodes_filter=nodes_filter,
commands=list(request.commands), commands=list(request.commands),
expected=request.expected, expected=list(request.expected),
folder=request.folder if request.folder else None, folder=request.folder if request.folder else None,
prompt=request.prompt if request.prompt else None, prompt=request.prompt if request.prompt else None,
parallel=request.parallel, parallel=request.parallel,
timeout=request.timeout if request.timeout > 0 else 10,
variables=from_struct(request.vars) if request.HasField("vars") else None, variables=from_struct(request.vars) if request.HasField("vars") else None,
on_node_complete=_on_complete on_node_complete=_on_complete,
name=request.name if request.name else None
) )
except Exception as e: except Exception as e:
q.put(e) q.put(e)
+9 -4
View File
@@ -420,9 +420,9 @@ class ExecutionStub:
folder=folder or "", folder=folder or "",
prompt=prompt or "", prompt=prompt or "",
parallel=parallel, parallel=parallel,
timeout=timeout,
name=kwargs.get("name", "")
) )
# Note: 'timeout', 'on_node_complete', and 'logger' are currently not
# sent over gRPC in the current proto definition.
if variables is not None: if variables is not None:
req.vars.CopyFrom(to_struct(variables)) req.vars.CopyFrom(to_struct(variables))
@@ -432,7 +432,10 @@ class ExecutionStub:
for response in self.stub.run_commands(req): for response in self.stub.run_commands(req):
if on_complete: if on_complete:
on_complete(response.unique_id, response.output, response.status) on_complete(response.unique_id, response.output, response.status)
final_results[response.unique_id] = response.output final_results[response.unique_id] = {
"output": response.output,
"status": response.status
}
return final_results return final_results
@@ -442,10 +445,12 @@ class ExecutionStub:
req = connpy_pb2.TestRequest( req = connpy_pb2.TestRequest(
nodes=nodes_list, nodes=nodes_list,
commands=commands, commands=commands,
expected=expected, expected=expected if isinstance(expected, list) else [expected],
folder=kwargs.get("folder", ""), folder=kwargs.get("folder", ""),
prompt=prompt or "", prompt=prompt or "",
parallel=parallel, parallel=parallel,
timeout=timeout,
name=kwargs.get("name", "")
) )
if variables is not None: if variables is not None:
req.vars.CopyFrom(to_struct(variables)) req.vars.CopyFrom(to_struct(variables))
+89 -19
View File
@@ -317,7 +317,7 @@ def test_panel(unique, output, status, result):
_get_console().print(Panel(Group(Text(), code_block, test_results), title=title_line, width=cols, border_style=border)) _get_console().print(Panel(Group(Text(), code_block, test_results), title=title_line, width=cols, border_style=border))
def test_summary(results): def test_summary(results):
"""Print an aggregate summary of multiple test results.""" """Print an aggregate summary of multiple test results in a single panel."""
from rich.panel import Panel from rich.panel import Panel
from rich.text import Text from rich.text import Text
from rich.console import Group from rich.console import Group
@@ -328,26 +328,96 @@ def test_summary(results):
except OSError: except OSError:
cols = 80 cols = 80
for node, test_result in results.items(): summary_content = Text()
status_code = 0 if test_result and all(test_result.values()) else 1 total_passed = 0
if status_code == 0: total_failed = 0
status_str = "[pass]✓ PASS[/pass]" total_partial = 0
border = "pass"
else: if not results:
status_str = f"[fail]✗ FAIL[/fail]" summary_content.append(" No test results found.\n", style="error")
border = "fail" else:
for node, test_result in results.items():
summary_content.append(f"", style="border")
summary_content.append(f"{node.ljust(40)}", style="bold")
title_line = f"[bold]{node}[/bold] — {status_str}" if test_result:
passed_count = sum(1 for v in test_result.values() if v)
test_output = Text() total_count = len(test_result)
test_output.append("TEST RESULTS:\n", style="header")
max_key_len = max(len(k) for k in test_result.keys()) if test_result else 0 if passed_count == total_count:
for k, v in (test_result.items() if test_result else []): total_passed += 1
mark = "" if v else "" node_style = "success"
style = "success" if v else "error" mark = "✓ PASS"
test_output.append(f" {k.ljust(max_key_len)} {mark}\n", style=style) elif passed_count > 0:
total_partial += 1
node_style = "warning"
mark = f"⚠ PARTIAL ({passed_count}/{total_count})"
else:
total_failed += 1
node_style = "error"
mark = "✗ FAIL"
summary_content.append(f" {mark}\n", style=node_style)
for k, v in test_result.items():
res_mark = "" if v else ""
res_style = "success" if v else "error"
summary_content.append(f" {k.ljust(38)} {res_mark}\n", style=res_style)
else:
total_failed += 1
summary_content.append(" ✗ FAIL\n", style="error")
summary_content.append(" No results (execution failed)\n", style="error")
status_parts = []
if total_passed: status_parts.append(f"[pass]{total_passed} PASSED[/pass]")
if total_partial: status_parts.append(f"[warning]{total_partial} PARTIAL[/warning]")
if total_failed: status_parts.append(f"[fail]{total_failed} FAILED[/fail]")
status_str = " | ".join(status_parts) if status_parts else "[error]NO RESULTS[/error]"
title_line = f"AGGREGATE TEST SUMMARY — {status_str}"
_get_console().print(Panel(Group(Text(), summary_content), title=title_line, width=cols, border_style="border"))
def run_summary(results):
"""Print an aggregate summary of multiple execution results in a single panel."""
from rich.panel import Panel
from rich.text import Text
from rich.console import Group
import os
try:
cols, _ = os.get_terminal_size()
except OSError:
cols = 80
summary_content = Text()
total_ok = 0
total_err = 0
if not results:
summary_content.append(" No execution results found.\n", style="error")
else:
for node, data in results.items():
summary_content.append(f"", style="border")
summary_content.append(f"{node.ljust(40)}", style="bold")
_get_console().print(Panel(Group(Text(), test_output), title=title_line, width=cols, border_style=border)) # Check if we have a status dict or just output (for backward compatibility)
status = data.get("status", 0) if isinstance(data, dict) else 0
if status == 0:
total_ok += 1
summary_content.append(f" ✓ DONE\n", style="success")
else:
total_err += 1
summary_content.append(f" ✗ FAIL({status})\n", style="error")
status_parts = []
if total_ok: status_parts.append(f"[success]{total_ok} DONE[/success]")
if total_err: status_parts.append(f"[error]{total_err} FAILED[/error]")
status_str = " | ".join(status_parts) if status_parts else "[error]NO RESULTS[/error]"
title_line = f"AGGREGATE EXECUTION SUMMARY — {status_str}"
_get_console().print(Panel(Group(Text(), summary_content), title=title_line, width=cols, border_style="border"))
def header(text): def header(text):
"""Print a section header.""" """Print a section header."""
+5 -1
View File
@@ -176,16 +176,20 @@ message RunRequest {
string prompt = 4; string prompt = 4;
int32 parallel = 5; int32 parallel = 5;
google.protobuf.Struct vars = 6; google.protobuf.Struct vars = 6;
int32 timeout = 7;
string name = 8;
} }
message TestRequest { message TestRequest {
repeated string nodes = 1; repeated string nodes = 1;
repeated string commands = 2; repeated string commands = 2;
string expected = 3; repeated string expected = 3;
string folder = 4; string folder = 4;
string prompt = 5; string prompt = 5;
int32 parallel = 6; int32 parallel = 6;
google.protobuf.Struct vars = 7; google.protobuf.Struct vars = 7;
int32 timeout = 8;
string name = 9;
} }
message ScriptRequest { message ScriptRequest {
+53 -26
View File
@@ -18,7 +18,8 @@ class ExecutionService(BaseService):
folder: Optional[str] = None, folder: Optional[str] = None,
prompt: Optional[str] = None, prompt: Optional[str] = None,
on_node_complete: Optional[Callable] = None, on_node_complete: Optional[Callable] = None,
logger: Optional[Callable] = None logger: Optional[Callable] = None,
name: Optional[str] = None
) -> Dict[str, str]: ) -> Dict[str, str]:
"""Execute commands on a set of nodes.""" """Execute commands on a set of nodes."""
@@ -42,7 +43,15 @@ class ExecutionService(BaseService):
logger=logger logger=logger
) )
return results # Combine output and status for the caller
full_results = {}
for unique in results:
full_results[unique] = {
"output": results[unique],
"status": executor.status.get(unique, 1)
}
return full_results
except Exception as e: except Exception as e:
raise ConnpyError(f"Execution failed: {e}") raise ConnpyError(f"Execution failed: {e}")
@@ -54,9 +63,11 @@ class ExecutionService(BaseService):
variables: Optional[Dict[str, Any]] = None, variables: Optional[Dict[str, Any]] = None,
parallel: int = 10, parallel: int = 10,
timeout: int = 10, timeout: int = 10,
folder: Optional[str] = None,
prompt: Optional[str] = None, prompt: Optional[str] = None,
on_node_complete: Optional[Callable] = None, on_node_complete: Optional[Callable] = None,
logger: Optional[Callable] = None logger: Optional[Callable] = None,
name: Optional[str] = None
) -> Dict[str, Dict[str, bool]]: ) -> Dict[str, Dict[str, bool]]:
"""Run commands and verify expected output on a set of nodes.""" """Run commands and verify expected output on a set of nodes."""
@@ -75,6 +86,7 @@ class ExecutionService(BaseService):
vars=variables, vars=variables,
parallel=parallel, parallel=parallel,
timeout=timeout, timeout=timeout,
folder=folder,
prompt=prompt, prompt=prompt,
on_complete=on_node_complete, on_complete=on_node_complete,
logger=logger logger=logger
@@ -96,37 +108,52 @@ class ExecutionService(BaseService):
return self.run_commands(nodes_filter, commands, parallel=parallel) return self.run_commands(nodes_filter, commands, parallel=parallel)
def run_yaml_playbook(self, playbook_path: str, parallel: int = 10) -> Dict[str, Any]: def run_yaml_playbook(self, playbook_data: str, parallel: int = 10) -> Dict[str, Any]:
"""Run a structured Connpy YAML automation playbook.""" """Run a structured Connpy YAML automation playbook (from path or content)."""
if not os.path.exists(playbook_path): playbook = None
raise ConnpyError(f"Playbook file not found: {playbook_path}") if playbook_data.startswith("---YAML---\n"):
try:
try: content = playbook_data[len("---YAML---\n"):]
with open(playbook_path, "r") as f: playbook = yaml.load(content, Loader=yaml.FullLoader)
playbook = yaml.load(f, Loader=yaml.FullLoader) except Exception as e:
except Exception as e: raise ConnpyError(f"Failed to parse YAML content: {e}")
raise ConnpyError(f"Failed to load playbook {playbook_path}: {e}") else:
if not os.path.exists(playbook_data):
raise ConnpyError(f"Playbook file not found: {playbook_data}")
try:
with open(playbook_data, "r") as f:
playbook = yaml.load(f, Loader=yaml.FullLoader)
except Exception as e:
raise ConnpyError(f"Failed to load playbook {playbook_data}: {e}")
# Basic validation # Basic validation
if not isinstance(playbook, dict) or "nodes" not in playbook or "commands" not in playbook: if not isinstance(playbook, dict) or "nodes" not in playbook or "commands" not in playbook:
raise ConnpyError("Invalid playbook format: missing 'nodes' or 'commands' keys.") raise ConnpyError("Invalid playbook format: missing 'nodes' or 'commands' keys.")
action = playbook.get("action", "run") action = playbook.get("action", "run")
options = playbook.get("options", {})
# Extract all fields similar to RunHandler.cli_run
exec_args = {
"nodes_filter": playbook["nodes"],
"commands": playbook["commands"],
"variables": playbook.get("variables"),
"parallel": options.get("parallel", parallel),
"timeout": playbook.get("timeout", options.get("timeout", 10)),
"prompt": options.get("prompt"),
"name": playbook.get("name", "Task")
}
# Map 'output' field to folder path if it's not stdout/null
output_cfg = playbook.get("output")
if output_cfg not in [None, "stdout"]:
exec_args["folder"] = output_cfg
if action == "run": if action == "run":
return self.run_commands( return self.run_commands(**exec_args)
nodes_filter=playbook["nodes"],
commands=playbook["commands"],
parallel=parallel,
timeout=playbook.get("timeout", 10)
)
elif action == "test": elif action == "test":
return self.test_commands( exec_args["expected"] = playbook.get("expected", [])
nodes_filter=playbook["nodes"], return self.test_commands(**exec_args)
commands=playbook["commands"],
expected=playbook.get("expected", []),
parallel=parallel,
timeout=playbook.get("timeout", 10)
)
else: else:
raise ConnpyError(f"Unsupported playbook action: {action}") raise ConnpyError(f"Unsupported playbook action: {action}")
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.cli.ai_handler API documentation</title> <title>connpy.cli.ai_handler API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -371,7 +371,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.cli.api_handler API documentation</title> <title>connpy.cli.api_handler API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -193,7 +193,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.cli.config_handler API documentation</title> <title>connpy.cli.config_handler API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -482,7 +482,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.cli.context_handler API documentation</title> <title>connpy.cli.context_handler API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -249,7 +249,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.cli.forms API documentation</title> <title>connpy.cli.forms API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -517,7 +517,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+4 -9
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.cli.help_text API documentation</title> <title>connpy.cli.help_text API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -215,9 +215,7 @@ tasks:
nodes: #List of nodes to work on. Mandatory nodes: #List of nodes to work on. Mandatory
- &#39;router1@office&#39; #You can add specific nodes - &#39;router1@office&#39; #You can add specific nodes
- &#39;@aws&#39; #entire folders or subfolders - &#39;@aws&#39; #entire folders or subfolders
- &#39;@office&#39;: #or filter inside a folder or subfolder - &#39;router.*@office&#39; #or use regex to filter inside a folder
- &#39;router2&#39;
- &#39;router7&#39;
commands: #List of commands to send, use {name} to pass variables commands: #List of commands to send, use {name} to pass variables
- &#39;term len 0&#39; - &#39;term len 0&#39;
@@ -243,7 +241,7 @@ tasks:
vrouterN@aws: vrouterN@aws:
id: 5 id: 5
output: /home/user/logs #Type of output, if null you only get Connection and test result. Choices are: null,stdout,/path/to/folder. Folder path only works on &#39;run&#39; action. output: /home/user/logs #Type of output, if null you only get Connection and test result. Choices are: null,stdout,/path/to/folder. Folder path works on both &#39;run&#39; and &#39;test&#39; actions.
options: options:
prompt: r&#39;&gt;$|#$|\$$|&gt;.$|#.$|\$.$&#39; #Optional prompt to check on your devices, default should work on most devices. prompt: r&#39;&gt;$|#$|\$$|&gt;.$|#.$|\$.$&#39; #Optional prompt to check on your devices, default should work on most devices.
@@ -255,9 +253,6 @@ tasks:
nodes: nodes:
- &#39;router1@office&#39; - &#39;router1@office&#39;
- &#39;@aws&#39; - &#39;@aws&#39;
- &#39;@office&#39;:
- &#39;router2&#39;
- &#39;router7&#39;
commands: commands:
- &#39;ping 10.100.100.{id}&#39; - &#39;ping 10.100.100.{id}&#39;
expected: &#39;!&#39; #Expected text to find when running test action. Mandatory for &#39;test&#39; expected: &#39;!&#39; #Expected text to find when running test action. Mandatory for &#39;test&#39;
@@ -304,7 +299,7 @@ tasks:
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.cli.helpers API documentation</title> <title>connpy.cli.helpers API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -207,7 +207,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.cli.import_export_handler API documentation</title> <title>connpy.cli.import_export_handler API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -272,7 +272,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.cli API documentation</title> <title>connpy.cli API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -137,7 +137,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.cli.node_handler API documentation</title> <title>connpy.cli.node_handler API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -606,7 +606,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.cli.plugin_handler API documentation</title> <title>connpy.cli.plugin_handler API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -385,7 +385,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.cli.profile_handler API documentation</title> <title>connpy.cli.profile_handler API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -314,7 +314,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+155 -64
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.cli.run_handler API documentation</title> <title>connpy.cli.run_handler API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -58,6 +58,7 @@ el.replaceWith(d);
<pre><code class="python">class RunHandler: <pre><code class="python">class RunHandler:
def __init__(self, app): def __init__(self, app):
self.app = app self.app = app
self.print_lock = threading.Lock()
def dispatch(self, args): def dispatch(self, args):
if len(args.data) &gt; 1: if len(args.data) &gt; 1:
@@ -68,22 +69,43 @@ el.replaceWith(d);
def node_run(self, args): def node_run(self, args):
nodes_filter = args.data[0] nodes_filter = args.data[0]
commands = [&#34; &#34;.join(args.data[1:])] commands = [&#34; &#34;.join(args.data[1:])]
try: try:
header_printed = False header_printed = False
# Inline execution with streaming results
def _on_node_complete(unique, node_output, node_status): if hasattr(args, &#39;test_expected&#39;) and args.test_expected:
nonlocal header_printed # Mode: Test
if not header_printed: def _on_node_complete(unique, node_output, node_status, node_result):
printer.console.print(Rule(&#34;OUTPUT&#34;, style=&#34;header&#34;)) nonlocal header_printed
header_printed = True with self.print_lock:
printer.node_panel(unique, node_output, node_status) if not header_printed:
printer.console.print(Rule(&#34;OUTPUT&#34;, style=&#34;header&#34;))
self.app.services.execution.run_commands( header_printed = True
nodes_filter=nodes_filter, printer.test_panel(unique, node_output, node_status, node_result)
commands=commands,
on_node_complete=_on_node_complete results = self.app.services.execution.test_commands(
) nodes_filter=nodes_filter,
commands=commands,
expected=args.test_expected,
on_node_complete=_on_node_complete
)
printer.test_summary(results)
else:
# Mode: Normal Run
def _on_node_complete(unique, node_output, node_status):
nonlocal header_printed
with self.print_lock:
if not header_printed:
printer.console.print(Rule(&#34;OUTPUT&#34;, style=&#34;header&#34;))
header_printed = True
printer.node_panel(unique, node_output, node_status)
results = self.app.services.execution.run_commands(
nodes_filter=nodes_filter,
commands=commands,
on_node_complete=_on_node_complete
)
printer.run_summary(results)
except ConnpyError as e: except ConnpyError as e:
printer.error(str(e)) printer.error(str(e))
@@ -104,36 +126,44 @@ el.replaceWith(d);
try: try:
with open(path, &#34;r&#34;) as f: with open(path, &#34;r&#34;) as f:
playbook = yaml.load(f, Loader=yaml.FullLoader) playbook = yaml.load(f, Loader=yaml.FullLoader)
for task in playbook.get(&#34;tasks&#34;, []): for task in playbook.get(&#34;tasks&#34;, []):
self.cli_run(task) self.cli_run(task)
except Exception as e: except Exception as e:
printer.error(f&#34;Failed to run playbook {path}: {e}&#34;) printer.error(f&#34;Failed to run playbook {path}: {e}&#34;)
sys.exit(10) sys.exit(10)
def cli_run(self, script): def cli_run(self, script):
name = script.get(&#34;name&#34;, &#34;Task&#34;)
try: try:
action = script[&#34;action&#34;] action = script[&#34;action&#34;]
nodelist = script[&#34;nodes&#34;] nodelist = script[&#34;nodes&#34;]
commands = script[&#34;commands&#34;] commands = script[&#34;commands&#34;]
variables = script.get(&#34;variables&#34;) variables = script.get(&#34;variables&#34;)
output_cfg = script[&#34;output&#34;] output_cfg = script[&#34;output&#34;]
name = script.get(&#34;name&#34;, &#34;Task&#34;)
options = script.get(&#34;options&#34;, {}) options = script.get(&#34;options&#34;, {})
except KeyError as e: except KeyError as e:
printer.error(f&#34;&#39;{e.args[0]}&#39; is mandatory in script&#34;) printer.error(f&#34;[{name}] &#39;{e.args[0]}&#39; is mandatory in script&#34;)
sys.exit(11) sys.exit(11)
stdout = (output_cfg == &#34;stdout&#34;) stdout = (output_cfg == &#34;stdout&#34;)
folder = output_cfg if output_cfg not in [None, &#34;stdout&#34;] else None folder = output_cfg if output_cfg not in [None, &#34;stdout&#34;] else None
prompt = options.get(&#34;prompt&#34;) prompt = options.get(&#34;prompt&#34;)
printer.header(name.upper())
try: try:
header_printed = False
if action == &#34;run&#34;: if action == &#34;run&#34;:
# If stdout is true, we stream results as they arrive # If stdout is true, we stream results as they arrive
on_complete = printer.node_panel if stdout else None def _on_run_complete(unique, node_output, node_status):
nonlocal header_printed
if stdout:
with self.print_lock:
if not header_printed:
printer.console.print(Rule(name.upper(), style=&#34;header&#34;))
header_printed = True
printer.node_panel(unique, node_output, node_status)
results = self.app.services.execution.run_commands( results = self.app.services.execution.run_commands(
nodes_filter=nodelist, nodes_filter=nodelist,
commands=commands, commands=commands,
@@ -142,16 +172,31 @@ el.replaceWith(d);
timeout=options.get(&#34;timeout&#34;, 10), timeout=options.get(&#34;timeout&#34;, 10),
folder=folder, folder=folder,
prompt=prompt, prompt=prompt,
on_node_complete=on_complete on_node_complete=_on_run_complete
) )
# If not streaming, we could print a summary table here if needed # Final Summary
if not stdout: if not stdout and not folder:
for unique, output in results.items(): with self.print_lock:
printer.console.print(Rule(name.upper(), style=&#34;header&#34;))
for unique, data in results.items():
output = data[&#34;output&#34;] if isinstance(data, dict) else data
printer.node_panel(unique, output, 0) printer.node_panel(unique, output, 0)
# ALWAYS show the aggregate execution summary at the end
printer.run_summary(results)
elif action == &#34;test&#34;: elif action == &#34;test&#34;:
expected = script.get(&#34;expected&#34;, []) expected = script.get(&#34;expected&#34;, [])
on_complete = printer.test_panel if stdout else None # Show test_panel per node ONLY if stdout is True
def _on_test_complete(unique, node_output, node_status, node_result):
nonlocal header_printed
if stdout:
with self.print_lock:
if not header_printed:
printer.console.print(Rule(name.upper(), style=&#34;header&#34;))
header_printed = True
printer.test_panel(unique, node_output, node_status, node_result)
results = self.app.services.execution.test_commands( results = self.app.services.execution.test_commands(
nodes_filter=nodelist, nodes_filter=nodelist,
commands=commands, commands=commands,
@@ -159,12 +204,13 @@ el.replaceWith(d);
variables=variables, variables=variables,
parallel=options.get(&#34;parallel&#34;, 10), parallel=options.get(&#34;parallel&#34;, 10),
timeout=options.get(&#34;timeout&#34;, 10), timeout=options.get(&#34;timeout&#34;, 10),
folder=folder,
prompt=prompt, prompt=prompt,
on_node_complete=on_complete on_node_complete=_on_test_complete
) )
if not stdout: # ALWAYS show the aggregate summary at the end
printer.test_summary(results) printer.test_summary(results)
except ConnpyError as e: except ConnpyError as e:
printer.error(str(e))</code></pre> printer.error(str(e))</code></pre>
</details> </details>
@@ -180,27 +226,35 @@ el.replaceWith(d);
<span>Expand source code</span> <span>Expand source code</span>
</summary> </summary>
<pre><code class="python">def cli_run(self, script): <pre><code class="python">def cli_run(self, script):
name = script.get(&#34;name&#34;, &#34;Task&#34;)
try: try:
action = script[&#34;action&#34;] action = script[&#34;action&#34;]
nodelist = script[&#34;nodes&#34;] nodelist = script[&#34;nodes&#34;]
commands = script[&#34;commands&#34;] commands = script[&#34;commands&#34;]
variables = script.get(&#34;variables&#34;) variables = script.get(&#34;variables&#34;)
output_cfg = script[&#34;output&#34;] output_cfg = script[&#34;output&#34;]
name = script.get(&#34;name&#34;, &#34;Task&#34;)
options = script.get(&#34;options&#34;, {}) options = script.get(&#34;options&#34;, {})
except KeyError as e: except KeyError as e:
printer.error(f&#34;&#39;{e.args[0]}&#39; is mandatory in script&#34;) printer.error(f&#34;[{name}] &#39;{e.args[0]}&#39; is mandatory in script&#34;)
sys.exit(11) sys.exit(11)
stdout = (output_cfg == &#34;stdout&#34;) stdout = (output_cfg == &#34;stdout&#34;)
folder = output_cfg if output_cfg not in [None, &#34;stdout&#34;] else None folder = output_cfg if output_cfg not in [None, &#34;stdout&#34;] else None
prompt = options.get(&#34;prompt&#34;) prompt = options.get(&#34;prompt&#34;)
printer.header(name.upper())
try: try:
header_printed = False
if action == &#34;run&#34;: if action == &#34;run&#34;:
# If stdout is true, we stream results as they arrive # If stdout is true, we stream results as they arrive
on_complete = printer.node_panel if stdout else None def _on_run_complete(unique, node_output, node_status):
nonlocal header_printed
if stdout:
with self.print_lock:
if not header_printed:
printer.console.print(Rule(name.upper(), style=&#34;header&#34;))
header_printed = True
printer.node_panel(unique, node_output, node_status)
results = self.app.services.execution.run_commands( results = self.app.services.execution.run_commands(
nodes_filter=nodelist, nodes_filter=nodelist,
commands=commands, commands=commands,
@@ -209,16 +263,31 @@ el.replaceWith(d);
timeout=options.get(&#34;timeout&#34;, 10), timeout=options.get(&#34;timeout&#34;, 10),
folder=folder, folder=folder,
prompt=prompt, prompt=prompt,
on_node_complete=on_complete on_node_complete=_on_run_complete
) )
# If not streaming, we could print a summary table here if needed # Final Summary
if not stdout: if not stdout and not folder:
for unique, output in results.items(): with self.print_lock:
printer.console.print(Rule(name.upper(), style=&#34;header&#34;))
for unique, data in results.items():
output = data[&#34;output&#34;] if isinstance(data, dict) else data
printer.node_panel(unique, output, 0) printer.node_panel(unique, output, 0)
# ALWAYS show the aggregate execution summary at the end
printer.run_summary(results)
elif action == &#34;test&#34;: elif action == &#34;test&#34;:
expected = script.get(&#34;expected&#34;, []) expected = script.get(&#34;expected&#34;, [])
on_complete = printer.test_panel if stdout else None # Show test_panel per node ONLY if stdout is True
def _on_test_complete(unique, node_output, node_status, node_result):
nonlocal header_printed
if stdout:
with self.print_lock:
if not header_printed:
printer.console.print(Rule(name.upper(), style=&#34;header&#34;))
header_printed = True
printer.test_panel(unique, node_output, node_status, node_result)
results = self.app.services.execution.test_commands( results = self.app.services.execution.test_commands(
nodes_filter=nodelist, nodes_filter=nodelist,
commands=commands, commands=commands,
@@ -226,12 +295,13 @@ el.replaceWith(d);
variables=variables, variables=variables,
parallel=options.get(&#34;parallel&#34;, 10), parallel=options.get(&#34;parallel&#34;, 10),
timeout=options.get(&#34;timeout&#34;, 10), timeout=options.get(&#34;timeout&#34;, 10),
folder=folder,
prompt=prompt, prompt=prompt,
on_node_complete=on_complete on_node_complete=_on_test_complete
) )
if not stdout: # ALWAYS show the aggregate summary at the end
printer.test_summary(results) printer.test_summary(results)
except ConnpyError as e: except ConnpyError as e:
printer.error(str(e))</code></pre> printer.error(str(e))</code></pre>
</details> </details>
@@ -264,22 +334,43 @@ el.replaceWith(d);
<pre><code class="python">def node_run(self, args): <pre><code class="python">def node_run(self, args):
nodes_filter = args.data[0] nodes_filter = args.data[0]
commands = [&#34; &#34;.join(args.data[1:])] commands = [&#34; &#34;.join(args.data[1:])]
try: try:
header_printed = False header_printed = False
# Inline execution with streaming results
def _on_node_complete(unique, node_output, node_status): if hasattr(args, &#39;test_expected&#39;) and args.test_expected:
nonlocal header_printed # Mode: Test
if not header_printed: def _on_node_complete(unique, node_output, node_status, node_result):
printer.console.print(Rule(&#34;OUTPUT&#34;, style=&#34;header&#34;)) nonlocal header_printed
header_printed = True with self.print_lock:
printer.node_panel(unique, node_output, node_status) if not header_printed:
printer.console.print(Rule(&#34;OUTPUT&#34;, style=&#34;header&#34;))
self.app.services.execution.run_commands( header_printed = True
nodes_filter=nodes_filter, printer.test_panel(unique, node_output, node_status, node_result)
commands=commands,
on_node_complete=_on_node_complete results = self.app.services.execution.test_commands(
) nodes_filter=nodes_filter,
commands=commands,
expected=args.test_expected,
on_node_complete=_on_node_complete
)
printer.test_summary(results)
else:
# Mode: Normal Run
def _on_node_complete(unique, node_output, node_status):
nonlocal header_printed
with self.print_lock:
if not header_printed:
printer.console.print(Rule(&#34;OUTPUT&#34;, style=&#34;header&#34;))
header_printed = True
printer.node_panel(unique, node_output, node_status)
results = self.app.services.execution.run_commands(
nodes_filter=nodes_filter,
commands=commands,
on_node_complete=_on_node_complete
)
printer.run_summary(results)
except ConnpyError as e: except ConnpyError as e:
printer.error(str(e)) printer.error(str(e))
@@ -320,10 +411,10 @@ el.replaceWith(d);
try: try:
with open(path, &#34;r&#34;) as f: with open(path, &#34;r&#34;) as f:
playbook = yaml.load(f, Loader=yaml.FullLoader) playbook = yaml.load(f, Loader=yaml.FullLoader)
for task in playbook.get(&#34;tasks&#34;, []): for task in playbook.get(&#34;tasks&#34;, []):
self.cli_run(task) self.cli_run(task)
except Exception as e: except Exception as e:
printer.error(f&#34;Failed to run playbook {path}: {e}&#34;) printer.error(f&#34;Failed to run playbook {path}: {e}&#34;)
sys.exit(10)</code></pre> sys.exit(10)</code></pre>
@@ -363,7 +454,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.cli.sync_handler API documentation</title> <title>connpy.cli.sync_handler API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -427,7 +427,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.cli.validators API documentation</title> <title>connpy.cli.validators API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -508,7 +508,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+734 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.grpc_layer.connpy_pb2 API documentation</title> <title>connpy.grpc_layer.connpy_pb2 API documentation</title>
<meta name="description" content="Generated protocol buffer code."> <meta name="description" content="Generated protocol buffer code.">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -45,6 +45,560 @@ el.replaceWith(d);
<section> <section>
</section> </section>
<section> <section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.AIResponse"><code class="flex name class">
<span>class <span class="ident">AIResponse</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.AIResponse.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.AskRequest"><code class="flex name class">
<span>class <span class="ident">AskRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.AskRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.BoolResponse"><code class="flex name class">
<span>class <span class="ident">BoolResponse</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.BoolResponse.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.BulkRequest"><code class="flex name class">
<span>class <span class="ident">BulkRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.BulkRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.DeleteRequest"><code class="flex name class">
<span>class <span class="ident">DeleteRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.DeleteRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.ExportRequest"><code class="flex name class">
<span>class <span class="ident">ExportRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.ExportRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.FilterRequest"><code class="flex name class">
<span>class <span class="ident">FilterRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.FilterRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.FullReplaceRequest"><code class="flex name class">
<span>class <span class="ident">FullReplaceRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.FullReplaceRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.IdRequest"><code class="flex name class">
<span>class <span class="ident">IdRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.IdRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.IntRequest"><code class="flex name class">
<span>class <span class="ident">IntRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.IntRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.InteractRequest"><code class="flex name class">
<span>class <span class="ident">InteractRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.InteractRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.InteractResponse"><code class="flex name class">
<span>class <span class="ident">InteractResponse</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.InteractResponse.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.ListRequest"><code class="flex name class">
<span>class <span class="ident">ListRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.ListRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.MessageValue"><code class="flex name class">
<span>class <span class="ident">MessageValue</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.MessageValue.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.MoveRequest"><code class="flex name class">
<span>class <span class="ident">MoveRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.MoveRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.NodeRequest"><code class="flex name class">
<span>class <span class="ident">NodeRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.NodeRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.NodeRunResult"><code class="flex name class">
<span>class <span class="ident">NodeRunResult</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.NodeRunResult.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.PluginRequest"><code class="flex name class">
<span>class <span class="ident">PluginRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.PluginRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.ProfileRequest"><code class="flex name class">
<span>class <span class="ident">ProfileRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.ProfileRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.ProviderRequest"><code class="flex name class">
<span>class <span class="ident">ProviderRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.ProviderRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.RunRequest"><code class="flex name class">
<span>class <span class="ident">RunRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.RunRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.ScriptRequest"><code class="flex name class">
<span>class <span class="ident">ScriptRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.ScriptRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.StringRequest"><code class="flex name class">
<span>class <span class="ident">StringRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.StringRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.StringResponse"><code class="flex name class">
<span>class <span class="ident">StringResponse</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.StringResponse.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.StructRequest"><code class="flex name class">
<span>class <span class="ident">StructRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.StructRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.StructResponse"><code class="flex name class">
<span>class <span class="ident">StructResponse</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.StructResponse.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.TestRequest"><code class="flex name class">
<span>class <span class="ident">TestRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.TestRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.UpdateRequest"><code class="flex name class">
<span>class <span class="ident">UpdateRequest</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.UpdateRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
<dt id="connpy.grpc_layer.connpy_pb2.ValueResponse"><code class="flex name class">
<span>class <span class="ident">ValueResponse</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google._upb._message.Message</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="connpy.grpc_layer.connpy_pb2.ValueResponse.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"><p>The type of the None singleton.</p></div>
</dd>
</dl>
</dd>
</dl>
</section> </section>
</article> </article>
<nav id="sidebar"> <nav id="sidebar">
@@ -57,11 +611,189 @@ el.replaceWith(d);
<li><code><a title="connpy.grpc_layer" href="index.html">connpy.grpc_layer</a></code></li> <li><code><a title="connpy.grpc_layer" href="index.html">connpy.grpc_layer</a></code></li>
</ul> </ul>
</li> </li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.AIResponse" href="#connpy.grpc_layer.connpy_pb2.AIResponse">AIResponse</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.AIResponse.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.AIResponse.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.AskRequest" href="#connpy.grpc_layer.connpy_pb2.AskRequest">AskRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.AskRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.AskRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.BoolResponse" href="#connpy.grpc_layer.connpy_pb2.BoolResponse">BoolResponse</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.BoolResponse.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.BoolResponse.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.BulkRequest" href="#connpy.grpc_layer.connpy_pb2.BulkRequest">BulkRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.BulkRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.BulkRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.DeleteRequest" href="#connpy.grpc_layer.connpy_pb2.DeleteRequest">DeleteRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.DeleteRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.DeleteRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.ExportRequest" href="#connpy.grpc_layer.connpy_pb2.ExportRequest">ExportRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.ExportRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.ExportRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.FilterRequest" href="#connpy.grpc_layer.connpy_pb2.FilterRequest">FilterRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.FilterRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.FilterRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.FullReplaceRequest" href="#connpy.grpc_layer.connpy_pb2.FullReplaceRequest">FullReplaceRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.FullReplaceRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.FullReplaceRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.IdRequest" href="#connpy.grpc_layer.connpy_pb2.IdRequest">IdRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.IdRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.IdRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.IntRequest" href="#connpy.grpc_layer.connpy_pb2.IntRequest">IntRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.IntRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.IntRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.InteractRequest" href="#connpy.grpc_layer.connpy_pb2.InteractRequest">InteractRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.InteractRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.InteractRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.InteractResponse" href="#connpy.grpc_layer.connpy_pb2.InteractResponse">InteractResponse</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.InteractResponse.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.InteractResponse.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.ListRequest" href="#connpy.grpc_layer.connpy_pb2.ListRequest">ListRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.ListRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.ListRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.MessageValue" href="#connpy.grpc_layer.connpy_pb2.MessageValue">MessageValue</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.MessageValue.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.MessageValue.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.MoveRequest" href="#connpy.grpc_layer.connpy_pb2.MoveRequest">MoveRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.MoveRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.MoveRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.NodeRequest" href="#connpy.grpc_layer.connpy_pb2.NodeRequest">NodeRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.NodeRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.NodeRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.NodeRunResult" href="#connpy.grpc_layer.connpy_pb2.NodeRunResult">NodeRunResult</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.NodeRunResult.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.NodeRunResult.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.PluginRequest" href="#connpy.grpc_layer.connpy_pb2.PluginRequest">PluginRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.PluginRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.PluginRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.ProfileRequest" href="#connpy.grpc_layer.connpy_pb2.ProfileRequest">ProfileRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.ProfileRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.ProfileRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.ProviderRequest" href="#connpy.grpc_layer.connpy_pb2.ProviderRequest">ProviderRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.ProviderRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.ProviderRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.RunRequest" href="#connpy.grpc_layer.connpy_pb2.RunRequest">RunRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.RunRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.RunRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.ScriptRequest" href="#connpy.grpc_layer.connpy_pb2.ScriptRequest">ScriptRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.ScriptRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.ScriptRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.StringRequest" href="#connpy.grpc_layer.connpy_pb2.StringRequest">StringRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.StringRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.StringRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.StringResponse" href="#connpy.grpc_layer.connpy_pb2.StringResponse">StringResponse</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.StringResponse.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.StringResponse.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.StructRequest" href="#connpy.grpc_layer.connpy_pb2.StructRequest">StructRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.StructRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.StructRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.StructResponse" href="#connpy.grpc_layer.connpy_pb2.StructResponse">StructResponse</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.StructResponse.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.StructResponse.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.TestRequest" href="#connpy.grpc_layer.connpy_pb2.TestRequest">TestRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.TestRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.TestRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.UpdateRequest" href="#connpy.grpc_layer.connpy_pb2.UpdateRequest">UpdateRequest</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.UpdateRequest.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.UpdateRequest.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="connpy.grpc_layer.connpy_pb2.ValueResponse" href="#connpy.grpc_layer.connpy_pb2.ValueResponse">ValueResponse</a></code></h4>
<ul class="">
<li><code><a title="connpy.grpc_layer.connpy_pb2.ValueResponse.DESCRIPTOR" href="#connpy.grpc_layer.connpy_pb2.ValueResponse.DESCRIPTOR">DESCRIPTOR</a></code></li>
</ul>
</li>
</ul>
</li>
</ul> </ul>
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.grpc_layer.connpy_pb2_grpc API documentation</title> <title>connpy.grpc_layer.connpy_pb2_grpc API documentation</title>
<meta name="description" content="Client and server classes corresponding to protobuf-defined services."> <meta name="description" content="Client and server classes corresponding to protobuf-defined services.">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -5735,7 +5735,7 @@ def stop_api(request,
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.grpc_layer API documentation</title> <title>connpy.grpc_layer API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -102,7 +102,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.grpc_layer.remote_plugin_pb2 API documentation</title> <title>connpy.grpc_layer.remote_plugin_pb2 API documentation</title>
<meta name="description" content="Generated protocol buffer code."> <meta name="description" content="Generated protocol buffer code.">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -62,7 +62,7 @@ el.replaceWith(d);
<dl> <dl>
<dt id="connpy.grpc_layer.remote_plugin_pb2.IdRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt> <dt id="connpy.grpc_layer.remote_plugin_pb2.IdRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd> <dd>
<div class="desc"></div> <div class="desc"><p>The type of the None singleton.</p></div>
</dd> </dd>
</dl> </dl>
</dd> </dd>
@@ -81,7 +81,7 @@ el.replaceWith(d);
<dl> <dl>
<dt id="connpy.grpc_layer.remote_plugin_pb2.OutputChunk.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt> <dt id="connpy.grpc_layer.remote_plugin_pb2.OutputChunk.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd> <dd>
<div class="desc"></div> <div class="desc"><p>The type of the None singleton.</p></div>
</dd> </dd>
</dl> </dl>
</dd> </dd>
@@ -100,7 +100,7 @@ el.replaceWith(d);
<dl> <dl>
<dt id="connpy.grpc_layer.remote_plugin_pb2.PluginInvokeRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt> <dt id="connpy.grpc_layer.remote_plugin_pb2.PluginInvokeRequest.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd> <dd>
<div class="desc"></div> <div class="desc"><p>The type of the None singleton.</p></div>
</dd> </dd>
</dl> </dl>
</dd> </dd>
@@ -119,7 +119,7 @@ el.replaceWith(d);
<dl> <dl>
<dt id="connpy.grpc_layer.remote_plugin_pb2.StringResponse.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt> <dt id="connpy.grpc_layer.remote_plugin_pb2.StringResponse.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd> <dd>
<div class="desc"></div> <div class="desc"><p>The type of the None singleton.</p></div>
</dd> </dd>
</dl> </dl>
</dd> </dd>
@@ -168,7 +168,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.grpc_layer.remote_plugin_pb2_grpc API documentation</title> <title>connpy.grpc_layer.remote_plugin_pb2_grpc API documentation</title>
<meta name="description" content="Client and server classes corresponding to protobuf-defined services."> <meta name="description" content="Client and server classes corresponding to protobuf-defined services.">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -366,7 +366,7 @@ def invoke_plugin(request,
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+19 -7
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.grpc_layer.server API documentation</title> <title>connpy.grpc_layer.server API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -367,14 +367,20 @@ el.replaceWith(d);
def _worker(): def _worker():
try: try:
# Set task name in thread state for printer if available
if request.name:
printer.console.print(f&#34;[debug][DEBUG][/debug] Executing task: [bold cyan]{request.name}[/bold cyan]&#34;)
self.service.run_commands( self.service.run_commands(
nodes_filter=nodes_filter, nodes_filter=nodes_filter,
commands=list(request.commands), commands=list(request.commands),
folder=request.folder if request.folder else None, folder=request.folder if request.folder else None,
prompt=request.prompt if request.prompt else None, prompt=request.prompt if request.prompt else None,
parallel=request.parallel, parallel=request.parallel,
timeout=request.timeout if request.timeout &gt; 0 else 10,
variables=from_struct(request.vars) if request.HasField(&#34;vars&#34;) else None, variables=from_struct(request.vars) if request.HasField(&#34;vars&#34;) else None,
on_node_complete=_on_complete on_node_complete=_on_complete,
name=request.name if request.name else None
) )
except Exception as e: except Exception as e:
# Optionally pass error to stream, but handle_errors decorator covers top-level. # Optionally pass error to stream, but handle_errors decorator covers top-level.
@@ -407,20 +413,26 @@ el.replaceWith(d);
q = queue.Queue() q = queue.Queue()
def _on_complete(unique, output, status, result): def _on_complete(unique, node_output, node_status, node_result):
q.put({&#34;unique_id&#34;: unique, &#34;output&#34;: output, &#34;status&#34;: status, &#34;result&#34;: result}) q.put({&#34;unique_id&#34;: unique, &#34;output&#34;: node_output, &#34;status&#34;: node_status, &#34;result&#34;: node_result})
def _worker(): def _worker():
try: try:
# Set task name in thread state for printer if available
if request.name:
printer.console.print(f&#34;[debug][DEBUG][/debug] Executing task: [bold cyan]{request.name}[/bold cyan]&#34;)
self.service.test_commands( self.service.test_commands(
nodes_filter=nodes_filter, nodes_filter=nodes_filter,
commands=list(request.commands), commands=list(request.commands),
expected=request.expected, expected=list(request.expected),
folder=request.folder if request.folder else None, folder=request.folder if request.folder else None,
prompt=request.prompt if request.prompt else None, prompt=request.prompt if request.prompt else None,
parallel=request.parallel, parallel=request.parallel,
timeout=request.timeout if request.timeout &gt; 0 else 10,
variables=from_struct(request.vars) if request.HasField(&#34;vars&#34;) else None, variables=from_struct(request.vars) if request.HasField(&#34;vars&#34;) else None,
on_node_complete=_on_complete on_node_complete=_on_complete,
name=request.name if request.name else None
) )
except Exception as e: except Exception as e:
q.put(e) q.put(e)
@@ -1313,7 +1325,7 @@ interceptor chooses to service this RPC, or None otherwise.</p></div>
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+20 -10
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.grpc_layer.stubs API documentation</title> <title>connpy.grpc_layer.stubs API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -642,9 +642,9 @@ def update_setting(self, key, value):
folder=folder or &#34;&#34;, folder=folder or &#34;&#34;,
prompt=prompt or &#34;&#34;, prompt=prompt or &#34;&#34;,
parallel=parallel, parallel=parallel,
timeout=timeout,
name=kwargs.get(&#34;name&#34;, &#34;&#34;)
) )
# Note: &#39;timeout&#39;, &#39;on_node_complete&#39;, and &#39;logger&#39; are currently not
# sent over gRPC in the current proto definition.
if variables is not None: if variables is not None:
req.vars.CopyFrom(to_struct(variables)) req.vars.CopyFrom(to_struct(variables))
@@ -654,7 +654,10 @@ def update_setting(self, key, value):
for response in self.stub.run_commands(req): for response in self.stub.run_commands(req):
if on_complete: if on_complete:
on_complete(response.unique_id, response.output, response.status) on_complete(response.unique_id, response.output, response.status)
final_results[response.unique_id] = response.output final_results[response.unique_id] = {
&#34;output&#34;: response.output,
&#34;status&#34;: response.status
}
return final_results return final_results
@@ -664,10 +667,12 @@ def update_setting(self, key, value):
req = connpy_pb2.TestRequest( req = connpy_pb2.TestRequest(
nodes=nodes_list, nodes=nodes_list,
commands=commands, commands=commands,
expected=expected, expected=expected if isinstance(expected, list) else [expected],
folder=kwargs.get(&#34;folder&#34;, &#34;&#34;), folder=kwargs.get(&#34;folder&#34;, &#34;&#34;),
prompt=prompt or &#34;&#34;, prompt=prompt or &#34;&#34;,
parallel=parallel, parallel=parallel,
timeout=timeout,
name=kwargs.get(&#34;name&#34;, &#34;&#34;)
) )
if variables is not None: if variables is not None:
req.vars.CopyFrom(to_struct(variables)) req.vars.CopyFrom(to_struct(variables))
@@ -728,9 +733,9 @@ def run_commands(self, nodes_filter, commands, variables=None, parallel=10, time
folder=folder or &#34;&#34;, folder=folder or &#34;&#34;,
prompt=prompt or &#34;&#34;, prompt=prompt or &#34;&#34;,
parallel=parallel, parallel=parallel,
timeout=timeout,
name=kwargs.get(&#34;name&#34;, &#34;&#34;)
) )
# Note: &#39;timeout&#39;, &#39;on_node_complete&#39;, and &#39;logger&#39; are currently not
# sent over gRPC in the current proto definition.
if variables is not None: if variables is not None:
req.vars.CopyFrom(to_struct(variables)) req.vars.CopyFrom(to_struct(variables))
@@ -740,7 +745,10 @@ def run_commands(self, nodes_filter, commands, variables=None, parallel=10, time
for response in self.stub.run_commands(req): for response in self.stub.run_commands(req):
if on_complete: if on_complete:
on_complete(response.unique_id, response.output, response.status) on_complete(response.unique_id, response.output, response.status)
final_results[response.unique_id] = response.output final_results[response.unique_id] = {
&#34;output&#34;: response.output,
&#34;status&#34;: response.status
}
return final_results</code></pre> return final_results</code></pre>
</details> </details>
@@ -775,10 +783,12 @@ def test_commands(self, nodes_filter, commands, expected, variables=None, parall
req = connpy_pb2.TestRequest( req = connpy_pb2.TestRequest(
nodes=nodes_list, nodes=nodes_list,
commands=commands, commands=commands,
expected=expected, expected=expected if isinstance(expected, list) else [expected],
folder=kwargs.get(&#34;folder&#34;, &#34;&#34;), folder=kwargs.get(&#34;folder&#34;, &#34;&#34;),
prompt=prompt or &#34;&#34;, prompt=prompt or &#34;&#34;,
parallel=parallel, parallel=parallel,
timeout=timeout,
name=kwargs.get(&#34;name&#34;, &#34;&#34;)
) )
if variables is not None: if variables is not None:
req.vars.CopyFrom(to_struct(variables)) req.vars.CopyFrom(to_struct(variables))
@@ -2102,7 +2112,7 @@ def stop_api(self):
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.grpc_layer.utils API documentation</title> <title>connpy.grpc_layer.utils API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -138,7 +138,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+122 -48
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy API documentation</title> <title>connpy API documentation</title>
<meta name="description" content="Connection manager …"> <meta name="description" content="Connection manager …">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -2077,7 +2077,7 @@ class ai:
<dl> <dl>
<dt id="connpy.ai.SAFE_COMMANDS"><code class="name">var <span class="ident">SAFE_COMMANDS</span></code></dt> <dt id="connpy.ai.SAFE_COMMANDS"><code class="name">var <span class="ident">SAFE_COMMANDS</span></code></dt>
<dd> <dd>
<div class="desc"></div> <div class="desc"><p>The type of the None singleton.</p></div>
</dd> </dd>
</dl> </dl>
<h3>Instance variables</h3> <h3>Instance variables</h3>
@@ -3170,15 +3170,7 @@ class configfile:
if isinstance(uniques, str): if isinstance(uniques, str):
uniques = [uniques] uniques = [uniques]
for i in uniques: for i in uniques:
if isinstance(i, dict): if i.startswith(&#34;@&#34;):
name = list(i.keys())[0]
mylist = i[name]
if not self.config[&#34;case&#34;]:
name = name.lower()
mylist = [item.lower() for item in mylist]
this = self.getitem(name, mylist, extract = extract)
nodes.update(this)
elif i.startswith(&#34;@&#34;):
if not self.config[&#34;case&#34;]: if not self.config[&#34;case&#34;]:
i = i.lower() i = i.lower()
this = self.getitem(i, extract = extract) this = self.getitem(i, extract = extract)
@@ -3257,13 +3249,17 @@ class configfile:
layer3 = [k + &#34;@&#34; + s + &#34;@&#34; + f for k,v in self.connections[f][s].items() if isinstance(v, dict) and v.get(&#34;type&#34;) == &#34;connection&#34;] layer3 = [k + &#34;@&#34; + s + &#34;@&#34; + f for k,v in self.connections[f][s].items() if isinstance(v, dict) and v.get(&#34;type&#34;) == &#34;connection&#34;]
nodes.extend(layer3) nodes.extend(layer3)
if filter: if filter:
flat_filter = []
if isinstance(filter, str): if isinstance(filter, str):
nodes = [item for item in nodes if re.search(filter, item)] flat_filter = [filter]
elif isinstance(filter, list): elif isinstance(filter, list):
nodes = [item for item in nodes if any(re.search(pattern, item) for pattern in filter)] for item in filter:
if isinstance(item, str):
flat_filter.append(item)
else: else:
printer.error(&#34;Invalid filter: must be a string or a list of strings.&#34;) printer.error(&#34;Filter must be a string or a list of strings&#34;)
sys.exit(1) sys.exit(1)
nodes = [item for item in nodes if any(re.search(pattern, item) for pattern in flat_filter)]
return nodes return nodes
@MethodHook @MethodHook
@@ -3281,15 +3277,18 @@ class configfile:
layer3 = {k + &#34;@&#34; + s + &#34;@&#34; + f:v for k,v in self.connections[f][s].items() if isinstance(v, dict) and v.get(&#34;type&#34;) == &#34;connection&#34;} layer3 = {k + &#34;@&#34; + s + &#34;@&#34; + f:v for k,v in self.connections[f][s].items() if isinstance(v, dict) and v.get(&#34;type&#34;) == &#34;connection&#34;}
nodes.update(layer3) nodes.update(layer3)
if filter: if filter:
flat_filter = []
if isinstance(filter, str): if isinstance(filter, str):
filter = &#34;^(?!.*@).+$&#34; if filter == &#34;@&#34; else filter flat_filter = [filter]
nodes = {k: v for k, v in nodes.items() if re.search(filter, k)}
elif isinstance(filter, list): elif isinstance(filter, list):
filter = [&#34;^(?!.*@).+$&#34; if item == &#34;@&#34; else item for item in filter] for item in filter:
nodes = {k: v for k, v in nodes.items() if any(re.search(pattern, k) for pattern in filter)} if isinstance(item, str):
flat_filter.append(item)
else: else:
printer.error(&#34;Invalid filter: must be a string or a list of strings.&#34;) printer.error(&#34;Filter must be a string or a list of strings&#34;)
sys.exit(1) sys.exit(1)
flat_filter = [&#34;^(?!.*@).+$&#34; if item == &#34;@&#34; else item for item in flat_filter]
nodes = {k: v for k, v in nodes.items() if any(re.search(pattern, k) for pattern in flat_filter)}
if extract: if extract:
for node, keys in nodes.items(): for node, keys in nodes.items():
for key, value in keys.items(): for key, value in keys.items():
@@ -3586,15 +3585,7 @@ def getitems(self, uniques, extract = False):
if isinstance(uniques, str): if isinstance(uniques, str):
uniques = [uniques] uniques = [uniques]
for i in uniques: for i in uniques:
if isinstance(i, dict): if i.startswith(&#34;@&#34;):
name = list(i.keys())[0]
mylist = i[name]
if not self.config[&#34;case&#34;]:
name = name.lower()
mylist = [item.lower() for item in mylist]
this = self.getitem(name, mylist, extract = extract)
nodes.update(this)
elif i.startswith(&#34;@&#34;):
if not self.config[&#34;case&#34;]: if not self.config[&#34;case&#34;]:
i = i.lower() i = i.lower()
this = self.getitem(i, extract = extract) this = self.getitem(i, extract = extract)
@@ -3759,6 +3750,10 @@ class node:
self.jumphost = f&#34;-o ProxyCommand=\&#34;{jumphost_cmd}\&#34;&#34; self.jumphost = f&#34;-o ProxyCommand=\&#34;{jumphost_cmd}\&#34;&#34;
else: else:
self.jumphost = &#34;&#34; self.jumphost = &#34;&#34;
self.output = &#34;&#34;
self.status = 1
self.result = {}
@MethodHook @MethodHook
def _passtx(self, passwords, *, keyfile=None): def _passtx(self, passwords, *, keyfile=None):
@@ -4159,7 +4154,12 @@ class node:
self.child.logfile_read = self.mylog self.child.logfile_read = self.mylog
for c in commands: for c in commands:
if vars is not None: if vars is not None:
c = c.format(**vars) try:
c = c.format(**vars)
except KeyError as e:
self.output = f&#34;Error: Variable {e} not defined in task or inventory&#34;
self.status = 1
return self.output
result = self.child.expect(expects, timeout = timeout) result = self.child.expect(expects, timeout = timeout)
self.child.sendline(c) self.child.sendline(c)
if result == 2: if result == 2:
@@ -4193,7 +4193,7 @@ class node:
return connect return connect
@MethodHook @MethodHook
def test(self, commands, expected, vars = None,*, prompt = r&#39;&gt;$|#$|\$$|&gt;.$|#.$|\$.$&#39;, timeout = 10, logger = None): def test(self, commands, expected, vars = None,*, folder = &#39;&#39;, prompt = r&#39;&gt;$|#$|\$$|&gt;.$|#.$|\$.$&#39;, timeout = 10, logger = None):
&#39;&#39;&#39; &#39;&#39;&#39;
Run a command or list of commands on the node, then check if expected value appears on the output after the last command. Run a command or list of commands on the node, then check if expected value appears on the output after the last command.
@@ -4219,6 +4219,9 @@ class node:
### Optional Named Parameters: ### Optional Named Parameters:
- folder (str): Path where output log should be stored, leave
empty to not store logs.
- prompt (str): Prompt to be expected after a command is finished - prompt (str): Prompt to be expected after a command is finished
running. Usually linux uses &#34;&gt;&#34; or EOF while running. Usually linux uses &#34;&gt;&#34; or EOF while
routers use &#34;&gt;&#34; or &#34;#&#34;. The default value should routers use &#34;&gt;&#34; or &#34;#&#34;. The default value should
@@ -4233,6 +4236,7 @@ class node:
false if prompt is found before. false if prompt is found before.
&#39;&#39;&#39; &#39;&#39;&#39;
now = datetime.datetime.now().strftime(&#34;%Y-%m-%d_%H-%M-%S&#34;)
connect = self._connect(timeout = timeout, logger = logger) connect = self._connect(timeout = timeout, logger = logger)
if connect == True: if connect == True:
if logger: if logger:
@@ -4250,6 +4254,7 @@ class node:
if &#34;prompt&#34; in self.tags: if &#34;prompt&#34; in self.tags:
prompt = self.tags[&#34;prompt&#34;] prompt = self.tags[&#34;prompt&#34;]
expects = [prompt, pexpect.EOF, pexpect.TIMEOUT] expects = [prompt, pexpect.EOF, pexpect.TIMEOUT]
output = &#39;&#39; output = &#39;&#39;
if not isinstance(commands, list): if not isinstance(commands, list):
commands = [commands] commands = [commands]
@@ -4261,7 +4266,12 @@ class node:
self.child.logfile_read = self.mylog self.child.logfile_read = self.mylog
for c in commands: for c in commands:
if vars is not None: if vars is not None:
c = c.format(**vars) try:
c = c.format(**vars)
except KeyError as e:
self.output = f&#34;Error: Variable {e} not defined in task or inventory&#34;
self.status = 1
return self.output
result = self.child.expect(expects, timeout = timeout) result = self.child.expect(expects, timeout = timeout)
self.child.sendline(c) self.child.sendline(c)
if result == 2: if result == 2:
@@ -4270,6 +4280,12 @@ class node:
result = self.child.expect(expects, timeout = timeout) result = self.child.expect(expects, timeout = timeout)
self.child.close() self.child.close()
output = self._logclean(self.mylog.getvalue().decode(), True) output = self._logclean(self.mylog.getvalue().decode(), True)
if logger:
logger(&#34;output&#34;, output)
if folder != &#39;&#39;:
with open(folder + &#34;/&#34; + self.unique + &#34;_&#34; + now + &#34;.txt&#34;, &#34;w&#34;) as f:
f.write(output)
f.close()
self.output = output self.output = output
if result in [0, 1]: if result in [0, 1]:
# lastcommand = commands[-1] # lastcommand = commands[-1]
@@ -4654,7 +4670,12 @@ def run(self, commands, vars = None,*, folder = &#39;&#39;, prompt = r&#39;&gt;$
self.child.logfile_read = self.mylog self.child.logfile_read = self.mylog
for c in commands: for c in commands:
if vars is not None: if vars is not None:
c = c.format(**vars) try:
c = c.format(**vars)
except KeyError as e:
self.output = f&#34;Error: Variable {e} not defined in task or inventory&#34;
self.status = 1
return self.output
result = self.child.expect(expects, timeout = timeout) result = self.child.expect(expects, timeout = timeout)
self.child.sendline(c) self.child.sendline(c)
if result == 2: if result == 2:
@@ -4721,7 +4742,7 @@ def run(self, commands, vars = None,*, folder = &#39;&#39;, prompt = r&#39;&gt;$
</code></pre></div> </code></pre></div>
</dd> </dd>
<dt id="connpy.node.test"><code class="name flex"> <dt id="connpy.node.test"><code class="name flex">
<span>def <span class="ident">test</span></span>(<span>self,<br>commands,<br>expected,<br>vars=None,<br>*,<br>prompt=&#x27;&gt;$|#$|\\$$|&gt;.$|#.$|\\$.$&#x27;,<br>timeout=10,<br>logger=None)</span> <span>def <span class="ident">test</span></span>(<span>self,<br>commands,<br>expected,<br>vars=None,<br>*,<br>folder='',<br>prompt=&#x27;&gt;$|#$|\\$$|&gt;.$|#.$|\\$.$&#x27;,<br>timeout=10,<br>logger=None)</span>
</code></dt> </code></dt>
<dd> <dd>
<details class="source"> <details class="source">
@@ -4729,7 +4750,7 @@ def run(self, commands, vars = None,*, folder = &#39;&#39;, prompt = r&#39;&gt;$
<span>Expand source code</span> <span>Expand source code</span>
</summary> </summary>
<pre><code class="python">@MethodHook <pre><code class="python">@MethodHook
def test(self, commands, expected, vars = None,*, prompt = r&#39;&gt;$|#$|\$$|&gt;.$|#.$|\$.$&#39;, timeout = 10, logger = None): def test(self, commands, expected, vars = None,*, folder = &#39;&#39;, prompt = r&#39;&gt;$|#$|\$$|&gt;.$|#.$|\$.$&#39;, timeout = 10, logger = None):
&#39;&#39;&#39; &#39;&#39;&#39;
Run a command or list of commands on the node, then check if expected value appears on the output after the last command. Run a command or list of commands on the node, then check if expected value appears on the output after the last command.
@@ -4755,6 +4776,9 @@ def test(self, commands, expected, vars = None,*, prompt = r&#39;&gt;$|#$|\$$|&g
### Optional Named Parameters: ### Optional Named Parameters:
- folder (str): Path where output log should be stored, leave
empty to not store logs.
- prompt (str): Prompt to be expected after a command is finished - prompt (str): Prompt to be expected after a command is finished
running. Usually linux uses &#34;&gt;&#34; or EOF while running. Usually linux uses &#34;&gt;&#34; or EOF while
routers use &#34;&gt;&#34; or &#34;#&#34;. The default value should routers use &#34;&gt;&#34; or &#34;#&#34;. The default value should
@@ -4769,6 +4793,7 @@ def test(self, commands, expected, vars = None,*, prompt = r&#39;&gt;$|#$|\$$|&g
false if prompt is found before. false if prompt is found before.
&#39;&#39;&#39; &#39;&#39;&#39;
now = datetime.datetime.now().strftime(&#34;%Y-%m-%d_%H-%M-%S&#34;)
connect = self._connect(timeout = timeout, logger = logger) connect = self._connect(timeout = timeout, logger = logger)
if connect == True: if connect == True:
if logger: if logger:
@@ -4786,6 +4811,7 @@ def test(self, commands, expected, vars = None,*, prompt = r&#39;&gt;$|#$|\$$|&g
if &#34;prompt&#34; in self.tags: if &#34;prompt&#34; in self.tags:
prompt = self.tags[&#34;prompt&#34;] prompt = self.tags[&#34;prompt&#34;]
expects = [prompt, pexpect.EOF, pexpect.TIMEOUT] expects = [prompt, pexpect.EOF, pexpect.TIMEOUT]
output = &#39;&#39; output = &#39;&#39;
if not isinstance(commands, list): if not isinstance(commands, list):
commands = [commands] commands = [commands]
@@ -4797,7 +4823,12 @@ def test(self, commands, expected, vars = None,*, prompt = r&#39;&gt;$|#$|\$$|&g
self.child.logfile_read = self.mylog self.child.logfile_read = self.mylog
for c in commands: for c in commands:
if vars is not None: if vars is not None:
c = c.format(**vars) try:
c = c.format(**vars)
except KeyError as e:
self.output = f&#34;Error: Variable {e} not defined in task or inventory&#34;
self.status = 1
return self.output
result = self.child.expect(expects, timeout = timeout) result = self.child.expect(expects, timeout = timeout)
self.child.sendline(c) self.child.sendline(c)
if result == 2: if result == 2:
@@ -4806,6 +4837,12 @@ def test(self, commands, expected, vars = None,*, prompt = r&#39;&gt;$|#$|\$$|&g
result = self.child.expect(expects, timeout = timeout) result = self.child.expect(expects, timeout = timeout)
self.child.close() self.child.close()
output = self._logclean(self.mylog.getvalue().decode(), True) output = self._logclean(self.mylog.getvalue().decode(), True)
if logger:
logger(&#34;output&#34;, output)
if folder != &#39;&#39;:
with open(folder + &#34;/&#34; + self.unique + &#34;_&#34; + now + &#34;.txt&#34;, &#34;w&#34;) as f:
f.write(output)
f.close()
self.output = output self.output = output
if result in [0, 1]: if result in [0, 1]:
# lastcommand = commands[-1] # lastcommand = commands[-1]
@@ -4856,7 +4893,10 @@ def test(self, commands, expected, vars = None,*, prompt = r&#39;&gt;$|#$|\$$|&g
Values: strings. Values: strings.
</code></pre> </code></pre>
<h3 id="optional-named-parameters">Optional Named Parameters:</h3> <h3 id="optional-named-parameters">Optional Named Parameters:</h3>
<pre><code>- prompt (str): Prompt to be expected after a command is finished <pre><code>- folder (str): Path where output log should be stored, leave
empty to not store logs.
- prompt (str): Prompt to be expected after a command is finished
running. Usually linux uses "&gt;" or EOF while running. Usually linux uses "&gt;" or EOF while
routers use "&gt;" or "#". The default value should routers use "&gt;" or "#". The default value should
work for most nodes. Change it if your connection work for most nodes. Change it if your connection
@@ -5022,8 +5062,15 @@ class nodes:
nodesargs[n.unique][&#34;vars&#34;] = {} nodesargs[n.unique][&#34;vars&#34;] = {}
if &#34;__global__&#34; in vars.keys(): if &#34;__global__&#34; in vars.keys():
nodesargs[n.unique][&#34;vars&#34;].update(vars[&#34;__global__&#34;]) nodesargs[n.unique][&#34;vars&#34;].update(vars[&#34;__global__&#34;])
if n.unique in vars.keys(): for var_key, var_val in vars.items():
nodesargs[n.unique][&#34;vars&#34;].update(vars[n.unique]) if var_key == &#34;__global__&#34;:
continue
try:
if re.search(var_key, n.unique, re.IGNORECASE):
nodesargs[n.unique][&#34;vars&#34;].update(var_val)
except re.error:
if var_key == n.unique:
nodesargs[n.unique][&#34;vars&#34;].update(var_val)
# Pass the logger to the node # Pass the logger to the node
nodesargs[n.unique][&#34;logger&#34;] = logger nodesargs[n.unique][&#34;logger&#34;] = logger
@@ -5048,7 +5095,7 @@ class nodes:
return output return output
@MethodHook @MethodHook
def test(self, commands, expected, vars = None,*, prompt = None, parallel = 10, timeout = None, on_complete = None, logger = None): def test(self, commands, expected, vars = None,*, folder = None, prompt = None, parallel = 10, timeout = None, on_complete = None, logger = None):
&#39;&#39;&#39; &#39;&#39;&#39;
Run a command or list of commands on all the nodes in nodelist, then check if expected value appears on the output after the last command. Run a command or list of commands on all the nodes in nodelist, then check if expected value appears on the output after the last command.
@@ -5103,6 +5150,9 @@ class nodes:
nodesargs = {} nodesargs = {}
args[&#34;commands&#34;] = commands args[&#34;commands&#34;] = commands
args[&#34;expected&#34;] = expected args[&#34;expected&#34;] = expected
if folder != None:
args[&#34;folder&#34;] = folder
Path(folder).mkdir(parents=True, exist_ok=True)
if prompt != None: if prompt != None:
args[&#34;prompt&#34;] = prompt args[&#34;prompt&#34;] = prompt
if timeout != None: if timeout != None:
@@ -5124,8 +5174,15 @@ class nodes:
nodesargs[n.unique][&#34;vars&#34;] = {} nodesargs[n.unique][&#34;vars&#34;] = {}
if &#34;__global__&#34; in vars.keys(): if &#34;__global__&#34; in vars.keys():
nodesargs[n.unique][&#34;vars&#34;].update(vars[&#34;__global__&#34;]) nodesargs[n.unique][&#34;vars&#34;].update(vars[&#34;__global__&#34;])
if n.unique in vars.keys(): for var_key, var_val in vars.items():
nodesargs[n.unique][&#34;vars&#34;].update(vars[n.unique]) if var_key == &#34;__global__&#34;:
continue
try:
if re.search(var_key, n.unique, re.IGNORECASE):
nodesargs[n.unique][&#34;vars&#34;].update(var_val)
except re.error:
if var_key == n.unique:
nodesargs[n.unique][&#34;vars&#34;].update(var_val)
nodesargs[n.unique][&#34;logger&#34;] = logger nodesargs[n.unique][&#34;logger&#34;] = logger
if on_complete: if on_complete:
@@ -5275,8 +5332,15 @@ def run(self, commands, vars = None,*, folder = None, prompt = None, stdout = No
nodesargs[n.unique][&#34;vars&#34;] = {} nodesargs[n.unique][&#34;vars&#34;] = {}
if &#34;__global__&#34; in vars.keys(): if &#34;__global__&#34; in vars.keys():
nodesargs[n.unique][&#34;vars&#34;].update(vars[&#34;__global__&#34;]) nodesargs[n.unique][&#34;vars&#34;].update(vars[&#34;__global__&#34;])
if n.unique in vars.keys(): for var_key, var_val in vars.items():
nodesargs[n.unique][&#34;vars&#34;].update(vars[n.unique]) if var_key == &#34;__global__&#34;:
continue
try:
if re.search(var_key, n.unique, re.IGNORECASE):
nodesargs[n.unique][&#34;vars&#34;].update(var_val)
except re.error:
if var_key == n.unique:
nodesargs[n.unique][&#34;vars&#34;].update(var_val)
# Pass the logger to the node # Pass the logger to the node
nodesargs[n.unique][&#34;logger&#34;] = logger nodesargs[n.unique][&#34;logger&#34;] = logger
@@ -5346,7 +5410,7 @@ def run(self, commands, vars = None,*, folder = None, prompt = None, stdout = No
</code></pre></div> </code></pre></div>
</dd> </dd>
<dt id="connpy.nodes.test"><code class="name flex"> <dt id="connpy.nodes.test"><code class="name flex">
<span>def <span class="ident">test</span></span>(<span>self,<br>commands,<br>expected,<br>vars=None,<br>*,<br>prompt=None,<br>parallel=10,<br>timeout=None,<br>on_complete=None,<br>logger=None)</span> <span>def <span class="ident">test</span></span>(<span>self,<br>commands,<br>expected,<br>vars=None,<br>*,<br>folder=None,<br>prompt=None,<br>parallel=10,<br>timeout=None,<br>on_complete=None,<br>logger=None)</span>
</code></dt> </code></dt>
<dd> <dd>
<details class="source"> <details class="source">
@@ -5354,7 +5418,7 @@ def run(self, commands, vars = None,*, folder = None, prompt = None, stdout = No
<span>Expand source code</span> <span>Expand source code</span>
</summary> </summary>
<pre><code class="python">@MethodHook <pre><code class="python">@MethodHook
def test(self, commands, expected, vars = None,*, prompt = None, parallel = 10, timeout = None, on_complete = None, logger = None): def test(self, commands, expected, vars = None,*, folder = None, prompt = None, parallel = 10, timeout = None, on_complete = None, logger = None):
&#39;&#39;&#39; &#39;&#39;&#39;
Run a command or list of commands on all the nodes in nodelist, then check if expected value appears on the output after the last command. Run a command or list of commands on all the nodes in nodelist, then check if expected value appears on the output after the last command.
@@ -5409,6 +5473,9 @@ def test(self, commands, expected, vars = None,*, prompt = None, parallel = 10,
nodesargs = {} nodesargs = {}
args[&#34;commands&#34;] = commands args[&#34;commands&#34;] = commands
args[&#34;expected&#34;] = expected args[&#34;expected&#34;] = expected
if folder != None:
args[&#34;folder&#34;] = folder
Path(folder).mkdir(parents=True, exist_ok=True)
if prompt != None: if prompt != None:
args[&#34;prompt&#34;] = prompt args[&#34;prompt&#34;] = prompt
if timeout != None: if timeout != None:
@@ -5430,8 +5497,15 @@ def test(self, commands, expected, vars = None,*, prompt = None, parallel = 10,
nodesargs[n.unique][&#34;vars&#34;] = {} nodesargs[n.unique][&#34;vars&#34;] = {}
if &#34;__global__&#34; in vars.keys(): if &#34;__global__&#34; in vars.keys():
nodesargs[n.unique][&#34;vars&#34;].update(vars[&#34;__global__&#34;]) nodesargs[n.unique][&#34;vars&#34;].update(vars[&#34;__global__&#34;])
if n.unique in vars.keys(): for var_key, var_val in vars.items():
nodesargs[n.unique][&#34;vars&#34;].update(vars[n.unique]) if var_key == &#34;__global__&#34;:
continue
try:
if re.search(var_key, n.unique, re.IGNORECASE):
nodesargs[n.unique][&#34;vars&#34;].update(var_val)
except re.error:
if var_key == n.unique:
nodesargs[n.unique][&#34;vars&#34;].update(var_val)
nodesargs[n.unique][&#34;logger&#34;] = logger nodesargs[n.unique][&#34;logger&#34;] = logger
if on_complete: if on_complete:
@@ -5626,7 +5700,7 @@ def test(self, commands, expected, vars = None,*, prompt = None, parallel = 10,
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.proto API documentation</title> <title>connpy.proto API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -60,7 +60,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.services.ai_service API documentation</title> <title>connpy.services.ai_service API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -265,7 +265,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.services.base API documentation</title> <title>connpy.services.base API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -152,7 +152,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.services.config_service API documentation</title> <title>connpy.services.config_service API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -311,7 +311,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.services.context_service API documentation</title> <title>connpy.services.context_service API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -370,7 +370,7 @@ def current_context(self) -&gt; str:
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.services.exceptions API documentation</title> <title>connpy.services.exceptions API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -268,7 +268,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+112 -58
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.services.execution_service API documentation</title> <title>connpy.services.execution_service API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -68,7 +68,8 @@ el.replaceWith(d);
folder: Optional[str] = None, folder: Optional[str] = None,
prompt: Optional[str] = None, prompt: Optional[str] = None,
on_node_complete: Optional[Callable] = None, on_node_complete: Optional[Callable] = None,
logger: Optional[Callable] = None logger: Optional[Callable] = None,
name: Optional[str] = None
) -&gt; Dict[str, str]: ) -&gt; Dict[str, str]:
&#34;&#34;&#34;Execute commands on a set of nodes.&#34;&#34;&#34; &#34;&#34;&#34;Execute commands on a set of nodes.&#34;&#34;&#34;
@@ -92,7 +93,15 @@ el.replaceWith(d);
logger=logger logger=logger
) )
return results # Combine output and status for the caller
full_results = {}
for unique in results:
full_results[unique] = {
&#34;output&#34;: results[unique],
&#34;status&#34;: executor.status.get(unique, 1)
}
return full_results
except Exception as e: except Exception as e:
raise ConnpyError(f&#34;Execution failed: {e}&#34;) raise ConnpyError(f&#34;Execution failed: {e}&#34;)
@@ -104,9 +113,11 @@ el.replaceWith(d);
variables: Optional[Dict[str, Any]] = None, variables: Optional[Dict[str, Any]] = None,
parallel: int = 10, parallel: int = 10,
timeout: int = 10, timeout: int = 10,
folder: Optional[str] = None,
prompt: Optional[str] = None, prompt: Optional[str] = None,
on_node_complete: Optional[Callable] = None, on_node_complete: Optional[Callable] = None,
logger: Optional[Callable] = None logger: Optional[Callable] = None,
name: Optional[str] = None
) -&gt; Dict[str, Dict[str, bool]]: ) -&gt; Dict[str, Dict[str, bool]]:
&#34;&#34;&#34;Run commands and verify expected output on a set of nodes.&#34;&#34;&#34; &#34;&#34;&#34;Run commands and verify expected output on a set of nodes.&#34;&#34;&#34;
@@ -125,6 +136,7 @@ el.replaceWith(d);
vars=variables, vars=variables,
parallel=parallel, parallel=parallel,
timeout=timeout, timeout=timeout,
folder=folder,
prompt=prompt, prompt=prompt,
on_complete=on_node_complete, on_complete=on_node_complete,
logger=logger logger=logger
@@ -146,37 +158,52 @@ el.replaceWith(d);
return self.run_commands(nodes_filter, commands, parallel=parallel) return self.run_commands(nodes_filter, commands, parallel=parallel)
def run_yaml_playbook(self, playbook_path: str, parallel: int = 10) -&gt; Dict[str, Any]: def run_yaml_playbook(self, playbook_data: str, parallel: int = 10) -&gt; Dict[str, Any]:
&#34;&#34;&#34;Run a structured Connpy YAML automation playbook.&#34;&#34;&#34; &#34;&#34;&#34;Run a structured Connpy YAML automation playbook (from path or content).&#34;&#34;&#34;
if not os.path.exists(playbook_path): playbook = None
raise ConnpyError(f&#34;Playbook file not found: {playbook_path}&#34;) if playbook_data.startswith(&#34;---YAML---\n&#34;):
try:
try: content = playbook_data[len(&#34;---YAML---\n&#34;):]
with open(playbook_path, &#34;r&#34;) as f: playbook = yaml.load(content, Loader=yaml.FullLoader)
playbook = yaml.load(f, Loader=yaml.FullLoader) except Exception as e:
except Exception as e: raise ConnpyError(f&#34;Failed to parse YAML content: {e}&#34;)
raise ConnpyError(f&#34;Failed to load playbook {playbook_path}: {e}&#34;) else:
if not os.path.exists(playbook_data):
raise ConnpyError(f&#34;Playbook file not found: {playbook_data}&#34;)
try:
with open(playbook_data, &#34;r&#34;) as f:
playbook = yaml.load(f, Loader=yaml.FullLoader)
except Exception as e:
raise ConnpyError(f&#34;Failed to load playbook {playbook_data}: {e}&#34;)
# Basic validation # Basic validation
if not isinstance(playbook, dict) or &#34;nodes&#34; not in playbook or &#34;commands&#34; not in playbook: if not isinstance(playbook, dict) or &#34;nodes&#34; not in playbook or &#34;commands&#34; not in playbook:
raise ConnpyError(&#34;Invalid playbook format: missing &#39;nodes&#39; or &#39;commands&#39; keys.&#34;) raise ConnpyError(&#34;Invalid playbook format: missing &#39;nodes&#39; or &#39;commands&#39; keys.&#34;)
action = playbook.get(&#34;action&#34;, &#34;run&#34;) action = playbook.get(&#34;action&#34;, &#34;run&#34;)
options = playbook.get(&#34;options&#34;, {})
# Extract all fields similar to RunHandler.cli_run
exec_args = {
&#34;nodes_filter&#34;: playbook[&#34;nodes&#34;],
&#34;commands&#34;: playbook[&#34;commands&#34;],
&#34;variables&#34;: playbook.get(&#34;variables&#34;),
&#34;parallel&#34;: options.get(&#34;parallel&#34;, parallel),
&#34;timeout&#34;: playbook.get(&#34;timeout&#34;, options.get(&#34;timeout&#34;, 10)),
&#34;prompt&#34;: options.get(&#34;prompt&#34;),
&#34;name&#34;: playbook.get(&#34;name&#34;, &#34;Task&#34;)
}
# Map &#39;output&#39; field to folder path if it&#39;s not stdout/null
output_cfg = playbook.get(&#34;output&#34;)
if output_cfg not in [None, &#34;stdout&#34;]:
exec_args[&#34;folder&#34;] = output_cfg
if action == &#34;run&#34;: if action == &#34;run&#34;:
return self.run_commands( return self.run_commands(**exec_args)
nodes_filter=playbook[&#34;nodes&#34;],
commands=playbook[&#34;commands&#34;],
parallel=parallel,
timeout=playbook.get(&#34;timeout&#34;, 10)
)
elif action == &#34;test&#34;: elif action == &#34;test&#34;:
return self.test_commands( exec_args[&#34;expected&#34;] = playbook.get(&#34;expected&#34;, [])
nodes_filter=playbook[&#34;nodes&#34;], return self.test_commands(**exec_args)
commands=playbook[&#34;commands&#34;],
expected=playbook.get(&#34;expected&#34;, []),
parallel=parallel,
timeout=playbook.get(&#34;timeout&#34;, 10)
)
else: else:
raise ConnpyError(f&#34;Unsupported playbook action: {action}&#34;)</code></pre> raise ConnpyError(f&#34;Unsupported playbook action: {action}&#34;)</code></pre>
</details> </details>
@@ -217,7 +244,7 @@ el.replaceWith(d);
<div class="desc"><p>Run a plain-text script containing one command per line.</p></div> <div class="desc"><p>Run a plain-text script containing one command per line.</p></div>
</dd> </dd>
<dt id="connpy.services.execution_service.ExecutionService.run_commands"><code class="name flex"> <dt id="connpy.services.execution_service.ExecutionService.run_commands"><code class="name flex">
<span>def <span class="ident">run_commands</span></span>(<span>self,<br>nodes_filter: str,<br>commands: List[str],<br>variables: Dict[str, Any] | None = None,<br>parallel: int = 10,<br>timeout: int = 10,<br>folder: str | None = None,<br>prompt: str | None = None,<br>on_node_complete: Callable | None = None,<br>logger: Callable | None = None) > Dict[str, str]</span> <span>def <span class="ident">run_commands</span></span>(<span>self,<br>nodes_filter: str,<br>commands: List[str],<br>variables: Dict[str, Any] | None = None,<br>parallel: int = 10,<br>timeout: int = 10,<br>folder: str | None = None,<br>prompt: str | None = None,<br>on_node_complete: Callable | None = None,<br>logger: Callable | None = None,<br>name: str | None = None) > Dict[str, str]</span>
</code></dt> </code></dt>
<dd> <dd>
<details class="source"> <details class="source">
@@ -234,7 +261,8 @@ el.replaceWith(d);
folder: Optional[str] = None, folder: Optional[str] = None,
prompt: Optional[str] = None, prompt: Optional[str] = None,
on_node_complete: Optional[Callable] = None, on_node_complete: Optional[Callable] = None,
logger: Optional[Callable] = None logger: Optional[Callable] = None,
name: Optional[str] = None
) -&gt; Dict[str, str]: ) -&gt; Dict[str, str]:
&#34;&#34;&#34;Execute commands on a set of nodes.&#34;&#34;&#34; &#34;&#34;&#34;Execute commands on a set of nodes.&#34;&#34;&#34;
@@ -258,58 +286,81 @@ el.replaceWith(d);
logger=logger logger=logger
) )
return results # Combine output and status for the caller
full_results = {}
for unique in results:
full_results[unique] = {
&#34;output&#34;: results[unique],
&#34;status&#34;: executor.status.get(unique, 1)
}
return full_results
except Exception as e: except Exception as e:
raise ConnpyError(f&#34;Execution failed: {e}&#34;)</code></pre> raise ConnpyError(f&#34;Execution failed: {e}&#34;)</code></pre>
</details> </details>
<div class="desc"><p>Execute commands on a set of nodes.</p></div> <div class="desc"><p>Execute commands on a set of nodes.</p></div>
</dd> </dd>
<dt id="connpy.services.execution_service.ExecutionService.run_yaml_playbook"><code class="name flex"> <dt id="connpy.services.execution_service.ExecutionService.run_yaml_playbook"><code class="name flex">
<span>def <span class="ident">run_yaml_playbook</span></span>(<span>self, playbook_path: str, parallel: int = 10) > Dict[str, Any]</span> <span>def <span class="ident">run_yaml_playbook</span></span>(<span>self, playbook_data: str, parallel: int = 10) > Dict[str, Any]</span>
</code></dt> </code></dt>
<dd> <dd>
<details class="source"> <details class="source">
<summary> <summary>
<span>Expand source code</span> <span>Expand source code</span>
</summary> </summary>
<pre><code class="python">def run_yaml_playbook(self, playbook_path: str, parallel: int = 10) -&gt; Dict[str, Any]: <pre><code class="python">def run_yaml_playbook(self, playbook_data: str, parallel: int = 10) -&gt; Dict[str, Any]:
&#34;&#34;&#34;Run a structured Connpy YAML automation playbook.&#34;&#34;&#34; &#34;&#34;&#34;Run a structured Connpy YAML automation playbook (from path or content).&#34;&#34;&#34;
if not os.path.exists(playbook_path): playbook = None
raise ConnpyError(f&#34;Playbook file not found: {playbook_path}&#34;) if playbook_data.startswith(&#34;---YAML---\n&#34;):
try:
try: content = playbook_data[len(&#34;---YAML---\n&#34;):]
with open(playbook_path, &#34;r&#34;) as f: playbook = yaml.load(content, Loader=yaml.FullLoader)
playbook = yaml.load(f, Loader=yaml.FullLoader) except Exception as e:
except Exception as e: raise ConnpyError(f&#34;Failed to parse YAML content: {e}&#34;)
raise ConnpyError(f&#34;Failed to load playbook {playbook_path}: {e}&#34;) else:
if not os.path.exists(playbook_data):
raise ConnpyError(f&#34;Playbook file not found: {playbook_data}&#34;)
try:
with open(playbook_data, &#34;r&#34;) as f:
playbook = yaml.load(f, Loader=yaml.FullLoader)
except Exception as e:
raise ConnpyError(f&#34;Failed to load playbook {playbook_data}: {e}&#34;)
# Basic validation # Basic validation
if not isinstance(playbook, dict) or &#34;nodes&#34; not in playbook or &#34;commands&#34; not in playbook: if not isinstance(playbook, dict) or &#34;nodes&#34; not in playbook or &#34;commands&#34; not in playbook:
raise ConnpyError(&#34;Invalid playbook format: missing &#39;nodes&#39; or &#39;commands&#39; keys.&#34;) raise ConnpyError(&#34;Invalid playbook format: missing &#39;nodes&#39; or &#39;commands&#39; keys.&#34;)
action = playbook.get(&#34;action&#34;, &#34;run&#34;) action = playbook.get(&#34;action&#34;, &#34;run&#34;)
options = playbook.get(&#34;options&#34;, {})
# Extract all fields similar to RunHandler.cli_run
exec_args = {
&#34;nodes_filter&#34;: playbook[&#34;nodes&#34;],
&#34;commands&#34;: playbook[&#34;commands&#34;],
&#34;variables&#34;: playbook.get(&#34;variables&#34;),
&#34;parallel&#34;: options.get(&#34;parallel&#34;, parallel),
&#34;timeout&#34;: playbook.get(&#34;timeout&#34;, options.get(&#34;timeout&#34;, 10)),
&#34;prompt&#34;: options.get(&#34;prompt&#34;),
&#34;name&#34;: playbook.get(&#34;name&#34;, &#34;Task&#34;)
}
# Map &#39;output&#39; field to folder path if it&#39;s not stdout/null
output_cfg = playbook.get(&#34;output&#34;)
if output_cfg not in [None, &#34;stdout&#34;]:
exec_args[&#34;folder&#34;] = output_cfg
if action == &#34;run&#34;: if action == &#34;run&#34;:
return self.run_commands( return self.run_commands(**exec_args)
nodes_filter=playbook[&#34;nodes&#34;],
commands=playbook[&#34;commands&#34;],
parallel=parallel,
timeout=playbook.get(&#34;timeout&#34;, 10)
)
elif action == &#34;test&#34;: elif action == &#34;test&#34;:
return self.test_commands( exec_args[&#34;expected&#34;] = playbook.get(&#34;expected&#34;, [])
nodes_filter=playbook[&#34;nodes&#34;], return self.test_commands(**exec_args)
commands=playbook[&#34;commands&#34;],
expected=playbook.get(&#34;expected&#34;, []),
parallel=parallel,
timeout=playbook.get(&#34;timeout&#34;, 10)
)
else: else:
raise ConnpyError(f&#34;Unsupported playbook action: {action}&#34;)</code></pre> raise ConnpyError(f&#34;Unsupported playbook action: {action}&#34;)</code></pre>
</details> </details>
<div class="desc"><p>Run a structured Connpy YAML automation playbook.</p></div> <div class="desc"><p>Run a structured Connpy YAML automation playbook (from path or content).</p></div>
</dd> </dd>
<dt id="connpy.services.execution_service.ExecutionService.test_commands"><code class="name flex"> <dt id="connpy.services.execution_service.ExecutionService.test_commands"><code class="name flex">
<span>def <span class="ident">test_commands</span></span>(<span>self,<br>nodes_filter: str,<br>commands: List[str],<br>expected: List[str],<br>variables: Dict[str, Any] | None = None,<br>parallel: int = 10,<br>timeout: int = 10,<br>prompt: str | None = None,<br>on_node_complete: Callable | None = None,<br>logger: Callable | None = None) > Dict[str, Dict[str, bool]]</span> <span>def <span class="ident">test_commands</span></span>(<span>self,<br>nodes_filter: str,<br>commands: List[str],<br>expected: List[str],<br>variables: Dict[str, Any] | None = None,<br>parallel: int = 10,<br>timeout: int = 10,<br>folder: str | None = None,<br>prompt: str | None = None,<br>on_node_complete: Callable | None = None,<br>logger: Callable | None = None,<br>name: str | None = None) > Dict[str, Dict[str, bool]]</span>
</code></dt> </code></dt>
<dd> <dd>
<details class="source"> <details class="source">
@@ -324,9 +375,11 @@ el.replaceWith(d);
variables: Optional[Dict[str, Any]] = None, variables: Optional[Dict[str, Any]] = None,
parallel: int = 10, parallel: int = 10,
timeout: int = 10, timeout: int = 10,
folder: Optional[str] = None,
prompt: Optional[str] = None, prompt: Optional[str] = None,
on_node_complete: Optional[Callable] = None, on_node_complete: Optional[Callable] = None,
logger: Optional[Callable] = None logger: Optional[Callable] = None,
name: Optional[str] = None
) -&gt; Dict[str, Dict[str, bool]]: ) -&gt; Dict[str, Dict[str, bool]]:
&#34;&#34;&#34;Run commands and verify expected output on a set of nodes.&#34;&#34;&#34; &#34;&#34;&#34;Run commands and verify expected output on a set of nodes.&#34;&#34;&#34;
@@ -345,6 +398,7 @@ el.replaceWith(d);
vars=variables, vars=variables,
parallel=parallel, parallel=parallel,
timeout=timeout, timeout=timeout,
folder=folder,
prompt=prompt, prompt=prompt,
on_complete=on_node_complete, on_complete=on_node_complete,
logger=logger logger=logger
@@ -395,7 +449,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.services.import_export_service API documentation</title> <title>connpy.services.import_export_service API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -279,7 +279,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+112 -58
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.services API documentation</title> <title>connpy.services API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -594,7 +594,8 @@ el.replaceWith(d);
folder: Optional[str] = None, folder: Optional[str] = None,
prompt: Optional[str] = None, prompt: Optional[str] = None,
on_node_complete: Optional[Callable] = None, on_node_complete: Optional[Callable] = None,
logger: Optional[Callable] = None logger: Optional[Callable] = None,
name: Optional[str] = None
) -&gt; Dict[str, str]: ) -&gt; Dict[str, str]:
&#34;&#34;&#34;Execute commands on a set of nodes.&#34;&#34;&#34; &#34;&#34;&#34;Execute commands on a set of nodes.&#34;&#34;&#34;
@@ -618,7 +619,15 @@ el.replaceWith(d);
logger=logger logger=logger
) )
return results # Combine output and status for the caller
full_results = {}
for unique in results:
full_results[unique] = {
&#34;output&#34;: results[unique],
&#34;status&#34;: executor.status.get(unique, 1)
}
return full_results
except Exception as e: except Exception as e:
raise ConnpyError(f&#34;Execution failed: {e}&#34;) raise ConnpyError(f&#34;Execution failed: {e}&#34;)
@@ -630,9 +639,11 @@ el.replaceWith(d);
variables: Optional[Dict[str, Any]] = None, variables: Optional[Dict[str, Any]] = None,
parallel: int = 10, parallel: int = 10,
timeout: int = 10, timeout: int = 10,
folder: Optional[str] = None,
prompt: Optional[str] = None, prompt: Optional[str] = None,
on_node_complete: Optional[Callable] = None, on_node_complete: Optional[Callable] = None,
logger: Optional[Callable] = None logger: Optional[Callable] = None,
name: Optional[str] = None
) -&gt; Dict[str, Dict[str, bool]]: ) -&gt; Dict[str, Dict[str, bool]]:
&#34;&#34;&#34;Run commands and verify expected output on a set of nodes.&#34;&#34;&#34; &#34;&#34;&#34;Run commands and verify expected output on a set of nodes.&#34;&#34;&#34;
@@ -651,6 +662,7 @@ el.replaceWith(d);
vars=variables, vars=variables,
parallel=parallel, parallel=parallel,
timeout=timeout, timeout=timeout,
folder=folder,
prompt=prompt, prompt=prompt,
on_complete=on_node_complete, on_complete=on_node_complete,
logger=logger logger=logger
@@ -672,37 +684,52 @@ el.replaceWith(d);
return self.run_commands(nodes_filter, commands, parallel=parallel) return self.run_commands(nodes_filter, commands, parallel=parallel)
def run_yaml_playbook(self, playbook_path: str, parallel: int = 10) -&gt; Dict[str, Any]: def run_yaml_playbook(self, playbook_data: str, parallel: int = 10) -&gt; Dict[str, Any]:
&#34;&#34;&#34;Run a structured Connpy YAML automation playbook.&#34;&#34;&#34; &#34;&#34;&#34;Run a structured Connpy YAML automation playbook (from path or content).&#34;&#34;&#34;
if not os.path.exists(playbook_path): playbook = None
raise ConnpyError(f&#34;Playbook file not found: {playbook_path}&#34;) if playbook_data.startswith(&#34;---YAML---\n&#34;):
try:
try: content = playbook_data[len(&#34;---YAML---\n&#34;):]
with open(playbook_path, &#34;r&#34;) as f: playbook = yaml.load(content, Loader=yaml.FullLoader)
playbook = yaml.load(f, Loader=yaml.FullLoader) except Exception as e:
except Exception as e: raise ConnpyError(f&#34;Failed to parse YAML content: {e}&#34;)
raise ConnpyError(f&#34;Failed to load playbook {playbook_path}: {e}&#34;) else:
if not os.path.exists(playbook_data):
raise ConnpyError(f&#34;Playbook file not found: {playbook_data}&#34;)
try:
with open(playbook_data, &#34;r&#34;) as f:
playbook = yaml.load(f, Loader=yaml.FullLoader)
except Exception as e:
raise ConnpyError(f&#34;Failed to load playbook {playbook_data}: {e}&#34;)
# Basic validation # Basic validation
if not isinstance(playbook, dict) or &#34;nodes&#34; not in playbook or &#34;commands&#34; not in playbook: if not isinstance(playbook, dict) or &#34;nodes&#34; not in playbook or &#34;commands&#34; not in playbook:
raise ConnpyError(&#34;Invalid playbook format: missing &#39;nodes&#39; or &#39;commands&#39; keys.&#34;) raise ConnpyError(&#34;Invalid playbook format: missing &#39;nodes&#39; or &#39;commands&#39; keys.&#34;)
action = playbook.get(&#34;action&#34;, &#34;run&#34;) action = playbook.get(&#34;action&#34;, &#34;run&#34;)
options = playbook.get(&#34;options&#34;, {})
# Extract all fields similar to RunHandler.cli_run
exec_args = {
&#34;nodes_filter&#34;: playbook[&#34;nodes&#34;],
&#34;commands&#34;: playbook[&#34;commands&#34;],
&#34;variables&#34;: playbook.get(&#34;variables&#34;),
&#34;parallel&#34;: options.get(&#34;parallel&#34;, parallel),
&#34;timeout&#34;: playbook.get(&#34;timeout&#34;, options.get(&#34;timeout&#34;, 10)),
&#34;prompt&#34;: options.get(&#34;prompt&#34;),
&#34;name&#34;: playbook.get(&#34;name&#34;, &#34;Task&#34;)
}
# Map &#39;output&#39; field to folder path if it&#39;s not stdout/null
output_cfg = playbook.get(&#34;output&#34;)
if output_cfg not in [None, &#34;stdout&#34;]:
exec_args[&#34;folder&#34;] = output_cfg
if action == &#34;run&#34;: if action == &#34;run&#34;:
return self.run_commands( return self.run_commands(**exec_args)
nodes_filter=playbook[&#34;nodes&#34;],
commands=playbook[&#34;commands&#34;],
parallel=parallel,
timeout=playbook.get(&#34;timeout&#34;, 10)
)
elif action == &#34;test&#34;: elif action == &#34;test&#34;:
return self.test_commands( exec_args[&#34;expected&#34;] = playbook.get(&#34;expected&#34;, [])
nodes_filter=playbook[&#34;nodes&#34;], return self.test_commands(**exec_args)
commands=playbook[&#34;commands&#34;],
expected=playbook.get(&#34;expected&#34;, []),
parallel=parallel,
timeout=playbook.get(&#34;timeout&#34;, 10)
)
else: else:
raise ConnpyError(f&#34;Unsupported playbook action: {action}&#34;)</code></pre> raise ConnpyError(f&#34;Unsupported playbook action: {action}&#34;)</code></pre>
</details> </details>
@@ -743,7 +770,7 @@ el.replaceWith(d);
<div class="desc"><p>Run a plain-text script containing one command per line.</p></div> <div class="desc"><p>Run a plain-text script containing one command per line.</p></div>
</dd> </dd>
<dt id="connpy.services.ExecutionService.run_commands"><code class="name flex"> <dt id="connpy.services.ExecutionService.run_commands"><code class="name flex">
<span>def <span class="ident">run_commands</span></span>(<span>self,<br>nodes_filter: str,<br>commands: List[str],<br>variables: Dict[str, Any] | None = None,<br>parallel: int = 10,<br>timeout: int = 10,<br>folder: str | None = None,<br>prompt: str | None = None,<br>on_node_complete: Callable | None = None,<br>logger: Callable | None = None) > Dict[str, str]</span> <span>def <span class="ident">run_commands</span></span>(<span>self,<br>nodes_filter: str,<br>commands: List[str],<br>variables: Dict[str, Any] | None = None,<br>parallel: int = 10,<br>timeout: int = 10,<br>folder: str | None = None,<br>prompt: str | None = None,<br>on_node_complete: Callable | None = None,<br>logger: Callable | None = None,<br>name: str | None = None) > Dict[str, str]</span>
</code></dt> </code></dt>
<dd> <dd>
<details class="source"> <details class="source">
@@ -760,7 +787,8 @@ el.replaceWith(d);
folder: Optional[str] = None, folder: Optional[str] = None,
prompt: Optional[str] = None, prompt: Optional[str] = None,
on_node_complete: Optional[Callable] = None, on_node_complete: Optional[Callable] = None,
logger: Optional[Callable] = None logger: Optional[Callable] = None,
name: Optional[str] = None
) -&gt; Dict[str, str]: ) -&gt; Dict[str, str]:
&#34;&#34;&#34;Execute commands on a set of nodes.&#34;&#34;&#34; &#34;&#34;&#34;Execute commands on a set of nodes.&#34;&#34;&#34;
@@ -784,58 +812,81 @@ el.replaceWith(d);
logger=logger logger=logger
) )
return results # Combine output and status for the caller
full_results = {}
for unique in results:
full_results[unique] = {
&#34;output&#34;: results[unique],
&#34;status&#34;: executor.status.get(unique, 1)
}
return full_results
except Exception as e: except Exception as e:
raise ConnpyError(f&#34;Execution failed: {e}&#34;)</code></pre> raise ConnpyError(f&#34;Execution failed: {e}&#34;)</code></pre>
</details> </details>
<div class="desc"><p>Execute commands on a set of nodes.</p></div> <div class="desc"><p>Execute commands on a set of nodes.</p></div>
</dd> </dd>
<dt id="connpy.services.ExecutionService.run_yaml_playbook"><code class="name flex"> <dt id="connpy.services.ExecutionService.run_yaml_playbook"><code class="name flex">
<span>def <span class="ident">run_yaml_playbook</span></span>(<span>self, playbook_path: str, parallel: int = 10) > Dict[str, Any]</span> <span>def <span class="ident">run_yaml_playbook</span></span>(<span>self, playbook_data: str, parallel: int = 10) > Dict[str, Any]</span>
</code></dt> </code></dt>
<dd> <dd>
<details class="source"> <details class="source">
<summary> <summary>
<span>Expand source code</span> <span>Expand source code</span>
</summary> </summary>
<pre><code class="python">def run_yaml_playbook(self, playbook_path: str, parallel: int = 10) -&gt; Dict[str, Any]: <pre><code class="python">def run_yaml_playbook(self, playbook_data: str, parallel: int = 10) -&gt; Dict[str, Any]:
&#34;&#34;&#34;Run a structured Connpy YAML automation playbook.&#34;&#34;&#34; &#34;&#34;&#34;Run a structured Connpy YAML automation playbook (from path or content).&#34;&#34;&#34;
if not os.path.exists(playbook_path): playbook = None
raise ConnpyError(f&#34;Playbook file not found: {playbook_path}&#34;) if playbook_data.startswith(&#34;---YAML---\n&#34;):
try:
try: content = playbook_data[len(&#34;---YAML---\n&#34;):]
with open(playbook_path, &#34;r&#34;) as f: playbook = yaml.load(content, Loader=yaml.FullLoader)
playbook = yaml.load(f, Loader=yaml.FullLoader) except Exception as e:
except Exception as e: raise ConnpyError(f&#34;Failed to parse YAML content: {e}&#34;)
raise ConnpyError(f&#34;Failed to load playbook {playbook_path}: {e}&#34;) else:
if not os.path.exists(playbook_data):
raise ConnpyError(f&#34;Playbook file not found: {playbook_data}&#34;)
try:
with open(playbook_data, &#34;r&#34;) as f:
playbook = yaml.load(f, Loader=yaml.FullLoader)
except Exception as e:
raise ConnpyError(f&#34;Failed to load playbook {playbook_data}: {e}&#34;)
# Basic validation # Basic validation
if not isinstance(playbook, dict) or &#34;nodes&#34; not in playbook or &#34;commands&#34; not in playbook: if not isinstance(playbook, dict) or &#34;nodes&#34; not in playbook or &#34;commands&#34; not in playbook:
raise ConnpyError(&#34;Invalid playbook format: missing &#39;nodes&#39; or &#39;commands&#39; keys.&#34;) raise ConnpyError(&#34;Invalid playbook format: missing &#39;nodes&#39; or &#39;commands&#39; keys.&#34;)
action = playbook.get(&#34;action&#34;, &#34;run&#34;) action = playbook.get(&#34;action&#34;, &#34;run&#34;)
options = playbook.get(&#34;options&#34;, {})
# Extract all fields similar to RunHandler.cli_run
exec_args = {
&#34;nodes_filter&#34;: playbook[&#34;nodes&#34;],
&#34;commands&#34;: playbook[&#34;commands&#34;],
&#34;variables&#34;: playbook.get(&#34;variables&#34;),
&#34;parallel&#34;: options.get(&#34;parallel&#34;, parallel),
&#34;timeout&#34;: playbook.get(&#34;timeout&#34;, options.get(&#34;timeout&#34;, 10)),
&#34;prompt&#34;: options.get(&#34;prompt&#34;),
&#34;name&#34;: playbook.get(&#34;name&#34;, &#34;Task&#34;)
}
# Map &#39;output&#39; field to folder path if it&#39;s not stdout/null
output_cfg = playbook.get(&#34;output&#34;)
if output_cfg not in [None, &#34;stdout&#34;]:
exec_args[&#34;folder&#34;] = output_cfg
if action == &#34;run&#34;: if action == &#34;run&#34;:
return self.run_commands( return self.run_commands(**exec_args)
nodes_filter=playbook[&#34;nodes&#34;],
commands=playbook[&#34;commands&#34;],
parallel=parallel,
timeout=playbook.get(&#34;timeout&#34;, 10)
)
elif action == &#34;test&#34;: elif action == &#34;test&#34;:
return self.test_commands( exec_args[&#34;expected&#34;] = playbook.get(&#34;expected&#34;, [])
nodes_filter=playbook[&#34;nodes&#34;], return self.test_commands(**exec_args)
commands=playbook[&#34;commands&#34;],
expected=playbook.get(&#34;expected&#34;, []),
parallel=parallel,
timeout=playbook.get(&#34;timeout&#34;, 10)
)
else: else:
raise ConnpyError(f&#34;Unsupported playbook action: {action}&#34;)</code></pre> raise ConnpyError(f&#34;Unsupported playbook action: {action}&#34;)</code></pre>
</details> </details>
<div class="desc"><p>Run a structured Connpy YAML automation playbook.</p></div> <div class="desc"><p>Run a structured Connpy YAML automation playbook (from path or content).</p></div>
</dd> </dd>
<dt id="connpy.services.ExecutionService.test_commands"><code class="name flex"> <dt id="connpy.services.ExecutionService.test_commands"><code class="name flex">
<span>def <span class="ident">test_commands</span></span>(<span>self,<br>nodes_filter: str,<br>commands: List[str],<br>expected: List[str],<br>variables: Dict[str, Any] | None = None,<br>parallel: int = 10,<br>timeout: int = 10,<br>prompt: str | None = None,<br>on_node_complete: Callable | None = None,<br>logger: Callable | None = None) > Dict[str, Dict[str, bool]]</span> <span>def <span class="ident">test_commands</span></span>(<span>self,<br>nodes_filter: str,<br>commands: List[str],<br>expected: List[str],<br>variables: Dict[str, Any] | None = None,<br>parallel: int = 10,<br>timeout: int = 10,<br>folder: str | None = None,<br>prompt: str | None = None,<br>on_node_complete: Callable | None = None,<br>logger: Callable | None = None,<br>name: str | None = None) > Dict[str, Dict[str, bool]]</span>
</code></dt> </code></dt>
<dd> <dd>
<details class="source"> <details class="source">
@@ -850,9 +901,11 @@ el.replaceWith(d);
variables: Optional[Dict[str, Any]] = None, variables: Optional[Dict[str, Any]] = None,
parallel: int = 10, parallel: int = 10,
timeout: int = 10, timeout: int = 10,
folder: Optional[str] = None,
prompt: Optional[str] = None, prompt: Optional[str] = None,
on_node_complete: Optional[Callable] = None, on_node_complete: Optional[Callable] = None,
logger: Optional[Callable] = None logger: Optional[Callable] = None,
name: Optional[str] = None
) -&gt; Dict[str, Dict[str, bool]]: ) -&gt; Dict[str, Dict[str, bool]]:
&#34;&#34;&#34;Run commands and verify expected output on a set of nodes.&#34;&#34;&#34; &#34;&#34;&#34;Run commands and verify expected output on a set of nodes.&#34;&#34;&#34;
@@ -871,6 +924,7 @@ el.replaceWith(d);
vars=variables, vars=variables,
parallel=parallel, parallel=parallel,
timeout=timeout, timeout=timeout,
folder=folder,
prompt=prompt, prompt=prompt,
on_complete=on_node_complete, on_complete=on_node_complete,
logger=logger logger=logger
@@ -3215,7 +3269,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.services.node_service API documentation</title> <title>connpy.services.node_service API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -760,7 +760,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.services.plugin_service API documentation</title> <title>connpy.services.plugin_service API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -671,7 +671,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.services.profile_service API documentation</title> <title>connpy.services.profile_service API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -429,7 +429,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.services.provider API documentation</title> <title>connpy.services.provider API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -164,7 +164,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.services.sync_service API documentation</title> <title>connpy.services.sync_service API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -964,7 +964,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.services.system_service API documentation</title> <title>connpy.services.system_service API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -325,7 +325,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.tests.conftest API documentation</title> <title>connpy.tests.conftest API documentation</title>
<meta name="description" content="Shared fixtures for connpy tests …"> <meta name="description" content="Shared fixtures for connpy tests …">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -258,7 +258,7 @@ def tmp_config_dir(tmp_path):
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.tests API documentation</title> <title>connpy.tests API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -152,7 +152,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.tests.test_ai API documentation</title> <title>connpy.tests.test_ai API documentation</title>
<meta name="description" content="Tests for connpy.ai module."> <meta name="description" content="Tests for connpy.ai module.">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -1731,7 +1731,7 @@ def myai(self, ai_config, mock_litellm):
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.tests.test_capture API documentation</title> <title>connpy.tests.test_capture API documentation</title>
<meta name="description" content="Tests for connpy.core_plugins.capture"> <meta name="description" content="Tests for connpy.core_plugins.capture">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -245,7 +245,7 @@ def mock_connapp():
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.tests.test_completion API documentation</title> <title>connpy.tests.test_completion API documentation</title>
<meta name="description" content="Tests for connpy.completion module."> <meta name="description" content="Tests for connpy.completion module.">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -257,7 +257,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.tests.test_configfile API documentation</title> <title>connpy.tests.test_configfile API documentation</title>
<meta name="description" content="Tests for connpy.configfile module."> <meta name="description" content="Tests for connpy.configfile module.">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -2005,7 +2005,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.tests.test_connapp API documentation</title> <title>connpy.tests.test_connapp API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -699,7 +699,7 @@ def test_run(mock_run_commands, app):
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.tests.test_core API documentation</title> <title>connpy.tests.test_core API documentation</title>
<meta name="description" content="Tests for connpy.core module — node and nodes classes."> <meta name="description" content="Tests for connpy.core module — node and nodes classes.">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -1369,7 +1369,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.tests.test_execution_service API documentation</title> <title>connpy.tests.test_execution_service API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -142,7 +142,7 @@ Regression: ExecutionService.test_commands currently ignores on_node_complete.</
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.tests.test_grpc_layer API documentation</title> <title>connpy.tests.test_grpc_layer API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -709,7 +709,7 @@ def test_connect_dynamic_msg_formatting_ssm(self, mock_select, mock_read, mock_s
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.tests.test_hooks API documentation</title> <title>connpy.tests.test_hooks API documentation</title>
<meta name="description" content="Tests for connpy.hooks module — MethodHook and ClassHook."> <meta name="description" content="Tests for connpy.hooks module — MethodHook and ClassHook.">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -673,7 +673,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.tests.test_node_service API documentation</title> <title>connpy.tests.test_node_service API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -178,7 +178,7 @@ Regression: connapp._mod calls add_node instead of update_node.</p></div>
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.tests.test_plugins API documentation</title> <title>connpy.tests.test_plugins API documentation</title>
<meta name="description" content="Tests for connpy.plugins module."> <meta name="description" content="Tests for connpy.plugins module.">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -917,7 +917,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.tests.test_printer API documentation</title> <title>connpy.tests.test_printer API documentation</title>
<meta name="description" content="Tests for connpy.printer module."> <meta name="description" content="Tests for connpy.printer module.">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -459,7 +459,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.tests.test_printer_concurrency API documentation</title> <title>connpy.tests.test_printer_concurrency API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -148,7 +148,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.tests.test_profile_service API documentation</title> <title>connpy.tests.test_profile_service API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -192,7 +192,7 @@ Regression: ProfileService currently doesn't resolve inheritance within profiles
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.tests.test_provider API documentation</title> <title>connpy.tests.test_provider API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -139,7 +139,7 @@ el.replaceWith(d);
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.tests.test_sync API documentation</title> <title>connpy.tests.test_sync API documentation</title>
<meta name="description" content="Tests for connpy.services.sync_service"> <meta name="description" content="Tests for connpy.services.sync_service">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -354,7 +354,7 @@ def test_perform_restore(self, mock_remove, mock_dirname, mock_exists, MockZipFi
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>
+2 -2
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5"> <meta name="generator" content="pdoc3 0.11.6">
<title>connpy.tunnels API documentation</title> <title>connpy.tunnels API documentation</title>
<meta name="description" content=""> <meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
@@ -460,7 +460,7 @@ Bridges the blocking gRPC iterators with the async _async_interact_loop.</p></di
</nav> </nav>
</main> </main>
<footer id="footer"> <footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p> <p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.6</a>.</p>
</footer> </footer>
</body> </body>
</html> </html>