def test_string_parse_e2e_multiword3(type_context): fooType = AInixType(type_context, "FooType") fo = AInixObject( type_context, "fo", "FooType", [], preferred_object_parser_name=create_object_parser_from_grammar( type_context, "fooname", '"foo"').name) twoargs = AInixObject(type_context, "FooProgram", "Program", [ AInixArgument(type_context, "a", None, arg_data={"short_name": "a"}, parent_object_name="sdf"), AInixArgument(type_context, "barg", None, arg_data={"short_name": "b"}, parent_object_name="bw"), _make_positional() ], type_data={"invoke_name": "hello"}) type_context.finalize_data() parser = StringParser(type_context) ast = parser.create_parse_tree("hello -a", "CommandSequence") unparser = AstUnparser(type_context) to_string = unparser.to_string(ast) assert to_string.total_string == "hello -a"
def _create_root_types(type_context: TypeContext): """Creates the underlying types for handling generid strings""" AInixType(type_context, WORD_PART_TYPE_NAME, WORD_PART_TYPE_PARSER_NAME) AInixObject(type_context, WORD_PART_TERMINAL_NAME, WORD_PART_TYPE_NAME) _create_modifier_types(type_context) AInixType(type_context, WORD_TYPE_NAME) # Create a word which cannot be empty str parts = AInixArgument(type_context, "parts", WORD_PART_TYPE_NAME, required=True) def non_empty_word_parser(run: parse_primitives.ObjectParserRun, string: str, result: parse_primitives.ObjectParserResult): if string == "": raise AInixParseError("Expect a non-empty word") deleg = yield run.left_fill_arg(parts, (0, len(string))) result.accept_delegation(deleg) def unparser(arg_map: parse_primitives.ObjectNodeArgMap, result: parse_primitives.ObjectToStringResult): result.add_arg_tostring(parts) parser = ObjectParser(type_context, "non_empty_word_parser", non_empty_word_parser, unparser) AInixObject(type_context, WORD_OBJ_NAME, WORD_TYPE_NAME, [parts], parser.name)
def test_dfs_in_set(): tc = get_toy_strings_context() footype = AInixType(tc, "footype") bartype = AInixType(tc, "bartype") arg1 = AInixArgument(tc, "arg1", "bartype", required=True) foo_object = AInixObject(tc, "foo_object", "footype", [arg1]) bar_object = AInixObject(tc, "bar_object", "bartype") other_bar_obj = AInixObject(tc, "other_bar_ob", "bartype") # arg_choice = ObjectChoiceNode(bartype) ob_chosen = ObjectNode(bar_object) arg_choice.set_choice(ob_chosen) instance = ObjectNode(foo_object) instance.set_arg_value("arg1", arg_choice) ast = ObjectChoiceNode(footype) ast.set_choice(instance) # ast_set = AstObjectChoiceSet(footype) ast_set.add(ast, True, 1, 1) path = [pointer.cur_node for pointer in list(ast.depth_first_iter())] assert path == [ast, instance, arg_choice, ob_chosen] result = list(depth_first_iterate_ast_set_along_path(ast_set, path)) assert len(result) == len(path) assert isinstance(result[0], AstObjectChoiceSet) assert result[0].type_to_choose == footype assert isinstance(result[1], ObjectNodeSet) assert result[1].implementation == foo_object assert isinstance(result[2], AstObjectChoiceSet) assert result[2].type_to_choose == bartype assert isinstance(result[3], ObjectNodeSet) assert result[3].implementation == bar_object
def test_string_parse_e2e_multiword2(type_context): fooType = AInixType(type_context, "FooType") fo = AInixObject( type_context, "fo", "FooType", [], preferred_object_parser_name=create_object_parser_from_grammar( type_context, "fooname", '"foo bar"').name) twoargs = AInixObject(type_context, "FooProgram", "Program", [ AInixArgument(type_context, "a", None, arg_data={"short_name": "a"}, parent_object_name="sdf"), AInixArgument(type_context, "p1", "FooType", arg_data={ POSITION: 0, MULTIWORD_POS_ARG: True }, parent_object_name="sdf") ], type_data={"invoke_name": "hello"}) type_context.finalize_data() parser = StringParser(type_context) ast = parser.create_parse_tree("hello foo bar -a", "Program") unparser = AstUnparser(type_context) to_string = unparser.to_string(ast) assert to_string.total_string == "hello -a foo bar"
def test_make_copy_optional_arg(): tc = TypeContext() ft = AInixType(tc, "ft") bt = AInixType(tc, "bt") arg1 = AInixArgument(tc, "arg1", "bt", required=False, parent_object_name="fo") fo = AInixObject( tc, "fo", "ft", [arg1], preferred_object_parser_name=create_object_parser_from_grammar( tc, "masfoo_parser", '"foo" arg1?').name) bo = AInixObject( tc, "bo", "bt", None, preferred_object_parser_name=create_object_parser_from_grammar( tc, "masdfo_parser", '"bar"').name) tc.finalize_data() parser = StringParser(tc) unparser = AstUnparser(tc) ast = parser.create_parse_tree("foobar", "ft") tokenizer = SpaceTokenizer() in_str = "Hello bar sdf cow" tokens, metadata = tokenizer.tokenize(in_str) unpar_res = unparser.to_string(ast) assert unpar_res.total_string == "foobar" result = make_copy_version_of_tree(ast, unparser, metadata) assert result.next_node_not_copy.get_choice_node_for_arg( "arg1").copy_was_chosen
def latent_store_stuff() -> Tuple[LatentStore, TypeContext, List[Tuple[ int, int, AstObjectChoiceSet]]]: torch.manual_seed(1) tc = TypeContext() ft = AInixType(tc, "FT") fo1 = AInixObject(tc, "FO1", "FT") fo2 = AInixObject(tc, "FO2", "FT") fo3 = AInixObject(tc, "FO3", "FT") bt = AInixType(tc, "BT") bo1 = AInixObject(tc, "BO1", "BT") AInixObject(tc, "BO2", "BT") tc.finalize_data() builder = TorchLatentStore.get_builder(tc.get_type_count(), 3) valid_choices = [] oc = ObjectChoiceNode(ft, ObjectNode(fo1)) builder.add_example(0, oc) s1 = AstObjectChoiceSet(ft) s1.add(oc, True, 1, 1) valid_choices.append((0, 0, s1)) oc = ObjectChoiceNode(ft, ObjectNode(fo2)) builder.add_example(1, oc) s1 = AstObjectChoiceSet(ft) s1.add(oc, True, 1, 1) valid_choices.append((1, 0, s1)) builder.add_example(2, ObjectChoiceNode(ft, ObjectNode(fo3))) return builder.produce_result(), tc, valid_choices
def test_pointer_change_here(freeze_first): """Test an arg change""" # Establish types tc = TypeContext() AInixType(tc, "footype") bartype = AInixType(tc, "bartype") arg1 = AInixArgument(tc, "arg1", "bartype", required=True) foo_object = AInixObject(tc, "foo_object", "footype", [arg1]) bar_object = AInixObject(tc, "bar_object", "bartype") other_bar_obj = AInixObject(tc, "other_bar_ob", "bartype") # Make an ast arg_choice = ObjectChoiceNode(bartype) ob_chosen = ObjectNode(bar_object) arg_choice.set_choice(ob_chosen) instance = ObjectNode(foo_object) instance.set_arg_value("arg1", arg_choice) if freeze_first: instance.freeze() # Try change deepest = list(instance.depth_first_iter())[-1] assert deepest.cur_node == ob_chosen new_node = ObjectNode(other_bar_obj) new_point = deepest.change_here(new_node) assert new_point.cur_node == new_node assert new_point.cur_node.is_frozen == freeze_first
def test_string_parse_e2e_pos_unparse(type_context): fooType = AInixType(type_context, "FooType") fo = AInixObject( type_context, "fo", "FooType", [], preferred_object_parser_name=create_object_parser_from_grammar( type_context, "fooname", '"foo"').name) twoargs = AInixObject(type_context, "FooProgram", "Program", [ AInixArgument(type_context, "p1", "FooType", arg_data={ POSITION: 0, MULTIWORD_POS_ARG: False }, parent_object_name="bw", required=True) ], type_data={"invoke_name": "hello"}) type_context.finalize_data() parser = StringParser(type_context) ast = parser.create_parse_tree("hello foo", "Program") unparser = AstUnparser(type_context) unparse_result = unparser.to_string(ast) assert unparse_result.total_string == "hello foo" for p in ast.depth_first_iter(): n = p.cur_node if isinstance(n, ObjectChoiceNode) and n.type_to_choose.name == "FooType": arg_node_pointer = p break assert unparse_result.pointer_to_string(arg_node_pointer) == "foo"
def test_objectnode_copy_simple_with_arg(): """Copy with an arg""" # Establish types tc = TypeContext() AInixType(tc, "footype") bartype = AInixType(tc, "bartype") arg1 = AInixArgument(tc, "arg1", "bartype", required=True) foo_object = AInixObject(tc, "foo_object", "footype", [arg1]) bar_object = AInixObject(tc, "bar_object", "bartype") # Make an ast arg_choice = ObjectChoiceNode(bartype) ob_chosen = ObjectNode(bar_object) arg_choice.set_choice(ob_chosen) instance = ObjectNode(foo_object) instance.set_arg_value("arg1", arg_choice) # Do the tests: # Unfrozen clone, leaf = instance.path_clone() assert id(clone) != id(instance) assert leaf is None # with a path clone, leaf = instance.path_clone([instance]) assert id(clone) != id(instance) assert leaf.cur_node == clone assert leaf.parent is None # with a deep path clone, leaf = instance.path_clone([instance, arg_choice]) assert id(clone) != id(instance) assert leaf.cur_node.choice is None # with a deeper path clone, leaf = instance.path_clone([instance, arg_choice, ob_chosen]) assert id(clone) != id(instance) assert clone == instance assert leaf.cur_node == ob_chosen assert leaf.parent.cur_node.choice == ob_chosen
def test_objectnode_copy_with_child(): """Copy with an arg""" # Establish types tc = TypeContext() AInixType(tc, "footype") bartype = AInixType(tc, "bartype") arg1 = AInixArgument(tc, "arg1", "bartype", parent_object_name="foo_object") foo_object = AInixObject(tc, "foo_object", "footype", [arg1]) bar_object = AInixObject(tc, "bar_object", "bartype") # Make an ast fin_choice = ObjectNode(bar_object) is_pres = ObjectChoiceNode(bartype) is_pres.set_choice(fin_choice) arg_node = ObjectNode(arg1.is_present_object) arg_node.set_arg_value(OPTIONAL_ARGUMENT_NEXT_ARG_NAME, is_pres) is_pres_top = ObjectChoiceNode(arg1.present_choice_type) is_pres_top.set_choice(arg_node) instance = ObjectNode(foo_object) instance.set_arg_value("arg1", is_pres_top) # Do the tests: # Unfrozen clone, leaf = instance.path_clone() assert id(clone) != id(instance) assert leaf is None # Freeze part is_pres_top.freeze() clone, leaf = instance.path_clone() assert id(clone) != id(instance) assert not clone.is_frozen assert clone == instance assert id(clone.get_choice_node_for_arg("arg1")) == id(is_pres_top) # Freeze all instance.freeze() clone, leaf = instance.path_clone() assert id(clone) == id(instance) assert clone == instance assert id(clone.get_choice_node_for_arg("arg1")) == id(is_pres_top) # Full unfreeze path clone, leaf = instance.path_clone( [instance, is_pres_top, arg_node, is_pres, fin_choice]) assert id(clone) != id(instance) assert not clone.is_frozen assert clone == instance assert leaf.get_nodes_to_here() == [ instance, is_pres_top, arg_node, is_pres, fin_choice ] # Partial unfreeze path (stop early) clone, leaf = instance.path_clone([instance, is_pres_top, arg_node]) assert id(clone) != id(instance) assert not clone.is_frozen assert clone != instance path = leaf.get_nodes_to_here() assert len(path) == 3 new_arg_node: ObjectNode = leaf.cur_node assert new_arg_node.get_choice_node_for_arg( OPTIONAL_ARGUMENT_NEXT_ARG_NAME) is None
def test_parse_set_optional(): """Manually build up an ast, and make sure the ast set is representing optional args correctly.""" tc = TypeContext() foo_type = AInixType(tc, "FooType") test_arg = AInixArgument(tc, "test_arg", "FooType", parent_object_name="foo_ob") foo_ob = AInixObject(tc, "foo_ob", "FooType", [test_arg]) ast_set = AstObjectChoiceSet(foo_type, None) ast = ObjectChoiceNode(foo_type) next_o = ObjectNode(foo_ob) ast.set_choice(next_o) arg_choice_node = ObjectChoiceNode(test_arg.present_choice_type) arg_choice_node.set_choice(ObjectNode(test_arg.not_present_object)) next_o.set_arg_value("test_arg", arg_choice_node) ast.freeze() ast_set.add(ast, True, 1, 1) data = ast_set._impl_name_to_data["foo_ob"].next_node.get_arg_set_data( next_o.as_childless_node()) assert data is not None assert data.arg_to_choice_set["test_arg"].type_to_choose_name == \ test_arg.present_choice_type.name
def test_string_parse_e2e_sequence(type_context): twoargs = AInixObject(type_context, "FooProgram", "Program", [ AInixArgument(type_context, "a", None, arg_data={"short_name": "a"}, parent_object_name="sdf"), AInixArgument(type_context, "barg", None, arg_data={"short_name": "b"}, parent_object_name="bw") ], type_data={"invoke_name": "hello"}) parser = StringParser(type_context) unparser = AstUnparser(type_context) string = "hello -a | hello -b" ast = parser.create_parse_tree(string, "CommandSequence") to_string = unparser.to_string(ast) assert to_string.total_string == string no_space = "hello -a|hello -b" ast = parser.create_parse_tree(no_space, "CommandSequence") to_string = unparser.to_string(ast) assert to_string.total_string == string string = "hello -a | hello" ast = parser.create_parse_tree(string, "CommandSequence") to_string = unparser.to_string(ast) assert to_string.total_string == string
def test_objectnode_copy_simple(): """Copy with no children""" tc = TypeContext() AInixType(tc, "footype") foo_object = AInixObject(tc, "foo_object", "footype") instance = ObjectNode(foo_object) # Unfrozen clone, path = instance.path_clone() assert id(clone) != id(instance) assert clone.implementation == foo_object assert instance == clone assert path is None # Frozen instance.freeze() clone, path = instance.path_clone() assert id(clone) == id(instance) assert clone == instance assert path is None assert clone.is_frozen # Frozen but on unfreeze path clone, path = instance.path_clone([instance]) assert id(clone) != id(instance) assert instance == clone assert clone.implementation == foo_object assert not clone.is_frozen
def test_prog_object_parser_posarg_multword_optional_not_present(type_context): argval = AInixObject(type_context, "FooProgram", "Program", [_make_positional(required=False, multiword=True)]) parser = type_context.get_object_parser_by_name("ProgramObjectParser") result = gen_result(parser.parse_string("", argval)) assert result.get_arg_present("p1") is None assert result.remaining_start_i == len("")
def test_prog_object_parser_posarg_multword_and_nonpos2(type_context): argval = AInixObject( type_context, "FooProgram", "Program", [_make_positional(required=True, multiword=True), _make_flag("a")]) parser = type_context.get_object_parser_by_name("ProgramObjectParser") result = gen_result(parser.parse_string("hello -a", argval)) assert result.get_arg_present("p1") is not None assert result.get_arg_present("p1").slice_string == "hello" assert result.get_arg_present("a") is not None
def test_prog_object_tostring_basic_with_type(type_context): a_arg = AInixArgument(type_context, "a", "Program", arg_data={"short_name": "a"}, parent_object_name="sdf") onearg = AInixObject(type_context, "FooProgram", "Program", [a_arg]) parser = type_context.get_object_parser_by_name("ProgramObjectParser") # Unparse unparse = parser.to_string(ObjectNodeArgMap(onearg, {"a": True})) assert unparse.unparse_seq == ["-a", " ", ArgToStringDelegation(a_arg)]
def test_prog_type_parser(type_context): instance = type_context.get_type_parser_by_name("ProgramTypeParser") AInixObject(type_context, "FooProgram", "Program", [], type_data={"invoke_name": "foo"}) AInixObject(type_context, "BarProgram", "Program", [], type_data={"invoke_name": "bar"}) result = gen_result(instance.parse_string("foo -rm df")) assert result.get_implementation().name == "FooProgram" assert result.get_next_string() == "-rm df" result = gen_result(instance.parse_string("bar boop do")) assert result.get_implementation().name == "BarProgram" assert result.get_next_string() == "boop do" # Try a program which doesn't exist and get error with pytest.raises(AInixParseError): result = gen_result(instance.parse_string("baz bdsf do"))
def test_prog_object_parser_basic(type_context): onearg = AInixObject(type_context, "FooProgram", "Program", [ AInixArgument(type_context, "a", None, arg_data={"short_name": "a"}, parent_object_name="sdf") ]) parser = type_context.get_object_parser_by_name("ProgramObjectParser") result = gen_result(parser.parse_string("-a", onearg)) assert result.get_arg_present("a") is not None assert result.get_arg_present("a").slice_string == ""
def test_prog_object_parser_posarg(type_context): fooType = AInixType(type_context, "FooType") argval = AInixObject(type_context, "FooProgram", "Program", [ AInixArgument(type_context, "p1", fooType.name, arg_data={POSITION: 0}, required=True) ]) parser = type_context.get_object_parser_by_name("ProgramObjectParser") result = gen_result(parser.parse_string("hello", argval)) assert result.get_arg_present("p1") is not None assert result.get_arg_present("p1").slice_string == "hello"
def basic_classify_tc(base_tc): tc = base_tc AInixType(tc, "FooBarBazType", default_type_parser_name="max_munch_type_parser") for word in ("foo", "baz", "bar", "pop"): AInixObject( tc, word, "FooBarBazType", preferred_object_parser_name=create_object_parser_from_grammar( tc, f"par{word}", f'"{word}"').name) return tc
def test_prog_object_parser_argval(type_context): fooType = AInixType(type_context, "FooType") argval = AInixObject(type_context, "FooProgram", "Program", [ AInixArgument(type_context, "a", fooType.name, arg_data={"short_name": "a"}, parent_object_name="sdf") ]) parser = type_context.get_object_parser_by_name("ProgramObjectParser") result = gen_result(parser.parse_string("-a hello", argval)) assert result.get_arg_present("a") is not None assert result.get_arg_present("a").slice_string == "hello" assert result.remaining_start_i == len("-a hello")
def test_prog_object_parser_argval_combined_style(type_context): fooType = AInixType(type_context, "FooType") argval = AInixObject(type_context, "FooProgram", "Program", [ AInixArgument(type_context, "a", fooType.name, arg_data={"short_name": "a"}, parent_object_name="sdf") ]) parser = type_context.get_object_parser_by_name("ProgramObjectParser") # Combined style result = gen_result(parser.parse_string("-afoo", argval)) assert result.get_arg_present("a") is not None assert result.get_arg_present("a").slice_string == "foo"
def test_only_one_option(base_type_context): # Create some types foo_type = AInixType(base_type_context, "FooType") AInixObject(base_type_context, "FooObj", "FooType") base_type_context.finalize_data() # Create an index index = ExamplesIndex(base_type_context, ExamplesIndex.get_default_ram_backend()) index.add_yset_default_weight(["example"], ["y"], index.DEFAULT_X_TYPE, "FooType") # Create a expected value parser = StringParser(base_type_context) expected = parser.create_parse_tree("string", foo_type.name) # Predict model = make_rulebased_seacr(index) prediction = model.predict("example", "FooType", False) assert expected == prediction
def basic_string_tc(basic_classify_tc): tc = basic_classify_tc AInixType(tc, "FooStringType") lhsArg = AInixArgument(tc, "lhs", "FooBarBazType", required=True, parent_object_name="wer") rhsArg = AInixArgument(tc, "rhs", "FooStringType", required=False, parent_object_name="sdf") AInixObject(tc, "foo_string", "FooStringType", [lhsArg, rhsArg], preferred_object_parser_name=create_object_parser_from_grammar( tc, "itasdf", 'lhs (" " rhs)?').name) return tc
def test_prog_object_parser_twoargs(type_context): twoargs = AInixObject(type_context, "FooProgram", "Program", [ AInixArgument(type_context, "a", None, arg_data={SHORT_NAME: "a"}, parent_object_name="sfd"), AInixArgument(type_context, "barg", None, arg_data={SHORT_NAME: "b"}, parent_object_name="sfd") ]) parser = type_context.get_object_parser_by_name("ProgramObjectParser") result = gen_result(parser.parse_string("-a -b", twoargs)) assert result.get_arg_present("a") is not None assert result.get_arg_present("barg") is not None result = gen_result(parser.parse_string("-b", twoargs)) assert result.get_arg_present("a") is None assert result.get_arg_present("barg") is not None
def test_add_arg(): mock_context = MagicMock() obj = AInixObject(mock_context, "FooObj", "footype", [ AInixArgument( mock_context, "FooArg", None, parent_object_name="FooObj") ]) test_string = "test string" result = ObjectParserResult(obj, test_string) # Invalid arg with pytest.raises(Exception): result.set_arg_present("badname", 0, 4) with pytest.raises(Exception): result.get_arg_present("badname") # Valid arg result.set_arg_present("FooArg", 0, 4) data = result.get_arg_present("FooArg") assert data is not None assert data.slice == (0, 4) assert data.slice_string == test_string[0:4] assert result.remaining_start_i == 4
def test_prog_object_parser_2posarg_multword_end(type_context): fooType = AInixType(type_context, "FooType") argval = AInixObject(type_context, "FooProgram", "Program", [ AInixArgument(type_context, "p1", fooType.name, arg_data={POSITION: 0}, required=True), AInixArgument(type_context, "p2", fooType.name, arg_data={ POSITION: 1, MULTIWORD_POS_ARG: True }, required=True) ]) parser = type_context.get_object_parser_by_name("ProgramObjectParser") result = gen_result(parser.parse_string("hello yo there woo", argval)) assert result.get_arg_present("p1") is not None assert result.get_arg_present("p1").slice_string == "hello" assert result.get_arg_present("p2") is not None assert result.get_arg_present("p2").slice_string == "yo there woo"
def test_multi_copy(): tc = TypeContext() loader.load_path(f"builtin_types/generic_parsers.ainix.yaml", tc, up_search_limit=3) ft = AInixType(tc, "ft") bt = AInixType(tc, "bt", default_type_parser_name="max_munch_type_parser") arg1 = AInixArgument(tc, "lhs", "bt", required=True, parent_object_name="fo") arg2 = AInixArgument(tc, "right", "bt", required=True, parent_object_name="sg") fo = AInixObject( tc, "fo", "ft", [arg1, arg2], preferred_object_parser_name=create_object_parser_from_grammar( tc, "mp", 'lhs right').name) bfoo = AInixObject( tc, "bfoo", "bt", None, preferred_object_parser_name=create_object_parser_from_grammar( tc, "masdfo_parser", '"foo"').name) bbar = AInixObject( tc, "bbar", "bt", None, preferred_object_parser_name=create_object_parser_from_grammar( tc, "mdf", '"bar"').name) tc.finalize_data() parser = StringParser(tc) unparser = AstUnparser(tc) ast = parser.create_parse_tree("foofoo", "ft") tokenizer = SpaceTokenizer() in_str = "Hello foo" tokens, metadata = tokenizer.tokenize(in_str) unpar_res = unparser.to_string(ast) assert unpar_res.total_string == "foofoo" cset = AstObjectChoiceSet(ft) cset.add(ast, True, 1, 1) assert cset.is_node_known_valid(ast) add_copies_to_ast_set(ast, cset, unparser, metadata) copy_left = ObjectChoiceNode( ft, ObjectNode( fo, pmap({ "lhs": ObjectChoiceNode(bt, CopyNode(bt, 1, 1)), "right": ObjectChoiceNode(bt, ObjectNode(bfoo, pmap())) }))) assert cset.is_node_known_valid(copy_left) copy_right = ObjectChoiceNode( ft, ObjectNode( fo, pmap({ "lhs": ObjectChoiceNode(bt, ObjectNode(bfoo, pmap())), "right": ObjectChoiceNode(bt, CopyNode(bt, 1, 1)) }))) assert cset.is_node_known_valid(copy_right) copy_both = ObjectChoiceNode( ft, ObjectNode( fo, pmap({ "lhs": ObjectChoiceNode(bt, CopyNode(bt, 1, 1)), "right": ObjectChoiceNode(bt, CopyNode(bt, 1, 1)) }))) assert cset.is_node_known_valid(copy_both)
def test_prog_object_parser_nocrash(type_context): noargs = AInixObject(type_context, "FooProgram", "Program", []) instance = type_context.get_object_parser_by_name("ProgramObjectParser") instance.parse_string("", noargs)
def test_objectnode_copy_with_2children(): """Copypasta of the above test, just with an extra arg thrown in""" # Establish types tc = TypeContext() AInixType(tc, "footype") bartype = AInixType(tc, "bartype") arg1 = AInixArgument(tc, "arg1", "bartype", parent_object_name="foo_obj") arg2 = AInixArgument(tc, "arg2", "bartype", parent_object_name="bar_obj") foo_object = AInixObject(tc, "foo_object", "footype", [arg1, arg2]) bar_object = AInixObject(tc, "bar_object", "bartype") # Make an ast fin_choice = ObjectNode(bar_object) is_pres = ObjectChoiceNode(bartype) is_pres.set_choice(fin_choice) arg_node = ObjectNode(arg1.is_present_object) arg_node.set_arg_value(OPTIONAL_ARGUMENT_NEXT_ARG_NAME, is_pres) is_pres_top = ObjectChoiceNode(arg1.present_choice_type) is_pres_top.set_choice(arg_node) instance = ObjectNode(foo_object) instance.set_arg_value("arg1", is_pres_top) fin_choice2 = ObjectNode(bar_object) is_pres2 = ObjectChoiceNode(bartype) is_pres2.set_choice(fin_choice2) arg_node2 = ObjectNode(arg2.is_present_object) arg_node2.set_arg_value(OPTIONAL_ARGUMENT_NEXT_ARG_NAME, is_pres2) is_pres_top2 = ObjectChoiceNode(arg2.present_choice_type) is_pres_top2.set_choice(arg_node2) instance.set_arg_value("arg2", is_pres_top2) # Do the tests: # Unfrozen clone, leaf_pointer = instance.path_clone() assert id(clone) != id(instance) assert clone == instance # Freeze part is_pres_top.freeze() clone, leaf_pointer = instance.path_clone() assert id(clone) != id(instance) assert not clone.is_frozen assert clone == instance assert id(clone.get_choice_node_for_arg("arg1")) == id(is_pres_top) assert id(clone.get_choice_node_for_arg("arg2")) != id(is_pres_top2) # Freeze all instance.freeze() clone, leaf_pointer = instance.path_clone() assert id(clone) == id(instance) assert clone == instance assert id(clone.get_choice_node_for_arg("arg1")) == id(is_pres_top) assert id(clone.get_choice_node_for_arg("arg2")) == id(is_pres_top2) # Full unfreeze path clone, leaf_pointer = instance.path_clone( [instance, is_pres_top, arg_node, is_pres, fin_choice]) assert id(clone) != id(instance) assert not clone.is_frozen assert clone == instance assert leaf_pointer.get_nodes_to_here() == \ [instance, is_pres_top, arg_node, is_pres, fin_choice] assert id(clone.get_choice_node_for_arg("arg2")) == id(is_pres_top2) assert clone.get_choice_node_for_arg("arg2").is_frozen # Partial unfreeze path (stop early) clone, leaf_pointer = instance.path_clone( [instance, is_pres_top, arg_node]) assert id(clone) != id(instance) assert not clone.is_frozen assert clone != instance assert len(leaf_pointer.get_nodes_to_here()) == 3 new_arg_node: ObjectNode = leaf_pointer.cur_node assert new_arg_node.get_choice_node_for_arg( OPTIONAL_ARGUMENT_NEXT_ARG_NAME) is None assert new_arg_node.get_choice_node_for_arg( OPTIONAL_ARGUMENT_NEXT_ARG_NAME) is None assert clone.get_choice_node_for_arg("arg2") == is_pres_top2 assert id(clone.get_choice_node_for_arg("arg2")) == id(is_pres_top2)