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
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
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