Ejemplo n.º 1
0
Archivo: eval.py Proyecto: pgcudahy/sos
def SoS_exec(script: str,
             _dict: dict = None,
             return_result: bool = True) -> None:
    """Execute a statement."""
    if _dict is None:
        _dict = env.sos_dict.dict()

    if not return_result:
        if env.verbosity == 0:
            with contextlib.redirect_stdout(None):
                exec(
                    compile(script,
                            filename=stmtHash.hash(script),
                            mode="exec"), _dict)
        else:
            exec(compile(script, filename=stmtHash.hash(script), mode="exec"),
                 _dict)
        return None

    try:
        stmts = list(ast.iter_child_nodes(ast.parse(script)))
        if not stmts:
            return
        if isinstance(stmts[-1], ast.Expr):
            # the last one is an expression and we will try to return the results
            # so we first execute the previous statements
            if len(stmts) > 1:
                if env.verbosity == 0:
                    with contextlib.redirect_stdout(None):
                        exec(
                            compile(
                                ast.Module(body=stmts[:-1], type_ignores=[]),
                                filename=stmtHash.hash(script),
                                mode="exec",
                            ),
                            _dict,
                        )
                else:
                    exec(
                        compile(
                            ast.Module(body=stmts[:-1], type_ignores=[]),
                            filename=stmtHash.hash(script),
                            mode="exec",
                        ),
                        _dict,
                    )
            # then we eval the last one
            if env.verbosity == 0:
                with contextlib.redirect_stdout(None):
                    res = eval(
                        compile(
                            ast.Expression(body=stmts[-1].value),
                            filename=stmtHash.hash(script),
                            mode="eval",
                        ),
                        _dict,
                    )
            else:
                res = eval(
                    compile(
                        ast.Expression(body=stmts[-1].value),
                        filename=stmtHash.hash(script),
                        mode="eval",
                    ),
                    _dict,
                )
        else:
            # otherwise we just execute the entire code
            if env.verbosity == 0:
                with contextlib.redirect_stdout(None):
                    exec(
                        compile(script,
                                filename=stmtHash.hash(script),
                                mode="exec"),
                        _dict,
                    )
            else:
                exec(
                    compile(script,
                            filename=stmtHash.hash(script),
                            mode="exec"), _dict)
            res = None
    except SyntaxError as e:
        raise SyntaxError(f"Invalid code {script}: {e}")

    # if check_readonly:
    #    env.sos_dict.check_readonly_vars()
    return res
 def test_module(self):
     body = [ast.Num(42)]
     x = ast.Module(body)
     self.assertEqual(x.body, body)
 def stmt(self, stmt, msg=None):
     mod = ast.Module([stmt])
     self.mod(mod, msg)
Ejemplo n.º 4
0
 def test_invalid_string(self):
     m = ast.Module([ast.Expr(ast.Str(42))])
     ast.fix_missing_locations(m)
     with self.assertRaises(TypeError) as cm:
         compile(m, "<test>", "exec")
     self.assertIn("string must be of type str", str(cm.exception))
Ejemplo n.º 5
0
def make_module(*stmts):
    m = ast.Module(list(stmts))
    return ast.copy_location(m, stmts[0]) if stmts else m
Ejemplo n.º 6
0
 def test_add_single_name_from_import(self):
     tree = ast.Module(body=[])
     self.assertEqual(
         'foo', import_utils.add_import(tree, 'foo', from_import=True))
     self.assertEqual('import foo\n', pasta.dump(tree))
Ejemplo n.º 7
0
 def test_invalid_sum(self):
     pos = dict(lineno=2, col_offset=3)
     m = ast.Module([ast.Expr(ast.expr(**pos), **pos)])
     with self.assertRaises(TypeError) as cm:
         compile(m, "<test>", "exec")
     self.assertIn("but got <_ast.expr", str(cm.exception))
