def _prepare_global_namespace(
        modules_aliases: NamingScope, ) -> Dict[str, ModuleType]:
        """Provides the required modules under the given aliases.

        :param modules_aliases: The module aliases
        :return: A dictionary of module aliases and the corresponding module
        """
        global_namespace: Dict[str, ModuleType] = {}
        for required_module in modules_aliases.known_name_indices:
            global_namespace[modules_aliases.get_name(
                required_module)] = sys.modules[required_module]
        return global_namespace
Exemplo n.º 2
0
def create_var_name(variable_names: NamingScope, var: vr.VariableReference,
                    load: bool) -> ast.Name:
    """Create a name node for the corresponding variable.

    Args:
        variable_names: the naming scope for the variables
        var: the variable reference
        load: load or store?

    Returns:
        the name node
    """
    return ast.Name(
        id=variable_names.get_name(var),
        ctx=ast.Load() if load else ast.Store(),
    )
Exemplo n.º 3
0
 def _create_ast_imports(
         module_aliases: NamingScope,
         additional_import: Optional[str] = None) -> List[ast.stmt]:
     imports: List[ast.stmt] = []
     if additional_import:
         imports.append(
             ast.Import(
                 names=[ast.alias(name=additional_import, asname=None)]))
     for module_name in module_aliases.known_name_indices:
         imports.append(
             ast.Import(names=[
                 ast.alias(
                     name=module_name,
                     asname=module_aliases.get_name(module_name),
                 )
             ]))
     return imports
Exemplo n.º 4
0
 def _create_ast_imports(
         module_aliases: NamingScope,
         common_modules: Optional[Set[str]] = None) -> List[ast.stmt]:
     imports: List[ast.stmt] = []
     if common_modules is not None:
         for module in common_modules:
             imports.append(
                 ast.Import(names=[ast.alias(name=module, asname=None)]))
     for module_name in module_aliases.known_name_indices:
         imports.append(
             ast.Import(names=[
                 ast.alias(
                     name=module_name,
                     asname=module_aliases.get_name(module_name),
                 )
             ]))
     return imports
Exemplo n.º 5
0
def test_naming_scope_same():
    scope = NamingScope()
    some_object = "something"
    name1 = scope.get_name(some_object)
    name2 = scope.get_name(some_object)
    assert name1 == name2
Exemplo n.º 6
0
def test_naming_scope_known_indices_not_empty():
    scope = NamingScope()
    some_object = "something"
    scope.get_name(some_object)
    assert scope.known_name_indices == {some_object: 0}
Exemplo n.º 7
0
def test_naming_scope_different():
    scope = NamingScope()
    name1 = scope.get_name("one name")
    name2 = scope.get_name("another")
    assert name1 != name2
Exemplo n.º 8
0
class ExecutionContext:
    """Contains information required in the context of an execution.
    e.g. the used variables, modules and
    the AST representation of the statements that should be executed."""
    def __init__(self) -> None:
        """Create new execution context."""
        self._local_namespace: Dict[str, Any] = {}
        self._variable_names = NamingScope()
        self._modules_aliases = NamingScope(prefix="module")
        self._global_namespace: Dict[str, ModuleType] = {}

    @property
    def local_namespace(self) -> Dict[str, Any]:
        """The local namespace.

        Returns:
            The local namespace
        """
        return self._local_namespace

    def get_variable_value(self,
                           variable: vr.VariableReference) -> Optional[Any]:
        """Returns the value that is assigned to the given variable in the local
        namespace.

        Args:
            variable: the variable whose value we want

        Raises:
            ValueError, if the requested variable has no assigned value in this context.

        Returns:
            the assigned value.
        """
        if variable in self._variable_names.known_name_indices:
            name = self._variable_names.get_name(variable)
            if name in self._local_namespace:
                return self._local_namespace.get(name)
        raise ValueError("Variable is not defined in this context")

    @property
    def global_namespace(self) -> Dict[str, ModuleType]:
        """The global namespace.

        Returns:
            The global namespace
        """
        return self._global_namespace

    def executable_node_for(
        self,
        statement: stmt.Statement,
    ) -> ast.Module:
        """Transforms the given statement in an executable ast node.

        Args:
            statement: The statement that should be converted.

        Returns:
            An executable ast node.
        """
        modules_before = len(self._modules_aliases.known_name_indices)
        visitor = stmt_to_ast.StatementToAstVisitor(self._modules_aliases,
                                                    self._variable_names)
        statement.accept(visitor)
        if modules_before != len(self._modules_aliases.known_name_indices):
            # new module added
            # TODO(fk) cleaner solution?
            self._global_namespace = ExecutionContext._create_global_namespace(
                self._modules_aliases)
        assert (len(visitor.ast_nodes) == 1
                ), "Expected statement to produce exactly one ast node"
        return ExecutionContext._wrap_node_in_module(visitor.ast_nodes[0])

    @staticmethod
    def _wrap_node_in_module(node: ast.stmt) -> ast.Module:
        """Wraps the given node in a module, such that it can be executed.

        Args:
            node: The node to wrap

        Returns:
            The module wrapping the node
        """
        ast.fix_missing_locations(node)
        return ast.Module(body=[node], type_ignores=[])

    @staticmethod
    def _create_global_namespace(
        modules_aliases: NamingScope, ) -> Dict[str, ModuleType]:
        """Provides the required modules under the given aliases.

        Args:
            modules_aliases: The module aliases

        Returns:
            A dictionary of module aliases and the corresponding module
        """
        global_namespace: Dict[str, ModuleType] = {}
        for required_module in modules_aliases.known_name_indices:
            global_namespace[modules_aliases.get_name(
                required_module)] = sys.modules[required_module]
        return global_namespace