def testInclude(self): """Read a config that has an include directive""" c = Config(os.path.join(self.configDir, "testinclude.yaml")) self.assertEqual(c[".comp1.item1"], 58) self.assertEqual(c[".comp2.comp.item1"], 1) self.assertEqual(c[".comp3.1.comp.item1"], "posix") self.assertEqual(c[".comp4.0.comp.item1"], "posix") self.assertEqual(c[".comp4.1.comp.item1"], 1) self.assertEqual(c[".comp5.comp6.comp.item1"], "posix") # Test a specific name and then test that all # returned names are "in" the config. names = c.names() self.assertIn(c._D.join(("", "comp3", "1", "comp", "item1")), names) for n in names: self.assertIn(n, c) # Test that override delimiter works delimiter = "-" names = c.names(delimiter=delimiter) self.assertIn(delimiter.join(("", "comp3", "1", "comp", "item1")), names)
def testHierarchy(self): c = Config() # Simple dict c["a"] = {"z": 52, "x": "string"} self.assertIn(".a.z", c) self.assertEqual(c[".a.x"], "string") # Try different delimiters self.assertEqual(c["⇛a⇛z"], 52) self.assertEqual(c[("a", "z")], 52) self.assertEqual(c["a", "z"], 52) c[".b.new.thing1"] = "thing1" c[".b.new.thing2"] = "thing2" c[".b.new.thing3.supp"] = "supplemental" self.assertEqual(c[".b.new.thing1"], "thing1") tmp = c[".b.new"] self.assertEqual(tmp["thing2"], "thing2") self.assertEqual(c[".b.new.thing3.supp"], "supplemental") # Test that we can index into lists c[".a.b.c"] = [1, "7", 3, {"1": 4, "5": "Five"}, "hello"] self.assertIn(".a.b.c.3.5", c) self.assertNotIn(".a.b.c.10", c) self.assertNotIn(".a.b.c.10.d", c) self.assertEqual(c[".a.b.c.3.5"], "Five") # Is the value in the list? self.assertIn(".a.b.c.hello", c) self.assertNotIn(".a.b.c.hello.not", c) # And assign to an element in the list self.assertEqual(c[".a.b.c.1"], "7") c[".a.b.c.1"] = 8 self.assertEqual(c[".a.b.c.1"], 8) self.assertIsInstance(c[".a.b.c"], collections.abc.Sequence) # Test we do get lists back from asArray a = c.asArray(".a.b.c") self.assertIsInstance(a, list) # Is it the *same* list as in the config a.append("Sentinel") self.assertIn("Sentinel", c[".a.b.c"]) self.assertIn(".a.b.c.Sentinel", c) # Test we always get a list for k in c.names(): a = c.asArray(k) self.assertIsInstance(a, list) # Check we get the same top level keys self.assertEqual(set(c.names(topLevelOnly=True)), set(c._data.keys())) # Check that we can iterate through items for k, v in c.items(): self.assertEqual(c[k], v) # Check that lists still work even if assigned a dict c = Config({ "cls": "lsst.daf.butler", "formatters": { "calexp.wcs": "{component}", "calexp": "{datasetType}" }, "datastores": [{ "datastore": { "cls": "datastore1" } }, { "datastore": { "cls": "datastore2" } }] }) c[".datastores.1.datastore"] = {"cls": "datastore2modified"} self.assertEqual(c[".datastores.0.datastore.cls"], "datastore1") self.assertEqual(c[".datastores.1.datastore.cls"], "datastore2modified") self.assertIsInstance(c["datastores"], collections.abc.Sequence) # Test that we can get all the listed names. # and also that they are marked as "in" the Config # Try delimited names and tuples for n in itertools.chain(c.names(), c.nameTuples()): val = c[n] self.assertIsNotNone(val) self.assertIn(n, c) names = c.names() nameTuples = c.nameTuples() self.assertEqual(len(names), len(nameTuples)) self.assertEqual(len(names), 11) self.assertEqual(len(nameTuples), 11) # Test that delimiter escaping works names = c.names(delimiter=".") for n in names: self.assertIn(n, c) self.assertIn(".formatters.calexp\\.wcs", names) # Use a name that includes the internal default delimiter # to test automatic adjustment of delimiter strangeKey = f"calexp{c._D}wcs" c["formatters", strangeKey] = "dynamic" names = c.names() self.assertIn(strangeKey, "-".join(names)) self.assertFalse(names[0].startswith(c._D)) for n in names: self.assertIn(n, c) top = c.nameTuples(topLevelOnly=True) self.assertIsInstance(top[0], tuple) # Investigate a possible delimeter in a key c = Config({"formatters": {"calexp.wcs": 2, "calexp": 3}}) self.assertEqual(c[":formatters:calexp.wcs"], 2) self.assertEqual(c[":formatters:calexp"], 3) for k, v in c["formatters"].items(): self.assertEqual(c["formatters", k], v) # Check internal delimiter inheritance c._D = "." c2 = c["formatters"] self.assertEqual(c._D, c2._D) # Check that the child inherits self.assertNotEqual(c2._D, Config._D)
def testBasics(self): c = Config({"1": 2, "3": 4, "key3": 6, "dict": {"a": 1, "b": 2}}) pretty = c.ppprint() self.assertIn("key3", pretty) r = repr(c) self.assertIn("key3", r) regex = r"^Config\(\{.*\}\)$" self.assertRegex(r, regex) c2 = eval(r) self.assertIn("1", c) for n in c.names(): self.assertEqual(c2[n], c[n]) self.assertEqual(c, c2) s = str(c) self.assertIn("\n", s) self.assertNotRegex(s, regex) self.assertCountEqual(c.keys(), ["1", "3", "key3", "dict"]) self.assertEqual(list(c), list(c.keys())) self.assertEqual(list(c.values()), [c[k] for k in c.keys()]) self.assertEqual(list(c.items()), [(k, c[k]) for k in c.keys()]) newKeys = ("key4", ".dict.q", ("dict", "r"), "5") oldKeys = ("key3", ".dict.a", ("dict", "b"), "3") remainingKey = "1" # Check get with existing key for k in oldKeys: self.assertEqual(c.get(k, "missing"), c[k]) # Check get, pop with nonexistent key for k in newKeys: self.assertEqual(c.get(k, "missing"), "missing") self.assertEqual(c.pop(k, "missing"), "missing") # Check setdefault with existing key for k in oldKeys: c.setdefault(k, 8) self.assertNotEqual(c[k], 8) # Check setdefault with nonexistent key (mutates c, adding newKeys) for k in newKeys: c.setdefault(k, 8) self.assertEqual(c[k], 8) # Check pop with existing key (mutates c, removing newKeys) for k in newKeys: v = c[k] self.assertEqual(c.pop(k, "missing"), v) # Check deletion (mutates c, removing oldKeys) for k in ("key3", ".dict.a", ("dict", "b"), "3"): self.assertIn(k, c) del c[k] self.assertNotIn(k, c) # Check that `dict` still exists, but is now empty (then remove # it, mutatic c) self.assertIn("dict", c) del c["dict"] # Check popitem (mutates c, removing remainingKey) v = c[remainingKey] self.assertEqual(c.popitem(), (remainingKey, v)) # Check that c is now empty self.assertFalse(c)