Ejemplo n.º 8
0
def compile_func(gen: 'Generator',
                 func: Callable,
                 strategy: Strategy,
                 with_hooks: bool = False) -> Callable:
    """
    The compilation basically assigns functionality to each of the operator calls as
    governed by the semantics (strategy). Memoization is done with the keys as the `func`,
    the class of the `strategy` and the `with_hooks` argument.

    Args:
        gen (Generator): The generator object containing the function to compile
        func (Callable): The function to compile
        strategy (Strategy): The strategy governing the behavior of the operators
        with_hooks (bool): Whether support for hooks is required

    Returns:
        The compiled function

    """

    if isinstance(strategy, PartialReplayStrategy):
        strategy = strategy.backup_strategy

    if with_hooks:
        cache = CompilationCache.WITH_HOOKS[strategy.__class__]
    else:
        cache = CompilationCache.WITHOUT_HOOKS[strategy.__class__]

    if func in cache:
        return cache[func]

    cache[func] = None

    source_code, start_lineno = inspect.getsourcelines(func)
    source_code = ''.join(source_code)
    f_ast = astutils.parse(textwrap.dedent(source_code))

    # This matches up line numbers with original file and is thus super useful for debugging
    ast.increment_lineno(f_ast, start_lineno - 1)

    #  Remove the ``@generator`` decorator to avoid recursive compilation
    f_ast.decorator_list = [
        d for d in f_ast.decorator_list
        if (not isinstance(d, ast.Name) or d.id != 'generator') and (
            not isinstance(d, ast.Attribute) or d.attr != 'generator') and (
                not (isinstance(d, ast.Call) and isinstance(d.func, ast.Name))
                or d.func.id != 'generator')
    ]

    #  Get all the external dependencies of this function.
    #  We rely on a modified closure function adopted from the ``inspect`` library.
    closure_vars = getclosurevars_recursive(func, f_ast)
    g = {**closure_vars.nonlocals.copy(), **closure_vars.globals.copy()}
    known_ops: Set[str] = strategy.get_known_ops()
    known_methods: Set[str] = strategy.get_known_methods()
    op_info_constructor = OpInfoConstructor()
    delayed_compilations: List[Tuple[Generator, str]] = []

    ops = {}
    handlers = {}
    op_infos = {}
    op_idx: int = 0
    composition_cnt: int = 0
    for n in astutils.preorder_traversal(f_ast):
        if isinstance(n, ast.Call) and isinstance(
                n.func, ast.Name) and n.func.id in known_ops:
            #  Rename the function call, and assign a new function to be called during execution.
            #  This new function is determined by the semantics (strategy) being used for compilation.
            #  Also determine if there any eligible hooks for this operator call.
            op_idx += 1
            handler_idx = len(handlers)
            op_info: OpInfo = op_info_constructor.get(n, gen.name, gen.group)

            n.keywords.append(
                ast.keyword(arg='model',
                            value=ast.Name(_GEN_MODEL_VAR, ast.Load())))

            n.keywords.append(
                ast.keyword(arg='op_info',
                            value=ast.Name(f"_op_info_{op_idx}", ast.Load())))
            op_infos[f"_op_info_{op_idx}"] = op_info

            n.keywords.append(
                ast.keyword(arg='handler',
                            value=ast.Name(f"_handler_{handler_idx}",
                                           ast.Load())))
            handler = strategy.get_op_handler(op_info)
            handlers[f"_handler_{handler_idx}"] = handler

            if not with_hooks:
                n.func = astutils.parse(
                    f"{_GEN_STRATEGY_VAR}.generic_op").value
            else:
                n.keywords.append(
                    ast.keyword(arg=_GEN_HOOK_VAR,
                                value=ast.Name(_GEN_HOOK_VAR, ctx=ast.Load())))
                n.keywords.append(
                    ast.keyword(arg=_GEN_STRATEGY_VAR,
                                value=ast.Name(_GEN_STRATEGY_VAR,
                                               ctx=ast.Load())))

                n.func.id = _GEN_HOOK_WRAPPER
                ops[_GEN_HOOK_WRAPPER] = hook_wrapper

            if returns_lambda(handler):
                n.func = ast.Call(func=n.func,
                                  args=n.args[:],
                                  keywords=n.keywords[:])
                n.keywords = []
                n.args = [n.args[0]]

            ast.fix_missing_locations(n)

        elif isinstance(n, ast.Call) and isinstance(
                n.func, ast.Name) and n.func.id in known_methods:
            #  Similar in spirit to the known_ops case, just much less fancy stuff to do.
            #  Only need to get the right handler which we will achieve by simply making this
            #  a method call instead of a regular call.
            n.func = ast.Attribute(value=ast.Name(_GEN_STRATEGY_VAR,
                                                  ctx=ast.Load()),
                                   attr=n.func.id,
                                   ctx=ast.Load())
            ast.fix_missing_locations(n)

        elif isinstance(n, ast.Call):
            #  Try to check if it is a call to a Generator
            #  TODO : Can we be more sophisticated in our static analysis here
            try:
                function = eval(astunparse.unparse(n.func), g)
            except:
                continue

            if isinstance(function, Generator):
                call_id = f"{_GEN_COMPOSITION_ID}_{composition_cnt}"
                composition_cnt += 1
                n.func.id = call_id
                n.keywords.append(
                    ast.keyword(arg=_GEN_EXEC_ENV_VAR,
                                value=ast.Name(_GEN_EXEC_ENV_VAR, ast.Load())))
                n.keywords.append(
                    ast.keyword(arg=_GEN_STRATEGY_VAR,
                                value=ast.Name(_GEN_STRATEGY_VAR, ast.Load())))
                n.keywords.append(
                    ast.keyword(arg=_GEN_MODEL_VAR,
                                value=ast.Name(_GEN_MODEL_VAR, ast.Load())))
                n.keywords.append(
                    ast.keyword(arg=_GEN_HOOK_VAR,
                                value=ast.Name(_GEN_HOOK_VAR, ast.Load())))
                ast.fix_missing_locations(n)

                #  We delay compilation to handle mutually recursive generators
                delayed_compilations.append((function, call_id))

            elif function is CallGenerator:
                wrapped_func = n.args[0]
                n.func = wrapped_func.func
                n.args = wrapped_func.args[:]
                n.keywords = wrapped_func.keywords[:]
                n.keywords.append(
                    ast.keyword(arg=_GEN_EXEC_ENV_VAR,
                                value=ast.Name(_GEN_EXEC_ENV_VAR, ast.Load())))
                ast.fix_missing_locations(n)

    #  Add the execution environment argument to the function
    f_ast.args.kwonlyargs.append(
        ast.arg(arg=_GEN_EXEC_ENV_VAR, annotation=None))
    f_ast.args.kw_defaults.append(ast.NameConstant(value=None))

    #  Add the strategy argument to the function
    f_ast.args.kwonlyargs.append(
        ast.arg(arg=_GEN_STRATEGY_VAR, annotation=None))
    f_ast.args.kw_defaults.append(ast.NameConstant(value=None))

    #  Add the strategy argument to the function
    f_ast.args.kwonlyargs.append(ast.arg(arg=_GEN_MODEL_VAR, annotation=None))
    f_ast.args.kw_defaults.append(ast.NameConstant(value=None))

    #  Add the hook argument to the function
    f_ast.args.kwonlyargs.append(ast.arg(arg=_GEN_HOOK_VAR, annotation=None))
    f_ast.args.kw_defaults.append(ast.NameConstant(value=None))
    ast.fix_missing_locations(f_ast)

    #  New name so it doesn't clash with original
    func_name = f"{_GEN_COMPILED_TARGET_ID}_{len(cache)}"

    g.update({k: v for k, v in ops.items()})
    g.update({k: v for k, v in handlers.items()})
    g.update({k: v for k, v in op_infos.items()})

    module = ast.Module()
    module.body = [f_ast]

    #  Passing ``g`` to exec allows us to execute all the new functions
    #  we assigned to every operator call in the previous AST walk
    filename = inspect.getabsfile(func)
    exec(compile(module, filename=filename, mode="exec"), g)
    result = g[func.__name__]
    g["__name__"] = filename

    if inspect.ismethod(func):
        result = result.__get__(func.__self__, func.__self__.__class__)

    #  Restore the correct namespace so that tracebacks contain actual function names
    g[gen.name] = gen
    g[func_name] = result

    cache[func] = result

    #  Handle the delayed compilations now that we have populated the cache
    for gen, call_id in delayed_compilations:
        compiled_func = compile_func(gen, gen.func, strategy, with_hooks)
        if gen.caching and isinstance(strategy, DfsStrategy):
            #  Add instructions for using cached result if any
            g[call_id] = cache_wrapper(compiled_func)

        else:
            g[call_id] = compiled_func

    return result
