Example #1
0
def handleGlobalDeclarationNode(provider, node, source_ref):

    # On the module level, there is nothing to do.
    if provider.isCompiledPythonModule():
        if shallWarnUnusualCode():
            warning(
                "%s: Using 'global' statement on module level has no effect.",
                source_ref.getAsString(),
            )

        return None

    # Need to catch the error of declaring a parameter variable as global
    # ourselves here. The AST parsing doesn't catch it, so we check here.
    if provider.isExpressionFunctionBody():
        parameters = provider.getParameters()

        for variable_name in node.names:
            if variable_name in parameters.getParameterNames():
                SyntaxErrors.raiseSyntaxError(
                    "name '%s' is %s and global" %
                    (variable_name,
                     "local" if python_version < 300 else "parameter"),
                    source_ref.atColumnNumber(node.col_offset))

    # The module the "global" statement refers to.
    module = provider.getParentModule()

    # Can give multiple names.
    for variable_name in node.names:
        closure_variable = None

        # Re-use already taken global variables, in order to avoid creating yet
        # another instance, esp. as the indications could then potentially not
        # be shared.
        if provider.hasTakenVariable(variable_name):
            closure_variable = provider.getTakenVariable(variable_name)

            # Only global variables count. Could have a closure reference to
            # a location of a parent function here.
            if not closure_variable.isModuleVariable():
                closure_variable = None

        if closure_variable is None:
            module_variable = module.getVariableForAssignment(
                variable_name=variable_name)

            closure_variable = provider.addClosureVariable(
                variable=module_variable)

        assert closure_variable.isModuleVariable()

        if python_version < 340 and \
           provider.isExpressionClassBody() and \
           closure_variable.getName() == "__class__":
            SyntaxErrors.raiseSyntaxError("cannot make __class__ global",
                                          source_ref)

        provider.registerProvidedVariable(variable=closure_variable)

    # Drop this, not really part of our tree.
    return None
Example #2
0
    def computeExpression(self, trace_collection):
        # Many cases to deal with, pylint: disable=too-many-branches

        # TODO: In fact, if the module is not a package, we don't have to insist
        # on the "fromlist" that much, but normally it's not used for anything
        # but packages, so it will be rare.
        self._addUsedModules(trace_collection)

        # Attempt to recurse if not already done.
        if self.recurse_attempted:
            if self.finding == "not-found":
                # Importing and not finding, may raise an exception obviously.
                trace_collection.onExceptionRaiseExit(BaseException)
            else:
                # If we know it exists, only RuntimeError shall occur.
                trace_collection.onExceptionRaiseExit(RuntimeError)

            # We stay here.
            return self, None, None

        module_name = self.subnode_name

        if module_name.isCompileTimeConstant():
            imported_module_name = module_name.getCompileTimeConstant()

            if type(imported_module_name) in (str, unicode):
                # TODO: This is not handling decoding errors all that well.
                if str is not unicode and type(
                        imported_module_name) is unicode:
                    imported_module_name = str(imported_module_name)

                self._attemptRecursion(trace_collection=trace_collection,
                                       module_name=imported_module_name)

                self.recurse_attempted = True

                if self.finding == "absolute" and imported_module_name in hard_modules:
                    if isStandardLibraryPath(self.module_filename):
                        result = ExpressionImportModuleHard(
                            module_name=imported_module_name,
                            source_ref=self.source_ref)

                        return (
                            result,
                            "new_expression",
                            "Lowered import of standard library module %r to hard import."
                            % imported_module_name,
                        )
                    elif shallWarnUnusualCode():
                        unusual_logger.warning(
                            "%s Standard library module %r used from outside path %r."
                            % (
                                self.source_ref.getAsString(),
                                imported_module_name,
                                self.module_filename,
                            ))

                if self.finding == "built-in":
                    if imported_module_name in hard_modules:
                        result = ExpressionImportModuleHard(
                            module_name=imported_module_name,
                            source_ref=self.source_ref)

                        return (
                            result,
                            "new_expression",
                            "Lowered import of built-in module %r to hard import."
                            % imported_module_name,
                        )

                    self.type_shape = tshape_module_builtin
                    self.builtin_module = __import__(imported_module_name)

                self._addUsedModules(trace_collection)
            else:
                # TODO: This doesn't preserve side effects.

                # Non-strings is going to raise an error.
                (
                    new_node,
                    change_tags,
                    message,
                ) = trace_collection.getCompileTimeComputationResult(
                    node=self,
                    computation=lambda: __import__(module_name.
                                                   getCompileTimeConstant()),
                    description=
                    "Replaced '__import__' call with non-string module name argument.",
                )

                # Must fail, must not go on when it doesn't.
                assert change_tags == "new_raise", module_name

                return new_node, change_tags, message

        # Importing may raise an exception obviously, unless we know it will
        # not.
        if self.finding != "built-in":
            trace_collection.onExceptionRaiseExit(BaseException)

        # TODO: May return a module or module variable reference of some sort in
        # the future with embedded modules.
        return self, None, None
