def test_no_json_yaml_precedence(self) -> None: """ Test that neither JSON nor YAML take precedence over each other. """ yfp, ypath = tempfile.mkstemp(".yml") with open(ypath, 'w') as fy: fy.write(""" foo.bar: "i'm yaml" """) jfp, jpath = tempfile.mkstemp(".json") with open(jpath, 'w') as fj: fj.write(""" { "foo.bar": "i'm json" } """) db1 = hammer_config.HammerDatabase() configs = hammer_config.load_config_from_paths([ypath, jpath]) db1.update_core([hammer_config.combine_configs(configs)]) self.assertEqual(db1.get_setting("foo.bar"), "i'm json") db2 = hammer_config.HammerDatabase() configs = hammer_config.load_config_from_paths([jpath, ypath]) db2.update_core([hammer_config.combine_configs(configs)]) self.assertEqual(db2.get_setting("foo.bar"), "i'm yaml")
def test_multiple_lazy_metas(self) -> None: """ Test multiple lazy metas applied at once. Note that this is unsupported at the moment. """ db = hammer_config.HammerDatabase() base = hammer_config.load_config_from_string(""" hello1: "abc" hello2: "def" base: "hello1" test: "${base}" test_meta: ["lazysubst", "lazycrossref"] """, is_yaml=True) meta = hammer_config.load_config_from_string(""" { "base": "hello2" } """, is_yaml=False) db.update_core([base, meta]) with self.assertRaises(ValueError) as cm: self.assertEqual(db.get_setting("base"), "hello2") self.assertEqual(db.get_setting("test"), "def") msg = cm.exception.args[0] self.assertTrue( "Multiple lazy directives in a single directive array not supported yet" in msg)
def test_meta_prependlocal(self): """ Test that the meta attribute "prependlocal" works. """ db = hammer_config.HammerDatabase() base = hammer_config.load_config_from_string(""" foo: bar: adc: "yes" dac: "no" dsl: ["scala"] base_test: "local_path" base_test_meta: prependlocal """, is_yaml=True, path="base/config/path") meta = hammer_config.load_config_from_string(""" { "foo.bar.dsl": ["python"], "foo.bar.dsl_meta": "append", "foo.bar.dac": "current_weighted", "foo.bar.meta_test": "local_path", "foo.bar.meta_test_meta": "prependlocal" } """, is_yaml=False, path="meta/config/path") db.update_core([base, meta]) self.assertEqual(db.get_setting("foo.bar.dac"), "current_weighted") self.assertEqual(db.get_setting("foo.bar.dsl"), ["scala", "python"]) self.assertEqual(db.get_setting("foo.bar.base_test"), "base/config/path/local_path") self.assertEqual(db.get_setting("foo.bar.meta_test"), "meta/config/path/local_path")
def test_meta_transclude_prependlocal(self): """ Test that the meta attribute "transclude" works with "prependlocal". """ # Put some text into the file. file_contents = "The quick brown fox jumps over the lazy dog" local_path = "meta/config/path" fd, path = tempfile.mkstemp(".txt") with open(path, "w") as f: f.write(file_contents) db = hammer_config.HammerDatabase() base = hammer_config.load_config_from_string(""" chips: potato: tuber bear: "yeah" """, is_yaml=True) meta = hammer_config.load_config_from_string(""" { "chips.tree": "<path>", "chips.tree_meta": ["transclude", "prependlocal"] } """.replace("<path>", path), is_yaml=False, path=local_path) db.update_core([base, meta]) # Trigger merge before cleanup self.assertEqual(db.get_setting("chips.potato"), "tuber") # Cleanup os.remove(path) self.assertEqual(db.get_setting("chips.bear"), "yeah") self.assertEqual(db.get_setting("chips.tree"), os.path.join(local_path, file_contents))
def test_meta_lazysubst_other_lazysubst(self) -> None: """ Check that a lazysubst which references other lazysubst works. """ db = hammer_config.HammerDatabase() base = hammer_config.load_config_from_string(""" foo: flash: "yes" one: "1" two: "2" lolcat: "" twelve: "${lolcat}" twelve_meta: lazysubst """, is_yaml=True) project = hammer_config.load_config_from_string(""" { "lolcat": "whatever", "later": "${foo.twelve}", "later_meta": "lazysubst" } """, is_yaml=False) db.update_core([base]) db.update_project([project]) self.assertEqual(db.get_setting("lolcat"), "whatever") self.assertEqual(db.get_setting("foo.twelve"), "whatever") self.assertEqual(db.get_setting("later"), "whatever")
def test_self_reference_lazycrossref(self) -> None: """ Test that self-referencing lazy crossref works. """ db = hammer_config.HammerDatabase() base = hammer_config.load_config_from_string(""" base: "hello" derivative: "base" derivative_meta: "lazycrossref" """, is_yaml=True) config1 = hammer_config.load_config_from_string(""" { "derivative": "derivative", "derivative_meta": "lazycrossref" } """, is_yaml=True) config2 = hammer_config.load_config_from_string(""" { "base": "tower", "derivative": "derivative", "derivative_meta": "lazycrossref" } """, is_yaml=True) db.update_core([base, config1, config2]) self.assertEqual(db.get_setting("base"), "tower")
def test_self_reference_lazyappend(self) -> None: """ Test that lazy "append" works. Note that append is always self-referencing. """ db = hammer_config.HammerDatabase() base = hammer_config.load_config_from_string(""" global: ["hello", "world"] """, is_yaml=True) config1 = hammer_config.load_config_from_string(""" { "global": ["scala"], "global_meta": "lazyappend" } """, is_yaml=False) config2 = hammer_config.load_config_from_string(""" { "global": ["python"], "global_meta": "lazyappend" } """, is_yaml=False) db.update_core([base, config1]) db.update_project([config2]) self.assertEqual(db.get_setting("global"), ["hello", "world", "scala", "python"])
def test_meta_lazycrossappendref_prepend_local(self) -> None: """ Test that lazy crossappendref works to prepend the local path. """ db = hammer_config.HammerDatabase() base = hammer_config.load_config_from_string(""" # These lines are present to test that the dependency graph with # crossappendref is correct. # If crossappendref doesn't declare a dependency, aaa* might not be recognized # as a dependency of test. aaa0: "tmp.tmptmp" aaa0_meta: lazycrossref aaa1: "tmp.tmptmp" aaa1_meta: lazycrossref test: ["aaa0", "aaa1"] test_meta: "lazycrossappendref" base: ["bin", "usr_bin"] tmp.tmptmp2: "myfolder" tmp.tmptmp2_meta: "prependlocal" tmp.tmptmp: ["tmp.tmptmp2"] tmp.tmptmp_meta: "lazycrossref" paths: ["base", "tmp.tmptmp"] paths_meta: "lazycrossappendref" """, is_yaml=True, path="opt") db.update_core([base]) self.assertEqual(db.get_setting("base"), ["bin", "usr_bin"]) self.assertEqual(db.get_setting("paths"), ["bin", "usr_bin", "opt/myfolder"]) self.assertEqual(db.get_setting("test"), ["opt/myfolder", "opt/myfolder"])
def test_self_reference_lazysubst(self) -> None: """ Test that self-referencing lazy subst works. """ db = hammer_config.HammerDatabase() base = hammer_config.load_config_from_string(""" base_str: "hello" derivative_str: "${base_str}" derivative_str_meta: "lazysubst" """, is_yaml=True) config1 = hammer_config.load_config_from_string(""" { "derivative_str": "${derivative_str}_1", "derivative_str_meta": "lazysubst" } """, is_yaml=True) config2 = hammer_config.load_config_from_string(""" { "derivative_str": "${derivative_str}_2", "derivative_str_meta": "lazysubst" } """, is_yaml=True) db.update_core([base, config1, config2]) self.assertEqual(db.get_setting("derivative_str"), "hello_1_2")
def test_tarballs_not_extracted(self) -> None: """ Test that tarballs that are not pre-extracted work fine. """ import hammer_config tech_dir, tech_dir_base = HammerToolTestHelpers.create_tech_dir( "dummy28") tech_json_filename = os.path.join(tech_dir, "dummy28.tech.json") # Add defaults to specify tarball_dir. with open(os.path.join(tech_dir, "defaults.json"), "w") as f: f.write(json.dumps({"technology.dummy28.tarball_dir": tech_dir})) HammerToolTestHelpers.write_tech_json(tech_json_filename, self.add_tarballs) tech = self.get_tech( hammer_tech.HammerTechnology.load_from_dir("dummy28", tech_dir)) tech.cache_dir = tech_dir database = hammer_config.HammerDatabase() database.update_technology(tech.get_config()) HammerVLSISettings.load_builtins_and_core(database) tech.set_database(database) outputs = tech.process_library_filter( pre_filts=[], filt=hammer_tech.filters.gds_filter, must_exist=False, output_func=lambda str, _: [str]) self.assertEqual( outputs, ["{0}/extracted/foobar.tar.gz/test.gds".format(tech_dir)]) # Cleanup shutil.rmtree(tech_dir_base)
def test_meta_dynamicsubst_other_dynamicsubst(self): """ Check that a dynamicsubst which references other dynamicsubst errors for now. """ """ Test that the meta attribute "dynamicsubst" works. """ db = hammer_config.HammerDatabase() base = hammer_config.load_config_from_string(""" foo: flash: "yes" one: "1" two: "2" lolcat: "" twelve: "${lolcat}" twelve_meta: dynamicsubst """, is_yaml=True) project = hammer_config.load_config_from_string(""" { "lolcat": "whatever", "later": "${foo.twelve}", "later_meta": "dynamicsubst" } """, is_yaml=False) db.update_core([base]) db.update_project([project]) with self.assertRaises(ValueError): print(db.get_config())
def test_meta_crossref(self) -> None: """ Test that the meta attribute "crossref" works. """ db = hammer_config.HammerDatabase() base = hammer_config.load_config_from_string(""" my: numbers: ["1", "2", "3"] dichotomy: false unity: true world: ["world"] "target_key": "my.dichotomy" """, is_yaml=True) meta = hammer_config.load_config_from_string(""" { "just.numbers": "my.numbers", "just.numbers_meta": "crossref", "copies.numbers": ["my.numbers", "my.world"], "copies.numbers_meta": "crossref", "bools": ["my.dichotomy", "my.unity"], "bools_meta": "crossref", "indirect.numbers": "${target_key}", "indirect.numbers_meta": ["subst", "crossref"] } """, is_yaml=False) db.update_core([base, meta]) self.assertEqual(db.get_setting("just.numbers"), ["1", "2", "3"]) self.assertEqual(db.get_setting("copies.numbers"), [["1", "2", "3"], ["world"]]) self.assertEqual(db.get_setting("bools"), [False, True]) self.assertEqual(db.get_setting("indirect.numbers"), False)
def test_meta_transclude_subst(self): """ Test that the meta attribute "transclude" works with "subst". """ # Put some text into the file. file_contents = "I like ${food.condiment} on my ${food.dish}." file_contents_sol = "I like monosodium monochloride on my chips." local_path = "meta/config/path" fd, path = tempfile.mkstemp(".txt") with open(path, "w") as f: f.write(file_contents) db = hammer_config.HammerDatabase() base = hammer_config.load_config_from_string(""" food: condiment: "monosodium monochloride" dish: "chips" """, is_yaml=True) meta = hammer_config.load_config_from_string(""" { "food.announcement": "<path>", "food.announcement_meta": ["transclude", "subst"] } """.replace("<path>", path), is_yaml=False, path=local_path) db.update_core([base, meta]) # Trigger merge before cleanup self.assertEqual(db.get_setting("food.dish"), "chips") # Cleanup os.remove(path) self.assertEqual(db.get_setting("food.announcement"), file_contents_sol)
def test_meta_subst(self) -> None: """ Test that the meta attribute "subst" works. """ db = hammer_config.HammerDatabase() base = hammer_config.load_config_from_string(""" foo: flash: "yes" one: "1" two: "2" """, is_yaml=True) meta = hammer_config.load_config_from_string(""" { "foo.pipeline": "${foo.flash}man", "foo.pipeline_meta": "subst", "foo.uint": ["${foo.one}", "${foo.two}"], "foo.uint_meta": "subst" } """, is_yaml=False) db.update_core([base, meta]) self.assertEqual(db.get_setting("foo.flash"), "yes") self.assertEqual(db.get_setting("foo.pipeline"), "yesman") self.assertEqual(db.get_setting("foo.uint"), ["1", "2"])
def test_stackup(self) -> None: """ Test that getting the stackup works as expected. """ import hammer_config tech_dir, tech_dir_base = HammerToolTestHelpers.create_tech_dir( "dummy28") tech_json_filename = os.path.join(tech_dir, "dummy28.tech.json") test_stackup = StackupTestHelper.create_test_stackup_dict(10) def add_stackup(in_dict: Dict[str, Any]) -> Dict[str, Any]: out_dict = deepdict(in_dict) out_dict.update({"stackups": [test_stackup]}) return out_dict HammerToolTestHelpers.write_tech_json(tech_json_filename, add_stackup) tech = self.get_tech( hammer_tech.HammerTechnology.load_from_dir("dummy28", tech_dir)) tech.cache_dir = tech_dir tool = DummyTool() tool.technology = tech database = hammer_config.HammerDatabase() tool.set_database(database) self.assertEqual( tech.get_stackup_by_name(test_stackup["name"]), Stackup.from_setting(tech.get_grid_unit(), test_stackup))
def test_macro_sizes(self) -> None: """ Test that getting macro sizes works as expected. """ import hammer_config tech_dir, tech_dir_base = HammerToolTestHelpers.create_tech_dir( "dummy28") tech_json_filename = os.path.join(tech_dir, "dummy28.tech.json") def add_lib_with_lef(d: Dict[str, Any]) -> Dict[str, Any]: with open(os.path.join(tech_dir, 'my_vendor_lib.lef'), 'w') as f: f.write("""VERSION 5.8 ; BUSBITCHARS "[]" ; DIVIDERCHAR "/" ; MACRO my_awesome_macro CLASS BLOCK ; ORIGIN -0.435 607.525 ; FOREIGN my_awesome_macro 0.435 -607.525 ; SIZE 810.522 BY 607.525 ; SYMMETRY X Y R90 ; END my_awesome_macro END LIBRARY """) r = deepdict(d) r['libraries'].append({ 'name': 'my_vendor_lib', 'lef file': 'test/my_vendor_lib.lef' }) return r HammerToolTestHelpers.write_tech_json(tech_json_filename, add_lib_with_lef) tech_opt = hammer_tech.HammerTechnology.load_from_dir( "dummy28", tech_dir) if tech_opt is None: self.assertTrue(False, "Unable to load technology") return else: tech = tech_opt # type: hammer_tech.HammerTechnology tech.cache_dir = tech_dir tech.logger = HammerVLSILogging.context("") database = hammer_config.HammerDatabase() tech.set_database(database) # Test that macro sizes can be read out of the LEF. self.assertEqual(tech.get_macro_sizes(), [ hammer_tech.MacroSize(library='my_vendor_lib', name='my_awesome_macro', width=Decimal("810.522"), height=Decimal("607.525")) ]) # Cleanup shutil.rmtree(tech_dir_base)
def test_no_config_junk(self): """Test that no _config_path junk variables get left behind.""" db = hammer_config.HammerDatabase() db.update_core([hammer_config.load_config_from_string("key1: value1", is_yaml=True)]) db.update_technology([hammer_config.load_config_from_string("key2: value2", is_yaml=True)]) db.update_project([hammer_config.load_config_from_string("key3: value3", is_yaml=True)]) for key in hammer_config.HammerDatabase.internal_keys(): self.assertFalse(db.has_setting(key), "Should not have internal key " + key)
def test_read_libs(self) -> None: """ Test that HammerTool can read technology IP libraries and filter/process them. """ import hammer_config tech_dir, tech_dir_base = HammerToolTestHelpers.create_tech_dir( "dummy28") tech_json_filename = os.path.join(tech_dir, "dummy28.tech.json") HammerToolTestHelpers.write_tech_json(tech_json_filename) tech_opt = hammer_tech.HammerTechnology.load_from_dir( "dummy28", tech_dir) if tech_opt is None: self.assertTrue(False, "Unable to load technology") else: tech = tech_opt # type: hammer_tech.HammerTechnology tech.cache_dir = tech_dir class Tool(SingleStepTool): def step(self) -> bool: def test_tool_format(lib, filt) -> List[str]: return ["drink {0}".format(lib)] self._read_lib_output = self.read_libs( [self.milkyway_techfile_filter], test_tool_format, must_exist=False) self._test_filter_output = self.read_libs( [HammerToolTestHelpers.make_test_filter()], test_tool_format, must_exist=False) return True test = Tool() test.logger = HammerVLSILogging.context("") test.run_dir = tempfile.mkdtemp() test.technology = tech test.set_database(hammer_config.HammerDatabase()) test.run() # Don't care about ordering here. self.assertEqual(set(test._read_lib_output), { "drink {0}/soy".format(tech_dir), "drink {0}/coconut".format(tech_dir) }) # We do care about ordering here. self.assertEqual(test._test_filter_output, [ "drink {0}/tea".format(tech_dir), "drink {0}/grapefruit".format(tech_dir), "drink {0}/juice".format(tech_dir), "drink {0}/orange".format(tech_dir) ]) # Cleanup shutil.rmtree(tech_dir_base) shutil.rmtree(test.run_dir)
def test_overriding(self): """ Test that we can add a project first and technology after and still have it override. """ db = hammer_config.HammerDatabase() db.update_project([{"tech.x": "foo"}]) self.assertEqual(db.get_setting("tech.x"), "foo") db.update_technology([{"tech.x": "bar"}]) self.assertEqual(db.get_setting("tech.x"), "foo")
def test_meta_lazysubst_array(self) -> None: """ Check that lazysubst works correctly with an array. """ db = hammer_config.HammerDatabase() d = hammer_config.load_config_from_string(""" target: "foo" array: ["${target}bar"] array_meta: lazysubst """, is_yaml=True) db.update_core([d]) self.assertEqual(db.get_setting("array"), ["foobar"])
def test_unpacking(self): """ Test that input configs get unpacked. """ db = hammer_config.HammerDatabase() config = hammer_config.load_config_from_string(""" foo: bar: adc: "yes" dac: "no" """, is_yaml=True) db.update_core([config]) self.assertEqual(db.get_setting("foo.bar.adc"), "yes") self.assertEqual(db.get_setting("foo.bar.dac"), "no")
def test_drc_lvs_decks(self) -> None: """ Test that getting the DRC & LVS decks works as expected. """ import hammer_config tech_dir, tech_dir_base = HammerToolTestHelpers.create_tech_dir("dummy28") tech_json_filename = os.path.join(tech_dir, "dummy28.tech.json") def add_drc_lvs_decks(in_dict: Dict[str, Any]) -> Dict[str, Any]: out_dict = deepdict(in_dict) out_dict.update({"drc decks": [ {"tool name": "hammer", "deck name": "a_nail", "path": "/path/to/hammer/a_nail.drc.rules"}, {"tool name": "chisel", "deck name": "some_wood", "path": "/path/to/chisel/some_wood.drc.rules"}, {"tool name": "hammer", "deck name": "head_shark", "path": "/path/to/hammer/head_shark.drc.rules"} ]}) out_dict.update({"lvs decks": [ {"tool name": "hammer", "deck name": "a_nail", "path": "/path/to/hammer/a_nail.lvs.rules"}, {"tool name": "chisel", "deck name": "some_wood", "path": "/path/to/chisel/some_wood.lvs.rules"}, {"tool name": "hammer", "deck name": "head_shark", "path": "/path/to/hammer/head_shark.lvs.rules"} ]}) return out_dict HammerToolTestHelpers.write_tech_json(tech_json_filename, add_drc_lvs_decks) sys.path.append(tech_dir_base) tech = self.get_tech(hammer_tech.HammerTechnology.load_from_dir("dummy28", tech_dir)) tech.cache_dir = tech_dir tool = DummyTool() tool.technology = tech database = hammer_config.HammerDatabase() tool.set_database(database) self.maxDiff = None self.assertEqual(tech.get_drc_decks_for_tool("hammer"), [DRCDeck(tool_name="hammer", name="a_nail", path="/path/to/hammer/a_nail.drc.rules"), DRCDeck(tool_name="hammer", name="head_shark", path="/path/to/hammer/head_shark.drc.rules") ]) self.assertEqual(tech.get_lvs_decks_for_tool("hammer"), [LVSDeck(tool_name="hammer", name="a_nail", path="/path/to/hammer/a_nail.lvs.rules"), LVSDeck(tool_name="hammer", name="head_shark", path="/path/to/hammer/head_shark.lvs.rules") ]) self.assertEqual(tech.get_drc_decks_for_tool("chisel"), [DRCDeck(tool_name="chisel", name="some_wood", path="/path/to/chisel/some_wood.drc.rules")]) self.assertEqual(tech.get_lvs_decks_for_tool("chisel"), [LVSDeck(tool_name="chisel", name="some_wood", path="/path/to/chisel/some_wood.lvs.rules")])
def check_src(self, yaml_src: str, ref_port: ClockPort) -> None: """ Helper method to check if the given source parses to the given port. :param yaml_src: YAML config source :param ref_port: Reference port """ database = hammer_config.HammerDatabase() database.update_project( [hammer_config.load_config_from_string(yaml_src, is_yaml=True)]) tool = DummyHammerTool() tool.set_database(database) ports = tool.get_clock_ports() self.assertEqual(len(ports), 1) port = ports[0] self.assertEqual(port, ref_port)
def test_installs_in_cache_dir(self) -> None: """ Test that we can access files in the tech cache dir. Use case: A PDK file needs to be hacked by post_install_script """ import hammer_config tech_dir, tech_dir_base = HammerToolTestHelpers.create_tech_dir( "dummy28") tech_json_filename = os.path.join(tech_dir, "dummy28.tech.json") tech_json = { "name": "dummy", "installs": [{ "path": "tech-dummy28-cache", "base var": "" # means relative to tech dir }], "libraries": [{ "lef file": "tech-dummy28-cache/tech.lef", "provides": [{ "lib_type": "technology" }] }] } # type: Dict[str, Any] with open(tech_json_filename, "w") as f: # pyline: disable=invalid-name f.write(json.dumps(tech_json, cls=HammerJSONEncoder, indent=4)) tech = self.get_tech( hammer_tech.HammerTechnology.load_from_dir("dummy28", tech_dir)) tech.cache_dir = tech_dir database = hammer_config.HammerDatabase() database.update_technology(tech.get_config()) HammerVLSISettings.load_builtins_and_core(database) tech.set_database(database) outputs = tech.process_library_filter( pre_filts=[], filt=hammer_tech.filters.lef_filter, must_exist=False, output_func=lambda str, _: [str]) self.assertEqual(outputs, ["{0}/tech.lef".format(tech.cache_dir)]) # Cleanup shutil.rmtree(tech_dir_base)
def test_meta_lazycrossappend_with_lazycrossref(self) -> None: """ Test that lazy crossappend works with lazy crossref in one file. """ db = hammer_config.HammerDatabase() base = hammer_config.load_config_from_string(""" global: ["hello", "world", "scala"] tool_1: "global" tool_1_meta: "lazycrossref" tool: ["tool_1", ["python"]] tool_meta: "lazycrossappend" """, is_yaml=True) db.update_core([base]) self.assertEqual(db.get_setting("global"), ["hello", "world", "scala"]) self.assertEqual(db.get_setting("tool"), ["hello", "world", "scala", "python"])
def test_meta_crossref_errors(self) -> None: """ Test that the meta attribute "crossref" raises errors appropriately. """ db = hammer_config.HammerDatabase() base = hammer_config.load_config_from_string(""" my: numbers: ["1", "2", "3"] dichotomy: false unity: true world: ["world"] "target_key": "my.dichotomy" """, is_yaml=True) with self.assertRaises(ValueError): meta = hammer_config.load_config_from_string(""" { "no_crossrefing_using_int": 123, "no_crossrefing_using_int_meta": "crossref" } """, is_yaml=False) db.update_core([base, meta]) db.get_setting("no_crossrefing_using_int") with self.assertRaises(ValueError): meta = hammer_config.load_config_from_string(""" { "no_crossrefing_using_bool": false, "no_crossrefing_using_bool_meta": "crossref" } """, is_yaml=False) db.update_core([base, meta]) db.get_setting("no_crossrefing_using_bool") with self.assertRaises(ValueError): meta = hammer_config.load_config_from_string(""" { "bad_list": [1, 2], "bad_list_meta": "crossref" } """, is_yaml=False) db.update_core([base, meta]) db.get_setting("bad_list")
def test_meta_deepsubst_cwd(self) -> None: """ Test that the deepsubst special meta "cwd" correctly prepends the CWD. """ cwd = os.getcwd() db = hammer_config.HammerDatabase() base = hammer_config.load_config_from_string(""" foo: bar_meta: deepsubst bar: - adc: "yes" dac: "no" dsl: ["scala"] base_test: "some_relative_path" base_test_deepsubst_meta: "cwd" """, is_yaml=True, path="base/config/path") meta = hammer_config.load_config_from_string(""" { "foo.bar_meta": ["append", "deepsubst"], "foo.bar": [{ "dsl": ["python"], "dsl_meta": "append", "dac": "current_weighted", "meta_test": "some/relative/path", "meta_test_deepsubst_meta": "cwd", "abs_test": "/this/is/an/abs/path", "abs_test_deepsubst_meta": "cwd" }] } """, is_yaml=False, path="meta/config/path") db.update_core([base, meta]) self.assertEqual( db.get_setting("foo.bar")[0]["base_test"], os.path.join(cwd, "some_relative_path")) self.assertEqual( db.get_setting("foo.bar")[1]["meta_test"], os.path.join(cwd, "some/relative/path")) # leading / should override the meta self.assertEqual( db.get_setting("foo.bar")[1]["abs_test"], "/this/is/an/abs/path")
def test_meta_lazycrossref(self) -> None: """ Test that lazy crossref works. """ db = hammer_config.HammerDatabase() base = hammer_config.load_config_from_string(""" my: numbers: ["1", "2", "3"] """, is_yaml=True) meta = hammer_config.load_config_from_string(""" numbers: "my.numbers" numbers_meta: crossref lazy.numbers: "numbers" lazy.numbers_meta: lazycrossref """, is_yaml=True) db.update_core([base, meta]) self.assertEqual(db.get_setting("lazy.numbers"), ["1", "2", "3"])
def test_meta_subst_and_prependlocal(self): """ Test that meta attributes that are an array. """ db = hammer_config.HammerDatabase() base = hammer_config.load_config_from_string(""" foo: bar: base_test: "local_path" """, is_yaml=True, path="base/config/path") meta = hammer_config.load_config_from_string(""" { "foo.bar.meta_test": "${foo.bar.base_test}", "foo.bar.meta_test_meta": ["subst", "prependlocal"] } """, is_yaml=False, path="meta/config/path") db.update_core([base, meta]) self.assertEqual(db.get_setting("foo.bar.base_test"), "local_path") self.assertEqual(db.get_setting("foo.bar.meta_test"), "meta/config/path/local_path")
def test_meta_json2list(self): """ Test that the meta attribute "json2list" works. """ db = hammer_config.HammerDatabase() base = hammer_config.load_config_from_string(""" foo: flash: "yes" max: "min" """, is_yaml=True) meta = hammer_config.load_config_from_string(""" { "foo.pipeline": "[\\"1\\", \\"2\\"]", "foo.pipeline_meta": "json2list" } """, is_yaml=False) db.update_core([base, meta]) self.assertEqual(db.get_setting("foo.flash"), "yes") self.assertEqual(db.get_setting("foo.max"), "min") self.assertEqual(db.get_setting("foo.pipeline"), ["1", "2"])