Ejemplo n.º 9
0
    def test_empty_init(self):
        # Jython 2.5.0 did not allow empty constructors for many ast node types
        # but CPython ast nodes do allow this.  For the moment, I don't see a
        # reason to allow construction of the super types (like ast.AST and
        # ast.stmt) as well as the op types that are implemented as enums in
        # Jython (like boolop), but I've left them in but commented out for
        # now.  We may need them in the future since CPython allows this, but
        # it may fall under implementation detail.

        #ast.AST()
        ast.Add()
        ast.And()
        ast.Assert()
        ast.Assign()
        ast.Attribute()
        ast.AugAssign()
        ast.AugLoad()
        ast.AugStore()
        ast.BinOp()
        ast.BitAnd()
        ast.BitOr()
        ast.BitXor()
        ast.BoolOp()
        ast.Break()
        ast.Call()
        ast.ClassDef()
        ast.Compare()
        ast.Continue()
        ast.Del()
        ast.Delete()
        ast.Dict()
        ast.Div()
        ast.Ellipsis()
        ast.Eq()
        ast.Exec()
        ast.Expr()
        ast.Expression()
        ast.ExtSlice()
        ast.FloorDiv()
        ast.For()
        ast.FunctionDef()
        ast.GeneratorExp()
        ast.Global()
        ast.Gt()
        ast.GtE()
        ast.If()
        ast.IfExp()
        ast.Import()
        ast.ImportFrom()
        ast.In()
        ast.Index()
        ast.Interactive()
        ast.Invert()
        ast.Is()
        ast.IsNot()
        ast.LShift()
        ast.Lambda()
        ast.List()
        ast.ListComp()
        ast.Load()
        ast.Lt()
        ast.LtE()
        ast.Mod()
        ast.Module()
        ast.Mult()
        ast.Name()
        ast.Not()
        ast.NotEq()
        ast.NotIn()
        ast.Num()
        ast.Or()
        ast.Param()
        ast.Pass()
        ast.Pow()
        ast.Print()
        ast.RShift()
        ast.Raise()
        ast.Repr()
        ast.Return()
        ast.Slice()
        ast.Store()
        ast.Str()
        ast.Sub()
        ast.Subscript()
        ast.Suite()
        ast.TryExcept()
        ast.TryFinally()
        ast.Tuple()
        ast.UAdd()
        ast.USub()
        ast.UnaryOp()
        ast.While()
        ast.With()
        ast.Yield()
        ast.alias()
        ast.arguments()
        #ast.boolop()
        #ast.cmpop()
        ast.comprehension()
        #ast.excepthandler()
        #ast.expr()
        #ast.expr_context()
        ast.keyword()
Ejemplo n.º 10
0
 def __init__(self):
     """Instantiate translator."""
     import ast
     self.c_hello = GreeterTranslator(ast.Module())
Ejemplo n.º 11
0
 def sample_from_root(memsize_k, memsize_i, callback):
     root = MyAST(parent=None, node=ast.Module())
     root._sample(memsize_k, memsize_i, callback)
     return root
Ejemplo n.º 12
0
jconf = entry_point.getSparkConf()
jsc = entry_point.getJavaSparkContext()

conf = SparkConf(_jvm=gateway.jvm, _jconf=jconf)

sc = SparkContext(jsc=jsc, gateway=gateway, conf=conf)

spark = SparkSession(sc, entry_point.getSparkSession())
sqlc = spark._wrapped

ama_context = AmaContext(sc, sqlc)

while True:
    actionData = queue.getNext()
    resultQueue = entry_point.getResultQueue(actionData._2())
    actionSource = actionData._1()
    tree = ast.parse(actionSource)

    for node in tree.body:

        wrapper = ast.Module(body=[node])
        try:
            co = compile(wrapper, "<ast>", 'exec')
            exec(co)
            resultQueue.put('success', actionData._2(),
                            codegen.to_source(node), '')
        except:
            resultQueue.put('error', actionData._2(), codegen.to_source(node),
                            str(sys.exc_info()[1]))
    resultQueue.put('completion', '', '', '')