Example #3
0
    def computeExpression(self, trace_collection):
        # Attempt to recurse if not already done.
        if self.follow_attempted:
            if self.finding == "not-found":
                # Importing and not finding, may raise an exception obviously.
                trace_collection.onExceptionRaiseExit(BaseException)
            else:
                # If we know it exists, only RuntimeError shall occur.
                trace_collection.onExceptionRaiseExit(RuntimeError)

            # We stay here.
            return self, None, None

        module_name = self.subnode_name

        if module_name.isCompileTimeConstant():
            imported_module_name = module_name.getCompileTimeConstant()

            module_filename = self._attemptFollow(
                module_name=imported_module_name)

            self.follow_attempted = True

            if type(imported_module_name) in (str, unicode):
                imported_module_name = resolveModuleName(imported_module_name)

                if self.finding == "absolute" and imported_module_name in hard_modules:
                    if (isStandardLibraryPath(module_filename)
                            or imported_module_name == "pkg_resources"):
                        result = ExpressionImportModuleHard(
                            module_name=imported_module_name,
                            source_ref=self.source_ref)

                        return (
                            result,
                            "new_expression",
                            "Lowered import of standard library module '%s' to hard import."
                            % imported_module_name.asString(),
                        )
                    elif shallWarnUnusualCode():
                        unusual_logger.warning(
                            "%s: Standard library module '%s' used from outside path %r."
                            % (
                                self.source_ref.getAsString(),
                                imported_module_name.asString(),
                                self.module_filename,
                            ))

                if self.finding == "built-in":
                    if imported_module_name in hard_modules:
                        result = ExpressionImportModuleHard(
                            module_name=imported_module_name,
                            source_ref=self.source_ref)

                        return (
                            result,
                            "new_expression",
                            "Lowered import of built-in module '%s' to hard import."
                            % imported_module_name.asString(),
                        )

                    self.type_shape = tshape_module_builtin
                    self.builtin_module = __import__(imported_module_name)

            else:
                # TODO: This doesn't preserve side effects.

                # Non-strings is going to raise an error.
                (
                    new_node,
                    change_tags,
                    message,
                ) = trace_collection.getCompileTimeComputationResult(
                    node=self,
                    computation=lambda: __import__(module_name.
                                                   getCompileTimeConstant()),
                    description=
                    "Replaced '__import__' call with non-string module name argument.",
                )

                # Must fail, must not go on when it doesn't.
                assert change_tags == "new_raise", module_name

                return new_node, change_tags, message

        # Importing may raise an exception obviously, unless we know it will
        # not.
        if self.finding != "built-in":
            trace_collection.onExceptionRaiseExit(BaseException)

        # TODO: May return a module or module variable reference of some sort in
        # the future with embedded modules.
        return self, None, None