Skip to content

Commit

Permalink
Merge pull request #22 from zopefoundation/path_expr_with_configurabl…
Browse files Browse the repository at this point in the history
…e_builtins

Support (some) builtins in path expressions
  • Loading branch information
d-maurer committed Jul 6, 2020
2 parents a332b59 + 85e911a commit 0e55a38
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 3 deletions.
3 changes: 2 additions & 1 deletion CHANGES.rst
Expand Up @@ -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)
Expand Down
13 changes: 11 additions & 2 deletions src/zope/tales/expressions.py
Expand Up @@ -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
Expand Down Expand Up @@ -137,7 +139,12 @@ def _eval(self, econtext,
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()

Expand Down Expand Up @@ -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
Expand All @@ -192,7 +201,7 @@ def __init__(self, name, expr, engine, traverser=simpleTraverse):
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:
Expand Down
23 changes: 23 additions & 0 deletions src/zope/tales/tests/test_expressions.py
Expand Up @@ -387,6 +387,29 @@ def test_bad_initial_name_subexpr(self):
"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):

Expand Down

0 comments on commit 0e55a38

Please sign in to comment.