Ejemplo n.º 13
0
def run_cell(droplet_client, code_str, namespace):
    import ast
    import sys
    import time
    import cloudpickle as cp
    import collections.abc
    # https://docs.python.org/3/library/collections.abc.html

    import anna.lattices
    """
    CachedDict provides a caching wrapper around any object
    that exposes a dict interface.

    Does not ensure freshness of get().
    """
    class CachedDict(collections.abc.MutableMapping):
        def __init__(self, dict_to_wrap):
            # dict_to_wrap: the dictionary object to wrap.
            self.dict_to_wrap = dict_to_wrap
            self.dict_cache = dict()

        def __getitem__(self, key, refresh=False):
            # If we are asking for a refresh,
            # or item is not cached, fetch it.
            # Then, serves the item from cache.
            # Note: This does not deal with staleness.
            if refresh or (key not in self.dict_cache):
                self.dict_cache[key] = self.dict_to_wrap[key]
                # If this causes a KeyError from dict_to_wrap,
                # we want it to propagate upwards, so we leave it uncaught.
            return self.dict_cache[key]

        def __setitem__(self, key, value):
            # Write through to backing dict.
            self.dict_to_wrap[key] = value
            # Write to cache too.
            self.dict_cache[key] = value

        def __delitem__(self, key):
            del self.dict_to_wrap[key]
            del self.dict_cache[key]

        def __iter__(self):
            # Currently: just bypass the cache entirely.
            return self.dict_to_wrap.__iter__()

        def __len__(self):
            # Currently: just bypass the cache entirely.
            return self.dict_to_wrap.__len__()

    """
    HydroBackedDict is a dict whose contents are backed by
    the Hydro KVS instead of residing in process memory.
    """

    class HydroBackedDict(collections.abc.MutableMapping):
        # namespace is the permanent global namespace
        # that will be used to store this dict in Hydro.
        def __init__(self, droplet_client, namespace):
            self.droplet_client = droplet_client
            self.namespace = namespace

        def __getitem__(self, key):
            # Convert the key into a global key.
            global_key = self._get_global_key(key)
            # Use this key to get the raw bytes from the KVS.
            item = self.droplet_client.get(global_key)
            if item is None: raise KeyError(key)
            # Deserialize not necessary?.
            return item

        # key: str
        # value: any Python value
        def __setitem__(self, key, value):
            # Convert the key to a global key.
            key = self._get_global_key(key)
            # Serialize the value.
            value = cp.dumps(value)
            # Store it into the kvs.
            self.droplet_client.put(key, value)

        def __delitem__(self, key):
            raise NotImplementedError

        def __iter__(self):
            raise NotImplementedError

        def __len__(self):
            raise NotImplementedError

        # Helper that converts a key for this dict
        # to a global key "<namespace>:key:<key>".
        def _get_global_key(self, key):
            return "{}:key:{}".format(self.namespace, key)

    # Capture stdout and stderr.
    output = []

    class logger:
        def __init__(self, tag):
            self.tag = tag

        def write(self, data):
            output.append((self.tag, data))

    sys.stdout = logger('stdout')
    sys.stderr = logger('stderr')

    # Initialize the program state dictionary.
    hydro_user_ns = HydroBackedDict(droplet_client, namespace)
    # user_ns = CachedDict(hydro_user_ns)
    user_ns = hydro_user_ns  # Disable app-level caching for now.

    # Parse the code to execute.
    nodelist = ast.parse(code_str).body

    # The semantics of cell execution are that we run all statements,
    # but only return the result of the last one.
    nodes_exec = nodelist[:-1]
    nodes_interactive = nodelist[-1:]
    bytecodes = []
    for node in nodes_exec:
        node = ast.Module([node])
        bytecode = compile(node, '<string>', 'exec')
        bytecodes.append(bytecode)

    for node in nodes_interactive:
        node = ast.Interactive([node])
        bytecode = compile(node, '<string>', 'single')
        bytecodes.append(bytecode)

    try:
        for bytecode in bytecodes:
            exec(bytecode, globals(), user_ns)
    except:
        sys.stderr.write(str(sys.exc_info()[1]))

    # XXX DROPLET HACK
    # Droplet can't handle empty lists, so we append None.
    # output.append(None)
    # XXX DROPLET HACK
    # Droplet sorts lists, so we number the list.
    output = list(enumerate(output))

    # Also, get the execution count.
    exc_count = droplet_client.get('{}:exc_count'.format(namespace))
    if exc_count is None: exc_count = 0
    exc_count += 1
    droplet_client.put('{}:exc_count'.format(namespace), exc_count)

    return (exc_count, output)
Ejemplo n.º 14
0
 def test_execute_function(self) -> None:
     module = ast.Module(body=[])
     concat.execute.execute('<test>', module, {})
Ejemplo n.º 15
0
 def test_add_normal_import(self):
     tree = ast.Module(body=[])
     self.assertEqual(
         'a.b.c', import_utils.add_import(tree, 'a.b.c', from_import=False))
     self.assertEqual('import a.b.c\n', pasta.dump(tree))
