============================================== Python Execution in Special Dynamic Namespaces ============================================== $Id$ >>> from cybertools.meta import namespace A Very Restricted Basic Namespace ================================= >>> minimal = namespace.BaseNamespace() We >>> code = """ ... print 'Hello' ... # a comment ... print dir('') ... print '__builtins__:', __builtins__ ... output('something') ... a = 'a is a variable' ... if a: ... print a ... """ >>> exec code in minimal Hello ['__add__', ..., 'zfill'] __builtins__: {} something a is a variable Assignments in code executed in a namespace may be accessed as attributes of the namespace later. >>> minimal.a 'a is a variable' By setting the ``__builtins__`` mapping to an empty dictionary the minimal namespace provides a secure restricted execution environment. >>> exec "import os" in minimal Traceback (most recent call last): ... ImportError: __import__ not found >>> exec "f = open('dummy.txt', 'w')" in minimal Traceback (most recent call last): ... NameError: open Elements and sub-elements (children) ------------------------------------ >>> code = """ ... topic('zope3', title='Zope 3')[ ... annotation(author='jim')] ... topic('python')[ ... annotation(author='guido'), ... child('zope3')] ... """ >>> from cybertools.util.jeep import Jeep >>> from cybertools.meta.element import ElementFactory >>> symbols = namespace.BaseNamespace() >>> symbols['topic'] = ElementFactory(symbols, 'topic') >>> symbols['annotation'] = ElementFactory(symbols, 'annotation') >>> symbols['child'] = ElementFactory(symbols, 'child') >>> exec code in symbols >>> symbols.topic.instances [, ] >>> zope3 = symbols.topic.instances[0] >>> dict(zope3.annotation) {'author': 'jim'} >>> zope3.title 'Zope 3' A Namespace Automatically Generating Elements ============================================= >>> auto = namespace.AutoNamespace() >>> exec "print something" in auto something >>> auto.something Execution of Python Code in a Namespace ======================================= To simplify some standard use cases for working with namespaces the module provides two classes for execution of Python code with appropriate simple error handling. Evaluation of Python expressions -------------------------------- When evaluating an expression we always get a pair with the resulting value and an - hopefully empty - error string. >>> ev = namespace.Evaluator(auto) >>> ev.evaluate('25 * 25') (625, '') >>> ev.evaluate('30/0') (None, 'Traceback...ZeroDivisionError...') Trying to execute a statement leads to a syntax error. >>> ev.evaluate('print something_else') (None, 'Traceback...SyntaxError...') But we can explicitly allow the execution of statements. The result of executing a statement is None. >>> ev = namespace.Evaluator(auto, allowExec=True) >>> ev.evaluate('print something_else') something_else (None, '') >>> ev.evaluate('25 * 25') (625, '') Execution of Statements ----------------------- >>> ex = namespace.Executor(auto) >>> ex.execute('number = 25') '' >>> ex.execute('30/0') 'Traceback...ZeroDivisionError...'