diff options
author | Lars Wirzenius <liw@liw.fi> | 2020-12-02 08:33:00 +0200 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2020-12-02 10:33:06 +0200 |
commit | b06ae1c282075c388999be963a0f3ad4bb15cb29 (patch) | |
tree | 4a2d0550188fdb25c1c544a19ce1c3f7a16fd67e /templates | |
parent | ff07da8028390c9834212f8898c64f8fbcf30bd7 (diff) | |
download | subplot-b06ae1c282075c388999be963a0f3ad4bb15cb29.tar.gz |
feat: allow saving, recalling, and expanding values in steps
Diffstat (limited to 'templates')
-rw-r--r-- | templates/python/context.py | 28 | ||||
-rw-r--r-- | templates/python/context_tests.py | 41 |
2 files changed, 69 insertions, 0 deletions
diff --git a/templates/python/context.py b/templates/python/context.py index 9ecae19..d61316e 100644 --- a/templates/python/context.py +++ b/templates/python/context.py @@ -1,4 +1,5 @@ import logging +import re # Store context between steps. @@ -35,6 +36,33 @@ class Context: logging.debug(f"Context: declared {name}") return self._ns[name] + def remember_value(self, name, value): + ns = self.declare("_values") + if name in ns: + raise KeyError(name) + ns[name] = value + + def recall_value(self, name): + ns = self.declare("_values") + if name not in ns: + raise KeyError(name) + return ns[name] + + def expand_values(self, pattern): + parts = [] + while pattern: + m = re.search(r"(?<!\$)\$\{(?P<name>\S*)\}", pattern) + if not m: + parts.append(pattern) + break + name = m.group("name") + if not name: + raise KeyError("empty name in expansion") + value = self.recall_value(name) + parts.append(value) + pattern = pattern[m.end() :] + return "".join(parts) + class NameSpace: def __init__(self, name): diff --git a/templates/python/context_tests.py b/templates/python/context_tests.py index d878084..c91350e 100644 --- a/templates/python/context_tests.py +++ b/templates/python/context_tests.py @@ -52,6 +52,47 @@ class ContextTests(unittest.TestCase): self.assertTrue("bar" in repr(ctx)) +class ContextMemoryTests(unittest.TestCase): + def test_recall_raises_exception_for_unremembered_value(self): + ctx = Context() + with self.assertRaises(KeyError): + ctx.recall_value("foo") + + def test_recall_returns_remembered_value(self): + ctx = Context() + ctx.remember_value("foo", "bar") + self.assertEqual(ctx.recall_value("foo"), "bar") + + def test_remember_raises_exception_for_previously_remembered(self): + ctx = Context() + ctx.remember_value("foo", "bar") + with self.assertRaises(KeyError): + ctx.remember_value("foo", "bar") + + def test_expand_returns_pattern_without_values_as_is(self): + ctx = Context() + self.assertEqual(ctx.expand_values("foo"), "foo") + + def test_expand_allows_double_dollar_escapes(self): + ctx = Context() + self.assertEqual(ctx.expand_values("$${foo}"), "$${foo}") + + def test_expand_raises_exception_for_empty_name_expansion_as_is(self): + ctx = Context() + with self.assertRaises(KeyError): + ctx.expand_values("${}") + + def test_expand_raises_error_for_unrememebered_values(self): + ctx = Context() + with self.assertRaises(KeyError): + ctx.expand_values("${foo}") + + def test_expands_rememebered_values(self): + ctx = Context() + ctx.remember_value("foo", "bar") + self.assertEqual(ctx.expand_values("${foo}"), "bar") + + class ContextNamepaceTests(unittest.TestCase): def test_explicit_namespaces_are_empty_dicts_initially(self): ctx = Context() |