Ejemplo n.º 16
0
    def _process_function(self, function, namespace, arguments=[]):
        """
        Processes the arguments and body of a user-defined function. If the
        function is recursive, the recursive calls are not processed (otherwise
        this would throw `Saplings` into an infinite loop). If the function
        returns a closure, that function is added to the list of functions in
        the current scope.

        Parameters
        ----------
        function : Function
            function that's being called
        namespace : dict
            namespace within which the function should be processed
        arguments : list, optional
            arguments passed into the function when called (as a list of
            ArgTokens)

        Returns
        -------
        {ObjectNode, Function, Class, ClassInstance, None}
            namespace entity corresponding to the return value of the function;
            None if the function has no return value or returns something we
            don't care about (i.e. something that isn't tracked in the
            namespace)
        """

        parameters = function.def_node.args

        pos_params = [a.arg for a in parameters.args]
        kw_params = [a.arg for a in parameters.kwonlyargs]

        # Namespace entities corresponding to default values
        default_entities, null_defaults = self._process_default_args(
            pos_params, parameters.defaults, namespace)
        kw_default_entities, null_kw_defaults = self._process_default_args(
            kw_params, parameters.kw_defaults, namespace)

        # Update namespace with default values
        namespace = {**namespace, **default_entities, **kw_default_entities}
        for null_arg_name in null_defaults + null_kw_defaults:
            if null_arg_name in namespace:
                del namespace[null_arg_name]
                utils.delete_sub_aliases(null_arg_name, namespace)

        for index, argument in enumerate(arguments):
            if argument.arg_name == '':  # Positional argument
                if index < len(pos_params):
                    arg_name = pos_params[index]
                else:  # *arg
                    self._process_attribute_chain(argument.arg_val)
                    continue
            elif argument.arg_name is not None:  # Keyword argument
                arg_name = argument.arg_name
                if arg_name not in pos_params + kw_params:  # **kwargs
                    self._process_attribute_chain(argument.arg_val)
                    continue
            else:  # **kwargs
                self._process_attribute_chain(argument.arg_val)
                continue

            arg_entity, _ = self._process_attribute_chain(argument.arg_val)
            if not arg_entity:
                if arg_name in namespace:
                    del namespace[arg_name]
                    utils.delete_sub_aliases(arg_name, namespace)

                continue

            utils.delete_sub_aliases(arg_name, namespace)
            namespace[arg_name] = arg_entity

        # TODO (V2): Handle star args and **kwargs (blocked by data structure
        # handling)
        if parameters.vararg and parameters.vararg.arg in namespace:
            del namespace[parameters.vararg.arg]
            utils.delete_sub_aliases(parameters.vararg.arg, namespace)
        if parameters.kwarg and parameters.kwarg.arg in namespace:
            del namespace[parameters.kwarg.arg]
            utils.delete_sub_aliases(parameters.kwarg.arg, namespace)

        # Handles recursive functions by deleting all names of the function node
        for name, node in list(namespace.items()):
            if node == function:
                del namespace[name]

        # Processes function body
        func_saplings = self._process_subtree_in_new_scope(
            ast.Module(body=function.def_node.body), namespace)
        function.called = True
        return_value = func_saplings._return_value

        # If the function returns a closure then treat it like a function
        # defined in the current scope by adding it to self._functions
        if isinstance(return_value, Function):
            return_value.is_closure = True
            # TODO (V1): What if the function is defined in an outer scope but
            # returned in this scope? Then it's not a closure. Handle these.

            if not return_value.called:
                self._functions.add(return_value)
        elif isinstance(return_value, Class):
            for name, entity in return_value.init_instance_namespace.items():
                if isinstance(entity, Function):
                    entity.is_closure = True
                    if not entity.called:
                        self._functions.add(entity)

        return return_value, func_saplings
Ejemplo n.º 17
0
 def test_add_from_import(self):
     tree = ast.Module(body=[])
     self.assertEqual(
         'c', import_utils.add_import(tree, 'a.b.c', from_import=True))
     self.assertEqual('from a.b import c\n', pasta.dump(tree))
Ejemplo n.º 18
0
    def visit_ClassDef(self, node):
        """
        TODO
        """

        for base_node in node.bases:  # TODO (V2): Handle inheritance
            self.visit(ast.Call(func=base_node, args=[], keywords=[]))

        # TODO (V2): Handle metaclasses

        methods, nested_classes, static_variables = [], [], []
        stripped_body = []  # ;)
        for n in node.body:
            if isinstance(n, (ast.FunctionDef, ast.AsyncFunctionDef)):
                for decorator in n.decorator_list:
                    if not hasattr(decorator, "id"):
                        continue

                    if decorator.id == "staticmethod":
                        n.method_type = "static"
                        break
                    elif decorator.id == "classmethod":
                        n.method_type = "class"
                        break
                else:
                    n.method_type = "instance"

                methods.append(n)
                continue
            elif isinstance(n, ast.ClassDef):
                nested_classes.append(n)
                continue
            elif isinstance(n, (ast.Assign, ast.AnnAssign, ast.AugAssign)):
                # BUG: Static variables can be defined without an assignment.
                # For example:
                # class foo(object):
                #     for x in range(10):
                #         pass
                # foo.x is valid.

                targets = [n.target
                           ] if not isinstance(n, ast.Assign) else n.targets
                for target in targets:
                    if isinstance(target, ast.Tuple):
                        for element in target.elts:
                            static_variables.append(
                                utils.stringify_node(element))
                    else:
                        static_variables.append(utils.stringify_node(target))

            stripped_body.append(n)

        class_level_namespace = self._process_subtree_in_new_scope(
            ast.Module(body=stripped_body), self._namespace.copy())._namespace

        class_entity = Class(node, self._namespace.copy())
        self._namespace[node.name] = class_entity

        static_variable_map = {}
        for name, n in class_level_namespace.items():
            if name in static_variables:
                self._namespace['.'.join((node.name, name))] = n
                static_variable_map[name] = n

        def create_callable_attribute_map(callables):
            callable_map = {}
            for callable in callables:
                callable_name = callable.name

                # Handles callables that are accessed by the enclosing class
                adjusted_name = '.'.join((node.name, callable_name))
                callable.name = adjusted_name

                if isinstance(callable,
                              (ast.FunctionDef, ast.AsyncFunctionDef)):
                    entity = self.visit_FunctionDef(callable)
                elif isinstance(callable, ast.ClassDef):
                    entity = self.visit_ClassDef(callable)

                callable.name = callable_name

                if isinstance(entity, Function):
                    entity.method_type = callable.method_type
                    entity.containing_class = class_entity

                callable_map[callable_name] = entity

            return callable_map

        method_map = create_callable_attribute_map(methods)
        nested_class_map = create_callable_attribute_map(nested_classes)

        # Everything here is an attribute of `self`
        class_entity.init_instance_namespace = {
            **static_variable_map,
            **method_map,
            **nested_class_map
        }

        return class_entity
