示例#1
0
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
示例#2
0
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
示例#3
0
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