==============================================
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
  [<Element 'zope3'>, <Element 'python'>]
  >>> 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
  <AutoElement '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...'