Ejemplo n.º 19
0
 def test_add_import_after_docstring(self):
     tree = ast.Module(body=[ast.Expr(value=ast.Str(s='Docstring.'))])
     self.assertEqual('a', import_utils.add_import(tree, 'a'))
     self.assertEqual('\'Docstring.\'\nimport a\n', pasta.dump(tree))
Ejemplo n.º 20
0
        if final_code:
            # use exec mode to compile the statements except the last statement,
            # so that the last statement's evaluation will be printed to stdout
            code = compile('\n'.join(final_code), '<stdin>', 'exec',
                           ast.PyCF_ONLY_AST, 1)

            to_run_hooks = []
            if (nhooks > 0):
                to_run_hooks = code.body[-nhooks:]

            to_run_exec, to_run_single = (code.body[:-(nhooks + 1)],
                                          [code.body[-(nhooks + 1)]])

            try:
                for node in to_run_exec:
                    mod = ast.Module([node])
                    code = compile(mod, '<stdin>', 'exec')
                    exec(code, _zcUserQueryNameSpace)

                for node in to_run_single:
                    mod = ast.Interactive([node])
                    code = compile(mod, '<stdin>', 'single')
                    exec(code, _zcUserQueryNameSpace)

                for node in to_run_hooks:
                    mod = ast.Module([node])
                    code = compile(mod, '<stdin>', 'exec')
                    exec(code, _zcUserQueryNameSpace)
            except:
                raise Exception(traceback.format_exc())
Ejemplo n.º 21
0
 def test_invalid_identitifer(self):
     m = ast.Module([ast.Expr(ast.Name(42, ast.Load()))])
     ast.fix_missing_locations(m)
     with self.assertRaises(TypeError) as cm:
         compile(m, "<test>", "exec")
     self.assertIn("identifier must be of type str", str(cm.exception))
Ejemplo n.º 22
0
 def visit_Module(self, node):
     self.generic_visit(node)
     importIt = ast.Import(names=[ast.alias(name='itertools', asname=None)])
     return ast.Module(body=([importIt] + node.body))
Ejemplo n.º 23
0
def _debug_scope(func):
    tree = ast.Module(body=get_body_ast(func))
    fill_scopes(tree)
    print tree.scope  # Only shown then test fails
    return tree
Ejemplo n.º 24
0
  def decorator(f):
    tree = ast.parse("with 0:\n" + inspect.getsource(f))
    func_decl = tree.body[0].body[0]
    #print(ast.dump(func_decl))
    #print()
    #print()
    name = f.__name__

    start_block, init = ParsePass().parse_func(f, func_decl)
    start_block = SimplifyPass().simplify(start_block)
    firstline = f.__code__.co_firstlineno
    states = MergePass().generate_states(start_block, firstline)

    ast_stmts = []
    for state in states:
      ast_stmts.append(AstGenerator(wildcard_import).generate_ast(state))

    # print([state.dump() for state in states])

    fsm_name = None
    if wildcard_import:
      fsm_name = ast.Name(id="FSM", ctx=ast.Load(), lineno=firstline, col_offset=0)
    else:
      fsm_name = ast.Attribute(
              value=ast.Name(id="migen", ctx=ast.Load(), lineno=firstline, col_offset=0),
              attr="FSM",
              ctx=ast.Load(),
              lineno=firstline,
              col_offset=0)

    prologue = [
        ast.Assign(
          targets=[ast.Name(id="fsm", ctx=ast.Store(), lineno=firstline, col_offset=0)],
          value=ast.Call(
            func=fsm_name,
            args=[],
            keywords=[
              ast.keyword(
                arg="reset_state",
                value=ast.Str(states[0].name, lineno=firstline, col_offset=0),
                lineno=firstline,
                col_offset=0)
              ],
            lineno=firstline,
            col_offset=0),
          lineno=firstline,
          col_offset=0)
        ]
    epilogue = [
        ast.Return(
          value=ast.Name(id="fsm", ctx=ast.Load(), lineno=firstline, col_offset=0),
          lineno=firstline,
          col_offset=0)
        ]
    new_body = prologue + init + ast_stmts + epilogue

    new_func_decl = ast.Module(body=[
      ast.FunctionDef(
        name=func_decl.name,
        args=func_decl.args,
        body=new_body,
        decorator_list=func_decl.decorator_list[:-1],    # remove this decorator from the list
        returns=func_decl.returns,
        lineno=firstline,
        col_offset=0)
      ])
    # print(ast.dump(new_func_decl))
    if astor is not None:
      f.fsmgen_source = astor.to_source(new_func_decl)
    p = compile(new_func_decl, "<ast>", mode="exec")
    exec(p)
    f.__code__ = locals()[func_decl.name].__code__
    return f
