diff options
author | Dieter Maurer <d-maurer@users.noreply.github.com> | 2020-07-06 08:01:03 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-06 08:01:03 +0200 |
commit | 0e55a386ffe19764ec11fc687bceb32b934bcc32 (patch) | |
tree | a7db76c78e89f8d2956a912539d9965442985b1a | |
parent | a332b59579d53e07ba9f8256415f8e684b6257ef (diff) | |
parent | 85e911aaa1991a06d6807f8f352d4a3a24090338 (diff) | |
download | zope-tales-0e55a386ffe19764ec11fc687bceb32b934bcc32.tar.gz |
Merge pull request #22 from zopefoundation/path_expr_with_configurable_builtins
Support (some) 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 | 23 |
3 files changed, 36 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..1653c29 100644 --- a/src/zope/tales/tests/test_expressions.py +++ b/src/zope/tales/tests/test_expressions.py @@ -387,6 +387,29 @@ 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 = {'True': True, 'False': False, 'x': None} + + 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") + self.assertIsNotNone(eval("x")) # variable before builtin + class FunctionTests(ExpressionTestBase): |