Mercurial > hgrepos > Python > libs > ConfigMix
changeset 647:df58983f28a2
Allow to disable the internal caching in configmix.
Also allow to re-enable internal caching.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Fri, 11 Mar 2022 01:53:08 +0100 |
| parents | f8cb74b447de |
| children | e8f3e970e411 |
| files | configmix/config.py tests/test.py |
| diffstat | 2 files changed, 117 insertions(+), 31 deletions(-) [+] |
line wrap: on
line diff
--- a/configmix/config.py Mon Mar 07 09:11:22 2022 +0100 +++ b/configmix/config.py Fri Mar 11 01:53:08 2022 +0100 @@ -451,14 +451,23 @@ # # PY2.7 compat: must be set before calling the superclass' __init__ # - self.__lookup_cache = {} - self.__interpolation_cache = {} + self.enable_cache() super(Configuration, self).__init__(*args, **kwds) def clear_cache(self): """Clear the internal lookup cache and the interpolation cache""" - self.__lookup_cache.clear() - self.__interpolation_cache.clear() + if self.__lookup_cache is not None: + self.__lookup_cache.clear() + if self.__interpolation_cache is not None: + self.__interpolation_cache.clear() + + def disable_cache(self): + self.__lookup_cache = None + self.__interpolation_cache = None + + def enable_cache(self): + self.__lookup_cache = {} + self.__interpolation_cache = {} def __getitem__(self, key): """Mapping and list interface that forwards to :meth:`~.getvarl_s` @@ -834,28 +843,33 @@ """ if not path: return self - v = self.__lookup_cache.get(path, _MARKER) - if v is not _MARKER: - if v is _MISSING: - raise KeyError( - "Configuration variable %r not found" - " (negative internal cache value)" % (path,)) - else: - return v + use_cache = self.__lookup_cache is not None + if use_cache: + v = self.__lookup_cache.get(path, _MARKER) + if v is not _MARKER: + if v is _MISSING: + raise KeyError( + "Configuration variable %r not found" + " (negative internal cache value)" % (path,)) + else: + return v eiref = self.expand_if_reference try: v = eiref(super(Configuration, self).__getitem__(path[0])) for p in path[1:]: v = eiref(v[p]) except TypeError: - self.__lookup_cache[path] = _MISSING + if use_cache: + self.__lookup_cache[path] = _MISSING raise KeyError( "Configuration variable %r not found" "(missing intermediate keys?)" % (path,)) except KeyError: - self.__lookup_cache[path] = _MISSING + if use_cache: + self.__lookup_cache[path] = _MISSING raise - self.__lookup_cache[path] = v + if use_cache: + self.__lookup_cache[path] = v return v def _lookupref(self, key): @@ -936,21 +950,23 @@ start = s.find(_STARTTOK, 0) if start < 0: return s - res = self.__interpolation_cache.get(s, _MARKER) - if res is not _MARKER: - if res is _MISSING: - warnings.warn("Cannot interpolate variables in string " - "%r (cached)" % (s, ), - UserWarning, - stacklevel=1) - raise KeyError("Cannot interpolate variables in string " - "%r (cached)" % (s, )) - else: - return res + use_cache = self.__interpolation_cache is not None + if use_cache: + res = self.__interpolation_cache.get(s, _MARKER) + if res is not _MARKER: + if res is _MISSING: + warnings.warn("Cannot interpolate variables in string " + "%r (cached)" % (s, ), + UserWarning, + stacklevel=1) + raise KeyError("Cannot interpolate variables in string " + "%r (cached)" % (s, )) + else: + return res res = [] res_append = res.append rest = 0 - use_cache = True + cacheable = True while start != -1: res_append(s[rest:start]) end = s.find(_ENDTOK, start) @@ -968,14 +984,15 @@ elif EMPTY_FILTER in filters: varvalue = _EMPTY_STR else: - self.__interpolation_cache[s] = _MISSING + if use_cache and cacheable: + self.__interpolation_cache[s] = _MISSING warnings.warn("Cannot interpolate variable %r in string " "%r" % (varname, s, ), UserWarning, stacklevel=1) raise if not cacheable: - use_cache = False + cacheable = False varvalue = self._apply_filters(filters, varvalue) rest = end + 2 # @@ -983,7 +1000,7 @@ # the whole `s` is just one expansion # if (start == 0) and (rest == len_s): - if use_cache: + if use_cache and cacheable: self.__interpolation_cache[s] = varvalue return varvalue if varvalue is None: @@ -994,7 +1011,7 @@ start = s.find(_STARTTOK, rest) res_append(s[rest:]) res = _EMPTY_STR.join(res) - if use_cache: + if use_cache and cacheable: self.__interpolation_cache[s] = res return res
--- a/tests/test.py Mon Mar 07 09:11:22 2022 +0100 +++ b/tests/test.py Fri Mar 11 01:53:08 2022 +0100 @@ -439,10 +439,31 @@ os.path.join(TESTDATADIR, "conf24.toml")) x = cfg.interpolate_variables("{{intl.cache.items|Empty}}") self.assertEqual(10, x) + x = cfg.interpolate_variables("{{intl.cache.items|Empty}}") + self.assertEqual(10, x) + + def test12a_Empty_filter_pass_through_without_cache(self): + cfg = self._load(os.path.join(TESTDATADIR, "conf20.yml"), + os.path.join(TESTDATADIR, "conf21.yml"), + os.path.join(TESTDATADIR, "conf22.ini"), + os.path.join(TESTDATADIR, "conf23.json"), + os.path.join(TESTDATADIR, "conf24.toml")) + cfg.disable_cache() + x = cfg.interpolate_variables("{{intl.cache.items|Empty}}") + self.assertEqual(10, x) + x = cfg.interpolate_variables("{{intl.cache.items|Empty}}") + self.assertEqual(10, x) def test13_keyerror(self): cfg = self._load(os.path.join(TESTDATADIR, "conf20.yml")) self.assertRaises(KeyError, cfg.getvar_s, "non.existing.key") + self.assertRaises(KeyError, cfg.getvar_s, "non.existing.key") + + def test13a_keyerror_without_cache(self): + cfg = self._load(os.path.join(TESTDATADIR, "conf20.yml")) + cfg.disable_cache() + self.assertRaises(KeyError, cfg.getvar_s, "non.existing.key") + self.assertRaises(KeyError, cfg.getvar_s, "non.existing.key") def test14_getvar_with_default(self): cfg = self._load(os.path.join(TESTDATADIR, "conf20.yml")) @@ -458,6 +479,16 @@ cfg = self._load(os.path.join(TESTDATADIR, "conf20.yml")) self.assertEqual("999", cfg.getvar_s("non.existing.key", default="999")) + self.assertEqual("999", cfg.getvar_s("non.existing.key", + default="999")) + + def test15a_getvar_s_with_default_without_cache(self): + cfg = self._load(os.path.join(TESTDATADIR, "conf20.yml")) + cfg.disable_cache() + self.assertEqual("999", cfg.getvar_s("non.existing.key", + default="999")) + self.assertEqual("999", cfg.getvar_s("non.existing.key", + default="999")) def test15_getvar_s_with_original_default(self): # The default must be the original and not a copy @@ -534,6 +565,20 @@ "intl.fallback", default=None)) + def test20a_getfirstvar_existing_without_cache(self): + cfg = self._load(os.path.join(TESTDATADIR, "conf20.yml")) + cfg.disable_cache() + self.assertEqual("test-configmix", cfg.getfirstvar("intl.domain")) + self.assertEqual("test-configmix", cfg.getfirstvar("intl.domain", + "intl.fallback")) + self.assertEqual("de", cfg.getfirstvar("intl.fallback", + "intl.domain", + default=None)) + + self.assertEqual("de", cfg.getfirstvar("intl.non.existing", + "intl.fallback", + default=None)) + def test21_getfirstvar_s_existing(self): cfg = self._load( os.path.join(TESTDATADIR, "conf20.yml"), @@ -558,6 +603,20 @@ "intl.non.existing", "intl.non.existing2") + def test22a_getfirstvar_s_non_existing_without_cache(self): + cfg = self._load( + os.path.join(TESTDATADIR, "conf20.yml"), + os.path.join(TESTDATADIR, "conf21.yml")) + cfg.disable_cache() + self.assertIsNone( + cfg.getfirstvar_s("intl.non.existing", "intl.non.existing2", + default=None)) + self.assertRaises( + KeyError, + cfg.getfirstvar_s, + "intl.non.existing", + "intl.non.existing2") + def test23_getfirstintvar_s_nonexisting(self): cfg = self._load(os.path.join(TESTDATADIR, "conf20.yml")) self.assertIsNone(cfg.getfirstintvar_s("db.non.existing.key", @@ -868,6 +927,16 @@ cfg = self._load(os.path.join(TESTDATADIR, "conf10.py")) cfg.clear_cache() + def test46_reenable_cache(self): + cfg = self._load(os.path.join(TESTDATADIR, "conf20.yml")) + self.assertTrue(cfg.getvarl() is cfg) + cfg.disable_cache() + self.assertTrue(cfg.getvarl() is cfg) + cfg.clear_cache() + self.assertTrue(cfg.getvarl() is cfg) + cfg.enable_cache() + self.assertTrue(cfg.getvarl() is cfg) + class T02LoadAndMerge(_T02MixinLoadAndMerge, unittest.TestCase):