Ejemplo n.º 25
0
    def run_ast_nodes(self,
                      nodelist,
                      cell_name,
                      interactivity='last_expr',
                      compiler=compile,
                      result=None):
        """Run a sequence of AST nodes. The execution mode depends on the
        interactivity parameter.
        Parameters
        ----------
        nodelist : list
          A sequence of AST nodes to run.
        cell_name : str
          Will be passed to the compiler as the filename of the cell. Typically
          the value returned by ip.compile.cache(cell).
        interactivity : str
          'all', 'last', 'last_expr' or 'none', specifying which nodes should be
          run interactively (displaying output from expressions). 'last_expr'
          will run the last node interactively only if it is an expression (i.e.
          expressions in loops or other blocks are not displayed. Other values
          for this parameter will raise a ValueError.
        compiler : callable
          A function with the same interface as the built-in compile(), to turn
          the AST nodes into code objects. Default is the built-in compile().
        result : ExecutionResult, optional
          An object to store exceptions that occur during execution.
        Returns
        -------
        True if an exception occurred while running code, False if it finished
        running.
        """
        if not nodelist:
            return

        if interactivity == 'last_expr':
            if isinstance(nodelist[-1], ast.Expr):
                interactivity = "last"
            else:
                interactivity = "none"

        if interactivity == 'none':
            to_run_exec, to_run_interactive = nodelist, []
        elif interactivity == 'last':
            to_run_exec, to_run_interactive = nodelist[:-1], nodelist[-1:]
        elif interactivity == 'all':
            to_run_exec, to_run_interactive = [], nodelist
        else:
            raise ValueError("Interactivity was %r" % interactivity)

        try:
            for i, node in enumerate(to_run_exec):
                mod = ast.Module([node])
                code = compiler(mod, cell_name, "exec")
                if self.run_code(code, result):
                    return True

            for i, node in enumerate(to_run_interactive):
                mod = ast.Interactive([node])
                code = compiler(mod, cell_name, "single")
                if self.run_code(code, result):
                    return True

            # Flush softspace
            if softspace(sys.stdout, 0):
                print()

        except:
            # It's possible to have exceptions raised here, typically by
            # compilation of odd code (such as a naked 'return' outside a
            # function) that did parse but isn't valid. Typically the exception
            # is a SyntaxError, but it's safest just to catch anything and show
            # the user a traceback.

            # We do only one try/except outside the loop to minimize the impact
            # on runtime, and also because if any node in the node list is
            # broken, we should stop execution completely.
            if result:
                result.error_before_exec = sys.exc_info()[1]
            self.showtraceback()
            return True

        return False
