def test_that_check_nodeoutput_dump(): cool_output = NodeOutput(dummy_node, "dump_test", int) dump_match = match.match( { "id": criterias.is_type(str) & criterias.regex(uuid_regex) & criterias.equals(str(cool_output.id)), "type": criterias.equals("NodeOutput"), "name": criterias.equals("dump_test"), "output_type": criterias.equals(str(int)), "parent": criterias.is_type(str) & criterias.regex(uuid_regex) & criterias.equals(str(cool_output.node.id)), "value": criterias.equals(None), }, cool_output.dump(), ) print(cool_output.dump()) print(dump_match.to_string()) assert dump_match.is_valid()
def test_that_check_nodeinput_fallback_values(): nice_input = NodeInput(dummy_node, "niceinput", str, False) nice_input.set("This is a fallback value") assert nice_input.get() == "This is a fallback value" str_output = NodeOutput(dummy_node, "stroutput", str) # The famous creator of C++ str_output.set("This is not a fallback value") nice_input.connect(str_output) assert nice_input.get() == "This is not a fallback value"
def on_connect_input(node, input, output): if input.input_type == list: if isinstance(output.output_type[0], dict): for output_name, output_value in output.output_type[0].items(): node.add_output(NodeOutput(node, output_name, output_value)) else: node.add_output( NodeOutput(node, output.name, output.output_type)) del node.outputs["out"]
def test_that_check_nodeinput_dump(): beautiful_input = NodeInput(dummy_node, "dump_test", int) beautiful_input.set(666) ugly_output = NodeOutput(dummy_node, "subdump_test", int) beautiful_input.connect(ugly_output) dump_match = match.match( { "id": criterias.is_type(str) & criterias.regex(uuid_regex) & criterias.equals(str(beautiful_input.id)), "type": criterias.equals("NodeInput"), "name": criterias.equals("dump_test"), "input_type": criterias.equals(str(int)), "parent": criterias.is_type(str) & criterias.regex(uuid_regex) & criterias.equals(str(beautiful_input.node.id)), "value": criterias.equals(666), "hidden": criterias.equals(False), "connected_output": criterias.is_type(str) & criterias.regex(uuid_regex) & criterias.equals(str(ugly_output.id)), }, beautiful_input.dump(), ) print(beautiful_input.dump()) print(dump_match.to_string()) assert dump_match.is_valid()
def test_that_check_nodeinput_connect(): cool_input = NodeInput(dummy_node, "coolinput", str, False) cool_output = NodeOutput(dummy_node, "cooloutput", str) cool_input.connect(cool_output) mean_input = NodeInput(dummy_node, "meaninput", str, True) with pytest.raises(HiddenNodeInputConnectError): mean_input.connect(cool_output)
def test_that_checks_node_dynamic_output_creation(): new_node = dummy_with_chaotic_outputs() new_node.connect_input(power=3) for x in range(22): new_node.add_output(NodeOutput(new_node, x, int)) new_node.trigger() assert new_node[11].get() == 1331
def __init__(self, function: Callable, module: str, name: str, autotrigger: bool): self.id = uuid4() self.function = function self.module = module self.name = name self.flows = [] self.autotrigger = autotrigger self.function_arg_spec = getfullargspec(self.function) self.on = NodeCallbacks() function_inputs = self._find_input_arguments(function) self.inputs = {} for (input_name, input_value) in function_inputs.items(): self.inputs[input_name] = self._build_node_input( input_name, input_value) self.args_inputs, self.kwargs_inputs = [], {} self.allow_args = self.function_arg_spec.varargs is not None self.allow_kwargs = self.function_arg_spec.varkw is not None self.outputs = { key: NodeOutput(self, key, output_type) for key, output_type in self._build_return_types().items() } self.is_aware = False self.origin = self if "self" in self.inputs: self.is_aware = True self.delay = 0 self.retries = 0 self.trigger_log = {"success": 0, "failure": 0, "trigger": 0}
def test_copy_scenario(): outside_node = dummy_node() dummy = dummy_node_with_convenient_outputs() dummy2 = dummy_with_inputs_node() dummy2.connect_input(a=dummy[0], b=dummy[1], c=NodeOutput(outside_node, "weird", int)) dummy3 = very_dummy_node() dummy4 = dumb_autotrigger_node() dummy5 = dumb_autotrigger_node() dummy6 = dummy_with_args_and_kwargs() dummy6.connect_input(dummy4, x=dummy5) dummy2.connect_flow(dummy3) dummy3.connect_flow(dummy6) scenario_copy = copy_scenario_state(dummy2) assert dummy2.id == scenario_copy.id assert len(dummy2.flows) == len(scenario_copy.flows)
def test_callback_copy(): logs = [] def on_add_output_callback(node, node_output): node.mirror.add_output(node_output) def mirror_on_add_output_callback(node, node_output): logs.append(f"add_output({node.id}, {node_output.name})") def mirror_on_after_flow_callback(node, flow): logs.append(f"after_flow({node.id}, {flow.name})") def mirror_on_before_flow_callback(node, flow): logs.append(f"before_flow({node.id}, {flow.name})") def on_connect_flow_callback(node, flow): node.mirror.connect_flow(flow.node, flow.name) node.mirror.get_flow(flow.name).priority = flow.priority def mirror_on_connect_flow_callback(node, flow): logs.append(f"connect_flow({node.id}, {flow.name})") def on_connect_input_callback(node, node_input, node_output): kwargs = {node_input.name: node_output} node.mirror.connect_input(**kwargs) def mirror_on_connect_input_callback(node, node_input, node_output): logs.append( f"connect_input({node.id}, {node_input.name}, {node_output.name})") def mirror_on_flow_failure_callback(node, flow, exception): logs.append(f"flow_failure({node.id}, {flow.name}, {exception})") def on_set_input_value_callback(node, node_input, value): on_connect_input_callback(node, node_input, value) def mirror_on_set_input_value_callback(node, node_input, value): logs.append(f"set_input_value({node.id}, {node_input.name}, {value})") def on_trigger_callback(node): node.mirror.trigger() def mirror_on_trigger_callback(node): logs.append(f"trigger({node.id})") def mirror_on_trigger_input_callback(node, node_input, triggered_node): logs.append( f"trigger_input({node.id}, {node_input.name}, {triggered_node.id})" ) original = extensible_node() original.id = "original" original.on.add_output.add(on_add_output_callback, mirror_on_add_output_callback) original.on.after_flow.add(mirror_on_after_flow_callback) original.on.before_flow.add(mirror_on_before_flow_callback) original.on.connect_flow.add(on_connect_flow_callback, mirror_on_connect_flow_callback) original.on.connect_input.add(on_connect_input_callback, mirror_on_connect_input_callback) original.on.flow_failure.add(mirror_on_flow_failure_callback) original.on.set_input_value.add(on_set_input_value_callback, mirror_on_set_input_value_callback) original.on.trigger.add(on_trigger_callback, mirror_on_trigger_callback) original.on.trigger_input.add(mirror_on_trigger_input_callback) original.mirror = extensible_node() original.mirror.id = "mirror" original.mirror.on = original.on.copy() original.mirror.on.add_output = mirror_on_add_output_callback original.mirror.on.connect_flow = mirror_on_connect_flow_callback original.mirror.on.connect_input = mirror_on_connect_input_callback original.mirror.on.set_input_value = mirror_on_set_input_value_callback original.mirror.on.trigger = mirror_on_trigger_callback next_step = null_node() original.connect_flow(next_step) autotrigger_step = dummy_data_node() autotrigger_step.id = "dummy" original.connect_input(d=autotrigger_step) fail_step = format_exception_node() fail_step.connect_input(exception_name="FakeError", string="This is a fake error") original.connect_flow(fail_step) original.connect_input(a=1, b=2, c=3) original.add_output(NodeOutput(original, "e", int)) original.trigger() assert original["out"].get() == 666 and original.mirror["out"].get() == 666 assert original["e"].get() == 28 and original.mirror["e"].get() == 28 assert logs == [ "connect_flow(mirror, 0)", "connect_flow(original, 0)", "connect_input(mirror, d, out)", "connect_input(original, d, out)", "connect_flow(mirror, 1)", "connect_flow(original, 1)", "set_input_value(mirror, a, 1)", "set_input_value(original, a, 1)", "set_input_value(mirror, b, 2)", "set_input_value(original, b, 2)", "set_input_value(mirror, c, 3)", "set_input_value(original, c, 3)", "add_output(mirror, e)", "add_output(original, e)", "trigger(mirror)", "trigger_input(mirror, d, dummy)", "before_flow(mirror, 0)", "after_flow(mirror, 0)", "before_flow(mirror, 1)", "flow_failure(mirror, 1, This is a fake error)", "after_flow(mirror, 1)", "trigger(original)", "trigger_input(original, d, dummy)", "before_flow(original, 0)", "after_flow(original, 0)", "before_flow(original, 1)", "flow_failure(original, 1, This is a fake error)", "after_flow(original, 1)", ]
def on_connect_input(node, input, output): for output_name, output_value in output.output_type.items(): node.add_output(NodeOutput(node, output_name, output_value))
def test_that_checks_multiple_nodeoutput_types(): versatile_output = NodeOutput(dummy_node, "versatile_output", [int]) versatile_output.set([1, 2, 3, 4]) assert versatile_output.get()[0] == 1 assert versatile_output.get()[1] == 2 assert versatile_output.get()[2] == 3 assert versatile_output.get()[3] == 4 beautiful_output = NodeOutput( dummy_node, "beautiful_output", { "a": [int], "b": { "c": [[int]] }, "d": [{ "e": str }] }, ) beautiful_output.set({ "a": [44], "b": { "c": [[22]] }, "d": [{ "e": "hello" }, { "e": "goodbye" }] }) assert beautiful_output.get()["a"][0] == 44 assert beautiful_output.get()["b"]["c"][0][0] == 22 assert beautiful_output.get()["d"][0]["e"] == "hello" assert beautiful_output.get()["d"][1]["e"] == "goodbye"
def test_that_check_nodeoutput_repr(): cooler_output = NodeOutput(dummy_node, "acoolname", str) assert str( cooler_output) == "Output[acoolname](type=<class 'str'>, value=None)"
def test_that_check_nodeoutput_value_getter(): str_output = NodeOutput(dummy_node, "str_output", str) str_output.set("Strange string") assert str_output.get() == "Strange string"
def test_that_check_nodeoutput_typecheck(): int_output = NodeOutput(dummy_node, "int_output", int) with pytest.raises(InvalidNodeOutputTypeError): int_output.set("hello") int_output.set(22) any_output = NodeOutput(dummy_node, "any_output", Any()) any_output.set(lambda x: x) any_output.set(11) any_output.set("It works with anything") sumtype_output = NodeOutput(dummy_node, "none_output", SumType(bool, str)) sumtype_output.set(True) sumtype_output.set("Goodbye") with pytest.raises(InvalidNodeOutputTypeError): sumtype_output.set(22)
def test_typing_in_node_output(): deprecated_output = NodeOutput(dummy_node, "deprecated_output", typing.Optional[int]) deprecated_output.set(22)
def test_that_checks_invalid_output_type(): wrong_output = NodeOutput(dummy_node, "wrong_output", [str]) with pytest.raises(InvalidNodeOutputTypeError): wrong_output.set([22]) wrong_output2 = NodeOutput(dummy_node, "wrong_output2", {"a": 1}) with pytest.raises(RuntimeError): wrong_output2.set({"a": "no"}) wrong_output3 = NodeOutput(dummy_node, "wrong_output3", [1]) with pytest.raises(RuntimeError): wrong_output3.set(["yes"])