Transforms the Python source code *code* and evaluates it so that the
  *resolve* and *assign* functions are called respectively for when a global
  variable is access or assigned.

  If *resolve* is a mapping, *assign* must be omitted. #KeyError#s raised by
  the mapping are automatically converted to #NameError#s.

  Otherwise, *resolve* and *assign* must be callables that have the same
  interface as `__getitem__()`, and `__setitem__()`. If *assign* is omitted
  in that case, assignments will be redirected to a separate dictionary and
  keys in that dictionary will be checked before continuing with the *resolve*
  callback.

def dynamic_exec(code, resolve, assign=None, delete=None, automatic_builtins=True,
                 filename=None, module_name=None, _type='exec'):
  """
  Transforms the Python source code *code* and evaluates it so that the
  *resolve* and *assign* functions are called respectively for when a global
  variable is access or assigned.

  If *resolve* is a mapping, *assign* must be omitted. #KeyError#s raised by
  the mapping are automatically converted to #NameError#s.

  Otherwise, *resolve* and *assign* must be callables that have the same
  interface as `__getitem__()`, and `__setitem__()`. If *assign* is omitted
  in that case, assignments will be redirected to a separate dictionary and
  keys in that dictionary will be checked before continuing with the *resolve*
  callback.
  """

  parse_filename = filename or '<string>'
  ast_node = transform(ast.parse(code, parse_filename, mode=_type))
  code = compile(ast_node, parse_filename, _type)
  if hasattr(resolve, '__getitem__'):
    if assign is not None:
      raise TypeError('"assign" parameter specified where "resolve" is a mapping')
    if delete is not None:
      raise TypeError('"delete" parameter specified where "resolve" is a mapping')
    input_mapping = resolve

    def resolve(x):
      try:
        return input_mapping[x]
      except KeyError:
        raise NameError(x)

    assign = input_mapping.__setitem__

    delete = input_mapping.__delitem__
  else:
    input_mapping = False

  class DynamicMapping(object):
    _data = {}
    _deleted = set()
    def __repr__(self):
      if input_mapping:
        return 'DynamicMapping({!r})'.format(input_mapping)
      else:
        return 'DynamicMapping(resolve={!r}, assign={!r})'.format(resolve, assign)
    def __getitem__(self, key):
      if key in self._deleted:
        raise NameError(key)
      if assign is None:
        try:
          return self._data[key]
        except KeyError:
          pass  # Continue with resolve()
      try:
        return resolve(key)
      except NameError as exc:
        if automatic_builtins and not key.startswith('_'):
          try:
            return getattr(builtins, key)
          except AttributeError:
            pass
        raise exc
    def __setitem__(self, key, value):
      self._deleted.discard(key)
      if assign is None:
        self._data[key] = value
      else:
        assign(key, value)
    def __delitem__(self, key):
      if delete is None:
        self._deleted.add(key)
      else:
        delete(key)
    def get(self, key, default=None):
      try:
        return self[key]
      except NameError:
        return default

  mapping = DynamicMapping()
  globals_ = {'__dict__': mapping}

  if filename:
    mapping['__file__'] = filename
    globals_['__file__'] = filename

  if module_name:
    mapping['__name__'] = module_name
    globals_['__name__'] = module_name

  return (exec_ if _type == 'exec' else eval)(code, globals_)