Ejemplo n.º 26
0
Archivo: fol2.py Proyecto: ican2002/xos
    def gen_test(self, fn_template, fol, verdict_var, bindings=None):
        if isinstance(fol, str):
            return self.str_to_ast('%(verdict_var)s = %(constant)s' % {
                'verdict_var': verdict_var,
                'constant': fol
            })

        (k, v), = fol.items()

        if k == 'policy':
            policy_name, object_name = v

            policy_fn = fn_template % policy_name
            call_str = """
if obj.%(object_name)s:
    %(verdict_var)s = %(policy_fn)s(obj.%(object_name)s, ctx)
else:
    # Everybody has access to null objects
    %(verdict_var)s = True
            """ % {
                'verdict_var': verdict_var,
                'policy_fn': policy_fn,
                'object_name': object_name
            }

            call_ast = self.str_to_ast(call_str)
            return call_ast
        if k == 'python':
            try:
                expr_ast = self.str_to_ast(v)
            except SyntaxError:
                raise PolicyException('Syntax error in %s' % v)

            if not isinstance(expr_ast, ast.Expr):
                raise PolicyException('%s is not an expression' % expr_ast)

            assignment_str = """
%(verdict_var)s = (%(escape_expr)s)
            """ % {
                'verdict_var': verdict_var,
                'escape_expr': v
            }

            assignment_ast = self.str_to_ast(assignment_str)
            return assignment_ast
        elif k == 'not':
            top_vvar = verdict_var
            self.verdict_next()
            sub_vvar = self.verdict_variable
            block = self.gen_test(fn_template, v, sub_vvar)
            assignment_str = """
%(verdict_var)s = not (%(subvar)s)
                    """ % {
                'verdict_var': top_vvar,
                'subvar': sub_vvar
            }

            assignment_ast = self.str_to_ast(assignment_str)

            return ast.Module(body=[block, assignment_ast])
        elif k in ['=', 'in']:
            # This is the simplest case, we don't recurse further
            # To use terms that are not simple variables, use
            # the Python escape, e.g. {{ slice.creator is not None }}
            lhs, rhs = v

            assignments = []

            try:
                for t in lhs, rhs:
                    py_expr = t['python']

                    self.verdict_next()
                    vv = self.verdict_variable

                    try:
                        expr_ast = self.str_to_ast(py_expr)
                    except SyntaxError:
                        raise PolicyException('Syntax error in %s' % v)

                    if not isinstance(expr_ast, ast.Expr):
                        raise PolicyException('%s is not an expression' %
                                              expr_ast)

                    assignment_str = """
%(verdict_var)s = (%(escape_expr)s)
                    """ % {
                        'verdict_var': vv,
                        'escape_expr': py_expr
                    }

                    if t == lhs:
                        lhs = vv
                    else:
                        rhs = vv

                    assignment_ast = self.str_to_ast(assignment_str)
                    assignments.append(assignment_ast)
            except TypeError:
                pass

            if k == '=':
                operator = '=='
            elif k == 'in':
                operator = 'in'

            comparison_str = """
%(verdict_var)s = (%(lhs)s %(operator)s %(rhs)s)
            """ % {
                'verdict_var': verdict_var,
                'lhs': lhs,
                'rhs': rhs,
                'operator': operator
            }

            comparison_ast = self.str_to_ast(comparison_str)
            combined_ast = ast.Module(body=assignments + [comparison_ast])

            return combined_ast
        elif k in BINOPS:
            lhs, rhs = v

            top_vvar = verdict_var

            self.verdict_next()
            lvar = self.verdict_variable

            self.verdict_next()
            rvar = self.verdict_variable

            lblock = self.gen_test(fn_template, lhs, lvar)
            rblock = self.gen_test(fn_template, rhs, rvar)

            invert = ''
            if k == '&':
                binop = 'and'
            elif k == '|':
                binop = 'or'
            elif k == '->':
                binop = 'or'
                invert = 'not'

            binop_str = """
%(verdict_var)s = %(invert)s %(lvar)s %(binop)s %(rvar)s
            """ % {
                'verdict_var': top_vvar,
                'invert': invert,
                'lvar': lvar,
                'binop': binop,
                'rvar': rvar
            }

            binop_ast = self.str_to_ast(binop_str)

            combined_ast = ast.Module(body=[lblock, rblock, binop_ast])
            return combined_ast
        elif k == 'exists':
            # If the variable starts with a capital letter,
            # we assume that it is a model. If it starts with
            # a small letter, we assume it is an enumerable
            #
            # We do not support nested exists yet. FIXME.

            var, expr = v

            if var.istitle():
                f = self.fol_to_python_filter(var, expr, django=True)
                entry = f.pop()

                python_str = """
%(verdict_var)s = not not %(model)s.objects.filter(%(query)s)
                """ % {
                    'verdict_var': verdict_var,
                    'model': var,
                    'query': entry
                }

                python_ast = ast.parse(python_str)
            else:
                f = self.fol_to_python_filter(var, expr, django=False)
                entry = f.pop()

                python_str = """
%(verdict_var)s = filter(lambda __elt:%(query)s, %(model)s)
                """ % {
                    'verdict_var': verdict_var,
                    'model': var,
                    'query': entry
                }

                python_ast = ast.parse(python_str)

            return python_ast
        elif k == 'forall':
            var, expr = v

            if var.istitle():
                f = self.fol_to_python_filter(var,
                                              expr,
                                              django=True,
                                              negate=True)
                entry = f.pop()

                self.verdict_next()
                vvar = self.verdict_variable

                python_str = """
%(verdict_var)s = not not %(model)s.objects.filter(%(query)s)
                """ % {
                    'verdict_var': vvar,
                    'model': var,
                    'query': entry
                }

                python_ast = ast.parse(python_str)
            else:
                f = self.fol_to_python_filter(var,
                                              expr,
                                              django=False,
                                              negate=True)
                entry = f.pop()

                python_str = """
%(verdict_var)s = next(elt for elt in %(model)s if %(query)s)
                """ % {
                    'verdict_var': vvar,
                    'model': var,
                    'query': entry
                }

                python_ast = ast.parse(python_str)

            negate_str = """
%(verdict_var)s = not %(vvar)s
            """ % {
                'verdict_var': verdict_var,
                'vvar': vvar
            }

            negate_ast = ast.parse(negate_str)

            return ast.Module(body=[python_ast, negate_ast])
 def expr(self, node, msg=None, *, exc=ValueError):
     mod = ast.Module([ast.Expr(node)])
     self.mod(mod, msg, exc=exc)
Ejemplo n.º 28
0
def make_module(function_asts, main_ast):
    module_body = function_asts
    module_body.append(ast.Expr(value=main_ast))
    module_ast = ast.Module(body=module_body)
    ast.fix_missing_locations(module_ast)
    return module_ast
Ejemplo n.º 29
0
            if mapdef['types']['left'] == 'list':
                sub_expr = [eval_node(sub_expr, ctx)]
            else:
                sub_expr = eval_node(sub_expr, ctx)

        elif isinstance(sub_expr, list):
            list_expr = sub_expr
            sub_expr = []
            for list_node in list_expr:
                if not isinstance(list_node, Node):
                    if isinstance(list_node, str):
                        sub_expr.append(ast.Str(s=list_node, lineno=0,
                                                col_offset=0))
                else:
                    sub_expr.append(eval_node(list_node, ctx))

        elif isinstance(sub_expr, int):
            sub_expr = ast.Num(n=sub_expr, lineno=0, col_offset=0)

        setattr(instance, key, sub_expr)

    return instance

for node in output:
    body.append(eval_node(node))

expr = ast.Module(body, lineno=0, col_offset=0)

eval(compile(ast.parse(expr), '<string>', mode='exec'))

Ejemplo n.º 30
0
 def visit_Module(self, node):
     new_node = ast.Module(self._visit(node.body))
     return new_node