summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDieter Maurer <d-maurer@users.noreply.github.com>2020-07-06 08:01:03 +0200
committerGitHub <noreply@github.com>2020-07-06 08:01:03 +0200
commit0e55a386ffe19764ec11fc687bceb32b934bcc32 (patch)
treea7db76c78e89f8d2956a912539d9965442985b1a
parenta332b59579d53e07ba9f8256415f8e684b6257ef (diff)
parent85e911aaa1991a06d6807f8f352d4a3a24090338 (diff)
downloadzope-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.rst3
-rw-r--r--src/zope/tales/expressions.py13
-rw-r--r--src/zope/tales/tests/test_expressions.py23
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):