[Zope-Checkins] CVS: Zope2 - Eval.py:1.1.2.7
shane@digicool.com
shane@digicool.com
Thu, 26 Apr 2001 18:20:28 -0400 (EDT)
Update of /cvs-repository/Zope2/lib/python/RestrictedPython
In directory korak:/tmp/cvs-serv10732
Modified Files:
Tag: RestrictedPythonBranch
Eval.py
Log Message:
Made it possible to optimize unrestricted expressions.
--- Updated File Eval.py in package Zope2 --
--- Eval.py 2001/04/26 19:13:39 1.1.2.6
+++ Eval.py 2001/04/26 22:20:26 1.1.2.7
@@ -95,12 +95,17 @@
def default_read_guard(ob):
# No restrictions.
- return ob
+ return ob
+PROFILE = 0
+
class RestrictionCapableEval:
"""A base class for restricted code.
"""
globals = {'__builtins__': {}}
+ rcode = None # restricted
+ ucode = None # unrestricted
+ used = None
def __init__(self, expr):
"""Create a restricted expression
@@ -111,33 +116,71 @@
globals -- A global namespace.
"""
- global compile_restricted_eval
- if compile_restricted_eval is None:
- # Late binding because this will import the whole
- # compiler suite.
- from RestrictedPython import compile_restricted_eval
-
expr = strip(expr)
self.__name__ = expr
expr = translate(expr, nltosp)
self.expr = expr
- self.code, err, warn, used = compile_restricted_eval(expr, '<string>')
- if err:
- raise SyntaxError, err[0]
- self.used = tuple(used.keys())
+
+ def prepRestrictedCode(self):
+ if self.rcode is None:
+ global compile_restricted_eval
+ if compile_restricted_eval is None:
+ # Late binding because this will import the whole
+ # compiler suite.
+ from RestrictedPython import compile_restricted_eval
+
+ if PROFILE:
+ from time import clock
+ start = clock()
+ co, err, warn, used = compile_restricted_eval(
+ self.expr, '<string>')
+ if PROFILE:
+ end = clock()
+ print 'prepRestrictedCode: %d ms for %s' % (
+ (end - start) * 1000, `self.expr`)
+ if err:
+ raise SyntaxError, err[0]
+ self.used = tuple(used.keys())
+ self.rcode = co
+
+ def prepUnrestrictedCode(self):
+ if self.ucode is None:
+ co = compile(self.expr, '<string>', 'eval')
+ if self.used is None:
+ names=list(co.co_names)
+ used={}
+ i=0
+ code=co.co_code
+ l=len(code)
+ LOAD_NAME=101
+ HAVE_ARGUMENT=90
+ while(i < l):
+ c=ord(code[i])
+ if c==LOAD_NAME:
+ name=names[ord(code[i+1])+256*ord(code[i+2])]
+ used[name]=1
+ i=i+3
+ elif c >= HAVE_ARGUMENT: i=i+3
+ else: i=i+1
+ self.used=tuple(used.keys())
+ self.ucode=co
def eval(self, mapping):
+ self.prepRestrictedCode()
+ code = self.rcode
d = {'_read_': default_read_guard}
+ d.update(self.globals)
+ has_key = d.has_key
for name in self.used:
try:
- d[name] = mapping[name]
+ if not has_key(name):
+ d[name] = mapping[name]
except KeyError:
# Swallow KeyErrors since the expression
# might not actually need the name. If it
# does need the name, a NameError will occur.
pass
- d.update(self.globals)
- return eval(self.code, d)
+ return eval(code, d)
def __call__(self, **kw):
return self.eval(kw)