Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """
- Author: Armon Dadgar
- Description:
- This module maintains a stack of Namespaces that are being evaluated on
- a thread level to support modifying the current namespace rather than
- then current global context.
- """
- # Get a thread local storage element
- tlocal = thread_local()
- # Get the current namespace object
- def get_current_namespace():
- """
- <Purpose>
- Gets the current namespace of execution for this thread.
- <Returns>
- An Enhanced Virtual Namespace object. See ImprVirtualNamespace.
- This may return None, in the case that an ImprVirtualNamespace is
- not being evaluated.
- """
- # Try to get the current namespace
- current = None
- # Ignore it if the property isn't set
- try:
- current = tlocal.current_namespace
- except AttributeError:
- pass
- return current
- # Set the current namespace
- def set_current_namespace(space):
- # Set the attribute
- tlocal.current_namespace = space
- # Implements an improved Virtual Namespace to add more functionality
- class ImprVirtualNamespace(object):
- """
- Wraps a normal VirtualNamespace object to provide more functionality.
- """
- def __init__(self,code_str=None,name="<string>",file=None,context=None,virt=None):
- """
- <Purpose>
- Initializes an improved virtual namespace object.
- <Arguments>
- The Improved Virtual Namespace object can be initialized
- from a virtual namespace, a file or from a string code bit. If all are provided,
- then the virtual namespace is used, then the code string is used.
- code: (Optional, String) The code string to initialize from
- file: (Optional, String) The name of the file to read in for the code
- virt: (Optional, VirtualNamespace) A VirtualNamespace object
- Either one is optional, but one of the three is required.
- context: (Optional) A context to associate with this namespace.
- If this is not provided then one must be provided to the call to eval
- name: (Optional, String) See VirtualNamespace.
- <Exceptions>
- As with VirtualNamespace
- """
- # Store the name
- self.name = name
- # Check if we are given a VirtualNamespace object
- if not virt is None:
- self.virt = virt
- else:
- # Get the code
- code = None
- if not file is None:
- try:
- code = open(file).read()
- except:
- raise Exception, "Failed to read code from file: '" + file + "'"
- if not code_str is None:
- code = code_str
- if code is None:
- raise Exception, "Code must be provided as a string or file name!"
- # Store the namespace object
- self.virt = VirtualNamespace(code,name)
- # Store the context
- self.context = context
- # Return the context of this namespace
- def get_context(self):
- """
- Returns the context associated with this namespace.
- """
- return self.context
- # Evaluates this namespace
- def evaluate(self,context=None):
- """
- <Purpose>
- Evaluates the code of this namespace in a context.
- <Arguments>
- context:
- If a context was provided at initialization time, then this is optional.
- Otherwise, a dictionary must be provided to execute in.
- <Exceptions>
- As with the code being evaluated.
- """
- # Backup the current namespace
- original = get_current_namespace()
- # Set the new namespace
- set_current_namespace(self)
- # Get the context to use
- if not context is None:
- self.context = context
- use_context = self.context
- if use_context is None:
- raise Exception, "Must provide a context of execution!"
- # Try to evaluate the code now
- try:
- self.virt.evaluate(use_context)
- except:
- # Restore the namespace
- set_current_namespace(original)
- raise
- finally:
- # Restore the namespace
- set_current_namespace(original)
- # Wrap settimer to persist the current namespace
- def _wrap_settimer(*args,**kwargs):
- # Get the user provided callback
- usr_callback = args[1]
- # Get the current namespace
- current = get_current_namespace()
- # Use a new callback function to persist
- def _wrapped_callback(*args,**kwargs):
- # Set the namespace
- set_current_namespace(current)
- # Call the user function
- usr_callback(*args,**kwargs)
- # Modify args
- args = args[:1] + (_wrapped_callback,) + args[2:]
- # Call settimer now
- return settimer(*args, **kwargs)
- # Wrap waitforconn to persist the current namespace
- def _wrap_waitforconn(*args,**kwargs):
- # Get the user provided callback
- usr_callback = args[2]
- # Get the current namespace
- current = get_current_namespace()
- # Use a new callback function to persist
- def _wrapped_callback(*args,**kwargs):
- # Set the namespace
- set_current_namespace(current)
- # Call the user function
- usr_callback(*args,**kwargs)
- # Modify args
- args = args[:2] + (_wrapped_callback,) + args[3:]
- # Call waitforconn now
- return waitforconn(*args, **kwargs)
- # Wrap recvmess to persist the current namespace
- def _wrap_recvmess(*args,**kwargs):
- # Get the user provided callback
- usr_callback = args[2]
- # Get the current namespace
- current = get_current_namespace()
- # Use a new callback function to persist
- def _wrapped_callback(*args,**kwargs):
- # Set the namespace
- set_current_namespace(current)
- # Call the user function
- usr_callback(*args,**kwargs)
- # Modify args
- args = args[:2] + (_wrapped_callback,) + args[3:]
- # Call recvmess now
- return recvmess(*args,**kwargs)
- # Setup the main namespace
- def _setup_main(space, context):
- # Initialize a ImprVirtualNamespace object
- space = ImprVirtualNamespace(context=context,virt=space)
- # Return the new namespace
- return space,context
- # Modifies the API to support the namespace stack
- def _modify_api():
- # Make get_current_namespace available
- MODIFIED_API["get_current_namespace"] = get_current_namespace
- # Switch VirtualNamespace to ImprVirtualNamespace
- MODIFIED_API["VirtualNamespace"] = ImprVirtualNamespace
- # Change settimer, recvmess and waitforconn to persist
- MODIFIED_API["settimer"] = _wrap_settimer
- MODIFIED_API["recvmess"] = _wrap_recvmess
- MODIFIED_API["waitforconn"] = _wrap_waitforconn
- # Setup a start hook
- HOOKS["start"] = _setup_main
- # Modify the API on initialization
- if "callfunc" in _context and callfunc == "initialize":
- _modify_api()
Add Comment
Please, Sign In to add comment