Guest User

Untitled

a guest
Jul 16th, 2018
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.48 KB | None | 0 0
  1. """
  2. Author: Armon Dadgar
  3. Description:
  4. This module maintains a stack of Namespaces that are being evaluated on
  5. a thread level to support modifying the current namespace rather than
  6. then current global context.
  7. """
  8.  
  9. # Get a thread local storage element
  10. tlocal = thread_local()
  11.  
  12. # Get the current namespace object
  13. def get_current_namespace():
  14. """
  15. <Purpose>
  16. Gets the current namespace of execution for this thread.
  17.  
  18. <Returns>
  19. An Enhanced Virtual Namespace object. See ImprVirtualNamespace.
  20. This may return None, in the case that an ImprVirtualNamespace is
  21. not being evaluated.
  22. """
  23. # Try to get the current namespace
  24. current = None
  25.  
  26. # Ignore it if the property isn't set
  27. try:
  28. current = tlocal.current_namespace
  29. except AttributeError:
  30. pass
  31.  
  32. return current
  33.  
  34. # Set the current namespace
  35. def set_current_namespace(space):
  36. # Set the attribute
  37. tlocal.current_namespace = space
  38.  
  39.  
  40. # Implements an improved Virtual Namespace to add more functionality
  41. class ImprVirtualNamespace(object):
  42. """
  43. Wraps a normal VirtualNamespace object to provide more functionality.
  44. """
  45.  
  46. def __init__(self,code_str=None,name="<string>",file=None,context=None,virt=None):
  47. """
  48. <Purpose>
  49. Initializes an improved virtual namespace object.
  50.  
  51. <Arguments>
  52. The Improved Virtual Namespace object can be initialized
  53. from a virtual namespace, a file or from a string code bit. If all are provided,
  54. then the virtual namespace is used, then the code string is used.
  55.  
  56. code: (Optional, String) The code string to initialize from
  57. file: (Optional, String) The name of the file to read in for the code
  58. virt: (Optional, VirtualNamespace) A VirtualNamespace object
  59. Either one is optional, but one of the three is required.
  60.  
  61. context: (Optional) A context to associate with this namespace.
  62. If this is not provided then one must be provided to the call to eval
  63.  
  64. name: (Optional, String) See VirtualNamespace.
  65.  
  66. <Exceptions>
  67. As with VirtualNamespace
  68. """
  69. # Store the name
  70. self.name = name
  71.  
  72. # Check if we are given a VirtualNamespace object
  73. if not virt is None:
  74. self.virt = virt
  75.  
  76. else:
  77. # Get the code
  78. code = None
  79. if not file is None:
  80. try:
  81. code = open(file).read()
  82. except:
  83. raise Exception, "Failed to read code from file: '" + file + "'"
  84.  
  85. if not code_str is None:
  86. code = code_str
  87.  
  88. if code is None:
  89. raise Exception, "Code must be provided as a string or file name!"
  90.  
  91. # Store the namespace object
  92. self.virt = VirtualNamespace(code,name)
  93.  
  94. # Store the context
  95. self.context = context
  96.  
  97.  
  98. # Return the context of this namespace
  99. def get_context(self):
  100. """
  101. Returns the context associated with this namespace.
  102. """
  103. return self.context
  104.  
  105.  
  106. # Evaluates this namespace
  107. def evaluate(self,context=None):
  108. """
  109. <Purpose>
  110. Evaluates the code of this namespace in a context.
  111.  
  112. <Arguments>
  113. context:
  114. If a context was provided at initialization time, then this is optional.
  115. Otherwise, a dictionary must be provided to execute in.
  116.  
  117. <Exceptions>
  118. As with the code being evaluated.
  119. """
  120. # Backup the current namespace
  121. original = get_current_namespace()
  122.  
  123. # Set the new namespace
  124. set_current_namespace(self)
  125.  
  126. # Get the context to use
  127. if not context is None:
  128. self.context = context
  129.  
  130. use_context = self.context
  131. if use_context is None:
  132. raise Exception, "Must provide a context of execution!"
  133.  
  134. # Try to evaluate the code now
  135. try:
  136. self.virt.evaluate(use_context)
  137.  
  138. except:
  139. # Restore the namespace
  140. set_current_namespace(original)
  141. raise
  142.  
  143. finally:
  144. # Restore the namespace
  145. set_current_namespace(original)
  146.  
  147.  
  148.  
  149. # Wrap settimer to persist the current namespace
  150. def _wrap_settimer(*args,**kwargs):
  151. # Get the user provided callback
  152. usr_callback = args[1]
  153.  
  154. # Get the current namespace
  155. current = get_current_namespace()
  156.  
  157. # Use a new callback function to persist
  158. def _wrapped_callback(*args,**kwargs):
  159. # Set the namespace
  160. set_current_namespace(current)
  161.  
  162. # Call the user function
  163. usr_callback(*args,**kwargs)
  164.  
  165. # Modify args
  166. args = args[:1] + (_wrapped_callback,) + args[2:]
  167.  
  168. # Call settimer now
  169. return settimer(*args, **kwargs)
  170.  
  171.  
  172. # Wrap waitforconn to persist the current namespace
  173. def _wrap_waitforconn(*args,**kwargs):
  174. # Get the user provided callback
  175. usr_callback = args[2]
  176.  
  177. # Get the current namespace
  178. current = get_current_namespace()
  179.  
  180. # Use a new callback function to persist
  181. def _wrapped_callback(*args,**kwargs):
  182. # Set the namespace
  183. set_current_namespace(current)
  184.  
  185. # Call the user function
  186. usr_callback(*args,**kwargs)
  187.  
  188. # Modify args
  189. args = args[:2] + (_wrapped_callback,) + args[3:]
  190.  
  191. # Call waitforconn now
  192. return waitforconn(*args, **kwargs)
  193.  
  194.  
  195. # Wrap recvmess to persist the current namespace
  196. def _wrap_recvmess(*args,**kwargs):
  197. # Get the user provided callback
  198. usr_callback = args[2]
  199.  
  200. # Get the current namespace
  201. current = get_current_namespace()
  202.  
  203. # Use a new callback function to persist
  204. def _wrapped_callback(*args,**kwargs):
  205. # Set the namespace
  206. set_current_namespace(current)
  207.  
  208. # Call the user function
  209. usr_callback(*args,**kwargs)
  210.  
  211. # Modify args
  212. args = args[:2] + (_wrapped_callback,) + args[3:]
  213.  
  214. # Call recvmess now
  215. return recvmess(*args,**kwargs)
  216.  
  217.  
  218.  
  219. # Setup the main namespace
  220. def _setup_main(space, context):
  221. # Initialize a ImprVirtualNamespace object
  222. space = ImprVirtualNamespace(context=context,virt=space)
  223.  
  224. # Return the new namespace
  225. return space,context
  226.  
  227.  
  228.  
  229. # Modifies the API to support the namespace stack
  230. def _modify_api():
  231. # Make get_current_namespace available
  232. MODIFIED_API["get_current_namespace"] = get_current_namespace
  233.  
  234. # Switch VirtualNamespace to ImprVirtualNamespace
  235. MODIFIED_API["VirtualNamespace"] = ImprVirtualNamespace
  236.  
  237. # Change settimer, recvmess and waitforconn to persist
  238. MODIFIED_API["settimer"] = _wrap_settimer
  239. MODIFIED_API["recvmess"] = _wrap_recvmess
  240. MODIFIED_API["waitforconn"] = _wrap_waitforconn
  241.  
  242. # Setup a start hook
  243. HOOKS["start"] = _setup_main
  244.  
  245.  
  246. # Modify the API on initialization
  247. if "callfunc" in _context and callfunc == "initialize":
  248. _modify_api()
Add Comment
Please, Sign In to add comment