diff options
author | dieter <dieter@handshake.de> | 2020-07-05 15:26:38 +0200 |
---|---|---|
committer | dieter <dieter@handshake.de> | 2020-07-05 15:26:38 +0200 |
commit | c990bcfbc302ad6b13dfe4bd30c6a2a8394186a8 (patch) | |
tree | c23ec7c75f533b1a393ed7046c4692be935b0edf | |
parent | a332b59579d53e07ba9f8256415f8e684b6257ef (diff) | |
download | zope-tales-c990bcfbc302ad6b13dfe4bd30c6a2a8394186a8.tar.gz |
Improve `PathExpr` reusability; allow customizable use of builtins in path expressions
-rw-r--r-- | CHANGES.rst | 3 | ||||
-rw-r--r-- | src/zope/tales/expressions.py | 13 | ||||
-rw-r--r-- | src/zope/tales/tests/test_expressions.py | 22 |
3 files changed, 35 insertions, 3 deletions
diff --git a/CHANGES.rst b/CHANGES.rst index 64a7d92..308dc28 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,7 +5,8 @@ 5.0.3 (unreleased) ================== -- Nothing changed yet. +- Improve `PathExpr` reusability + Provide customizable support for the use of builtins in path expressions 5.0.2 (2020-03-27) diff --git a/src/zope/tales/expressions.py b/src/zope/tales/expressions.py index 10584b9..dd8980c 100644 --- a/src/zope/tales/expressions.py +++ b/src/zope/tales/expressions.py @@ -60,6 +60,8 @@ class SubPathExpr(object): Implementation of a single path expression. """ + ALLOWED_BUILTINS = {} + def __init__(self, path, traverser, engine): self._traverser = traverser self._engine = engine @@ -137,7 +139,12 @@ class SubPathExpr(object): if base == 'CONTEXTS' or not base: # Special base name ob = econtext.contexts else: - ob = vars[base] + try: + ob = vars[base] + except KeyError: + ob = self.ALLOWED_BUILTINS.get(base, _marker) + if ob is _marker: + raise if isinstance(ob, DeferWrapper): ob = ob() @@ -177,6 +184,8 @@ class PathExpr(object): 'nocall', ) + SUBEXPR_FACTORY = SubPathExpr + def __init__(self, name, expr, engine, traverser=simpleTraverse): self._s = expr self._name = name @@ -192,7 +201,7 @@ class PathExpr(object): add(engine.compile('|'.join(paths[i:]).lstrip())) self._hybrid = True break - add(SubPathExpr(path, traverser, engine)._eval) + add(self.SUBEXPR_FACTORY(path, traverser, engine)._eval) def _exists(self, econtext): for expr in self._subexprs: diff --git a/src/zope/tales/tests/test_expressions.py b/src/zope/tales/tests/test_expressions.py index 9158d7b..2369468 100644 --- a/src/zope/tales/tests/test_expressions.py +++ b/src/zope/tales/tests/test_expressions.py @@ -387,6 +387,28 @@ class TestParsedExpressions(ExpressionTestBase): "Invalid variable name" ) + def test_builtins_in_path(self): + from ..tales import ExpressionEngine + from ..expressions import PathExpr, SubPathExpr + + class MySubPathExpr(SubPathExpr): + ALLOWED_BUILTINS = dict(True=True, False=False) + + class MyPathExpr(PathExpr): + SUBEXPR_FACTORY = MySubPathExpr + + engine = ExpressionEngine() + for pt in MyPathExpr._default_type_names: + engine.registerType(pt, MyPathExpr) + + def eval(expr): + return engine.compile(expr)(self.context) + + self.assertTrue(eval("True")) + self.assertFalse(eval("False")) + with self.assertRaises(KeyError): + eval("None") + class FunctionTests(ExpressionTestBase): |