def _six_fail_hook(modname): """Fix six.moves imports due to the dynamic nature of this class. Construct a pseudo-module which contains all the necessary imports for six :param modname: Name of failed module :type modname: str :return: An astroid module :rtype: nodes.Module """ attribute_of = modname != "six.moves" and modname.startswith("six.moves") if modname != "six.moves" and not attribute_of: raise AstroidBuildingError(modname=modname) module = AstroidBuilder(MANAGER).string_build(_IMPORTS) module.name = "six.moves" if attribute_of: # Facilitate import of submodules in Moves start_index = len(module.name) attribute = modname[start_index:].lstrip(".").replace(".", "_") try: import_attr = module.getattr(attribute)[0] except AttributeInferenceError as exc: raise AstroidBuildingError(modname=modname) from exc if isinstance(import_attr, nodes.Import): submodule = MANAGER.ast_from_module_name(import_attr.names[0][0]) return submodule # Let dummy submodule imports pass through # This will cause an Uninferable result, which is okay return module
def _import_gi_module(modname): # we only consider gi.repository submodules if not modname.startswith("gi.repository."): raise AstroidBuildingError(modname=modname) # build astroid representation unless we already tried so if modname not in _inspected_modules: modnames = [modname] optional_modnames = [] # GLib and GObject may have some special case handling # in pygobject that we need to cope with. However at # least as of pygobject3-3.13.91 the _glib module doesn't # exist anymore, so if treat these modules as optional. if modname == "gi.repository.GLib": optional_modnames.append("gi._glib") elif modname == "gi.repository.GObject": optional_modnames.append("gi._gobject") try: modcode = "" for m in itertools.chain(modnames, optional_modnames): try: with warnings.catch_warnings(): # Just inspecting the code can raise gi deprecation # warnings, so ignore them. try: from gi import ( # pylint:disable=import-error PyGIDeprecationWarning, PyGIWarning, ) warnings.simplefilter("ignore", PyGIDeprecationWarning) warnings.simplefilter("ignore", PyGIWarning) except Exception: # pylint:disable=broad-except pass __import__(m) modcode += _gi_build_stub(sys.modules[m]) except ImportError: if m not in optional_modnames: raise except ImportError: astng = _inspected_modules[modname] = None else: astng = AstroidBuilder(AstroidManager()).string_build( modcode, modname) _inspected_modules[modname] = astng else: astng = _inspected_modules[modname] if astng is None: raise AstroidBuildingError(modname=modname) return astng
def ast_from_file(self, filepath, modname=None, fallback=True, source=False): """given a module name, return the astroid object""" try: filepath = get_source_file(filepath, include_no_ext=True) source = True except NoSourceFile: pass if modname is None: try: modname = ".".join(modpath_from_file(filepath)) except ImportError: modname = filepath if (modname in self.astroid_cache and self.astroid_cache[modname].file == filepath): return self.astroid_cache[modname] if source: # pylint: disable=import-outside-toplevel; circular import from astroid.builder import AstroidBuilder return AstroidBuilder(self).file_build(filepath, modname) if fallback and modname: return self.ast_from_module_name(modname) raise AstroidBuildingError("Unable to build an AST for {path}.", path=filepath)
def infer_ast_from_something(self, obj, context=None): """infer astroid for the given class""" if hasattr(obj, "__class__") and not isinstance(obj, type): klass = obj.__class__ else: klass = obj try: modname = klass.__module__ except AttributeError as exc: raise AstroidBuildingError( "Unable to get module for {class_repr}.", cls=klass, class_repr=safe_repr(klass), ) from exc except Exception as exc: raise AstroidImportError( "Unexpected error while retrieving module for {class_repr}:\n" "{error}", cls=klass, class_repr=safe_repr(klass), ) from exc try: name = klass.__name__ except AttributeError as exc: raise AstroidBuildingError( "Unable to get name for {class_repr}:\n", cls=klass, class_repr=safe_repr(klass), ) from exc except Exception as exc: raise AstroidImportError( "Unexpected error while retrieving name for {class_repr}:\n" "{error}", cls=klass, class_repr=safe_repr(klass), ) from exc # take care, on living object __module__ is regularly wrong :( modastroid = self.ast_from_module_name(modname) if klass is obj: for inferred in modastroid.igetattr(name, context): yield inferred else: for inferred in modastroid.igetattr(name, context): yield inferred.instantiate_class()
def ast_from_class(self, klass, modname=None): """get astroid for the given class""" if modname is None: try: modname = klass.__module__ except AttributeError as exc: raise AstroidBuildingError( "Unable to get module for class {class_name}.", cls=klass, class_repr=safe_repr(klass), modname=modname, ) from exc modastroid = self.ast_from_module_name(modname) return modastroid.getattr(klass.__name__)[0] # XXX
def file_build(self, path, modname=None): """Build astroid from a source code file (i.e. from an ast) *path* is expected to be a python source file """ try: stream, encoding, data = open_source_file(path) except OSError as exc: raise AstroidBuildingError( "Unable to load file {path}:\n{error}", modname=modname, path=path, error=exc, ) from exc except (SyntaxError, LookupError) as exc: raise AstroidSyntaxError( "Python 3 encoding specification error or unknown encoding:\n" "{error}", modname=modname, path=path, error=exc, ) from exc except UnicodeError as exc: # wrong encoding # detect_encoding returns utf-8 if no encoding specified raise AstroidBuildingError( "Wrong or no encoding specified for {filename}.", filename=path) from exc with stream: # get module name if necessary if modname is None: try: modname = ".".join(modutils.modpath_from_file(path)) except ImportError: modname = os.path.splitext(os.path.basename(path))[0] # build astroid representation module = self._data_build(data, modname, path) return self._post_build(module, encoding)
def hook(modname: str): if modname == "foo.bar": return unittest raise AstroidBuildingError()
def _six_fail_hook(modname): if modname != 'six.moves': raise AstroidBuildingError(modname=modname) module = AstroidBuilder(MANAGER).string_build(_IMPORTS) module.name = 'six.moves' return module