def taskRunEval(tree, process, shell, env=None, extra_env = None, context=None, context_vals=None, pre_code = "", expr_code = "", name="", copy=True, tempname='_evaluation_object_', call=None): try: # Prepare code and mode ----------------------------------------------- if (expr_code and name) or (not expr_code and isinstance(tree, ast.Module)): mode = 'exec' else: mode = 'eval' tree = ast.Expression(tree) # Expression code takes precedence over tree code if expr_code: code = expr_code else: code = compile(tree, "<script>", mode) # Set up environment -------------------------------------------------- # avoid deepy copy if specified, or just looking up variable by name if not copy or (isinstance(tree, (ast.Name, ast.Subscript)) and isinstance(tree.ctx, ast.Load)): new_env = dict(get_env(shell.user_ns)) else: new_env = utils.copy_env(get_env(shell.user_ns)) if env is not None: new_env.update(deepcopy(env)) if extra_env is not None: new_env.update(deepcopy(extra_env)) if context is not None: set_context_vals(new_env, context, context_vals) # Execute code -------------------------------------------------------- # Run pre_code if specified if pre_code: exec(pre_code, new_env) if mode == 'eval': obj = eval(code, new_env) else: exec(code, new_env) obj = "exec only" # If name given, get from new_env if name: try: obj = eval(name, new_env) except NameError: return UndefinedValue() # call object if dict with args and kwargs was passed if call is not None: obj = obj(*call['args'], **call['kwargs']) # Set object as temp variable in original environment, so we can # later get its class, etc.., in order to extract it from process get_env(shell.user_ns)[tempname] = obj return str(obj) except Exception as e: return e
def taskRunEval(tree, process, shell, keep_objs_in_env = None, extra_env = None, context=None, context_vals=None, pre_code = "", expr_code = "", name="", tempname='_evaluation_object_', do_exec=False, call=None): new_env = utils.copy_env(get_env(shell.user_ns), keep_objs_in_env) if extra_env is not None: new_env.update(copy.deepcopy(extra_env)) if context is not None: set_context_vals(new_env, context, context_vals) try: # Execute pre_code if specified if pre_code: exec(pre_code, new_env) # If no name given, the object of interest is the output of eval # otherwise, we'll use name to get the object from the environment if not (name or do_exec): mode = 'eval' tree = ast.Expression(tree) else: mode = 'exec' # Expression code takes precedence over tree code if expr_code: code = expr_code else: code = compile(tree, "<script>", mode) if mode == 'eval': obj = eval(code, new_env) else: exec(code, new_env) obj = "exec only" # If name given, get from new_env if name: try: if isinstance(name, ast.AST): obj = eval(compile(tree, "<script>", "eval"), new_env) else: obj = eval(name, new_env) except NameError: return UndefinedValue() # call object if dict with args and kwargs was passed if call is not None: obj = obj(*call['args'], **call['kwargs']) # Set object as temp variable in original environment, so we can # later get its class, etc.., in order to extract it from process get_env(shell.user_ns)[tempname] = obj return str(obj) except Exception as e: return e
def taskRunEval( tree, process, shell, env=None, extra_env=None, context=None, context_vals=None, pre_code="", expr_code="", name="", copy=True, tempname="_evaluation_object_", call=None, ): """ Eval an expression tree (with setting envs, pre_code and/or expr_code) Utility function later wrapped to extract either result (end state of a variable), output (stdout) or error Args: tree (ast): current focused ast, used to get code to execute process: manages shell (see local.py) shell: link to to get process namespace from execution up until now env: update value in focused code by name extra_env: variables to be replaced in focused code by name from extra_env in has_expr context: sum of set_context in sct chain context_vals: extra context argument in has_expr pre_code: argument in has_expr to execute code before evaluating, for example to set a seed expr_code: code to execute instead of focused code name: extract value after executing focused expr_code (~post_code) copy: copy entire env because our expr_code could have side effects tempname: key for the result when it is added to context, only for v1 sct's call: only used in v1 sct's Returns: str: output of the executed code """ try: # Prepare code and mode ----------------------------------------------- # Verify if expr_code is expression code (returning a value) or just runnable code. if ( # expr_code returns nothing and then we will extract a value expr_code and name ) or ( # No expr_code and the tree is of a node type that does not evaluate to have output not expr_code and isinstance(tree, ast.Module) ): # We are not focused on an expression (no output) mode = "exec" else: mode = "eval" # Wrap the focused node in the tree so it can be run with eval() if not isinstance(tree, (ast.Module, ast.Expression, ast.Expr)): tree = ast.Expression(tree) # Expression code takes precedence over tree code if expr_code: code = expr_code tree = ast.parse(code, mode=mode) else: # Compile the tree to Python code code = compile(tree, "<script>", mode) # Set up environment -------------------------------------------------- # Unpack 'container nodes' before checking if a deepcopy is needed if isinstance(tree, ast.Module): tree = tree.body if isinstance(tree, ast.Expression): tree = tree.body if isinstance(tree, ast.Expr): tree = tree.value # Avoid a deep copy if specified or if the ast node type indicates we are looking up a variable by name # ast.Name, ast.Subscript and ast.Load most of the time do not have side effects in the environment, # making a deepcopy unnecessary if not copy or ( isinstance(tree, (ast.Name, ast.Subscript)) and isinstance(tree.ctx, ast.Load) ): new_env = dict(get_env(shell.user_ns)) # shallow copy of env else: # might raise an error if object refuses pickle interface # used by deepcopy to restore class new_env = utils.copy_env(get_env(shell.user_ns)) # Apply additional env and context variables if env is not None: new_env.update(deepcopy(env)) if extra_env is not None: new_env.update(deepcopy(extra_env)) if context is not None: set_context_vals(new_env, context, context_vals) # Execute code -------------------------------------------------------- # Run pre_code if specified if pre_code: exec(pre_code, new_env) if mode == "eval": obj = eval(code, new_env) else: exec(code, new_env) obj = "exec only" # If name given, get from new_env if name: try: obj = eval(name, new_env) except NameError: return UndefinedValue() # Backwards compatibility with v1 SCT's # If object is callable, args and kwargs can be passed in to be used in a call on object if call is not None: obj = obj(*call["args"], **call["kwargs"]) # Set object as temp variable in original environment, so we can # later get its class, etc.., in order to extract it from process get_env(shell.user_ns)[tempname] = obj return str(obj) except Exception as e: return e