def __init__(self, wrapped): try: wrapped.__name__ except AttributeError: util.reraise(TypeError('%s must have a __name__ attribute' % wrapped)) self.wrapped = wrapped
def igetattr(self, name, context=None): """inferred getattr""" if not context: context = contextmod.InferenceContext() try: # avoid recursively inferring the same attr on the same class if context.push((self._proxied, name)): return # XXX frame should be self._proxied, or not ? get_attr = self.getattr(name, context, lookupclass=False) for stmt in _infer_stmts(self._wrap_attr(get_attr, context), context, frame=self): yield stmt except exceptions.AttributeInferenceError: try: # fallback to class.igetattr since it has some logic to handle # descriptors attrs = self._proxied.igetattr(name, context, class_context=False) for stmt in self._wrap_attr(attrs, context): yield stmt except exceptions.AttributeInferenceError as error: util.reraise(exceptions.InferenceError(**vars(error)))
def infer_subscript(self, context=None): """Inference for subscripts We're understanding if the index is a Const or a slice, passing the result of inference to the value's `getitem` method, which should handle each supported index type accordingly. """ value = next(self.value.infer(context)) if value is util.Uninferable: yield util.Uninferable return index = next(self.slice.infer(context)) if index is util.Uninferable: yield util.Uninferable return if value.__class__ == bases.Instance: index_value = index else: index_value = _SLICE_SENTINEL if isinstance(index, nodes.Const): index_value = index.value elif isinstance(index, nodes.Slice): # Infer slices from the original object. lower = _slice_value(index.lower, context) upper = _slice_value(index.upper, context) step = _slice_value(index.step, context) if all(elem is not _SLICE_SENTINEL for elem in (lower, upper, step)): index_value = slice(lower, upper, step) elif isinstance(index, bases.Instance): index = helpers.class_instance_as_index(index) if index: index_value = index.value else: raise exceptions.InferenceError(node=self, context=context) if index_value is _SLICE_SENTINEL: raise exceptions.InferenceError(node=self, context=context) try: assigned = value.getitem(index_value, context) except (IndexError, TypeError, AttributeError) as exc: util.reraise( exceptions.InferenceError(node=self, error=exc, context=context)) # Prevent inferring if the inferred subscript # is the same as the original subscripted object. if self is assigned or assigned is util.Uninferable: yield util.Uninferable return for inferred in assigned.infer(context): yield inferred # Explicit StopIteration to return error information, see comment # in raise_if_nothing_inferred. raise StopIteration(dict(node=self, context=context))
def getattr(self, name, context=None, lookupclass=True): try: values = self._proxied.instance_attr(name, context) except exceptions.AttributeInferenceError: if self.special_attributes and name in self.special_attributes: return [self.special_attributes.lookup(name)] if lookupclass: # Class attributes not available through the instance # unless they are explicitly defined. return self._proxied.getattr(name, context, class_context=False) util.reraise( exceptions.AttributeInferenceError(target=self, attribute=name, context=context)) # since we've no context information, return matching class members as # well if lookupclass: try: return values + self._proxied.getattr( name, context, class_context=False) except exceptions.AttributeInferenceError: pass return values
def _data_build(self, data, modname, path): """Build tree node from data and add some informations""" try: node = _parse(data + '\n') except (TypeError, ValueError, SyntaxError) as exc: util.reraise( exceptions.AstroidSyntaxError( 'Parsing Python code failed:\n{error}', source=data, modname=modname, path=path, error=exc)) if path is not None: node_file = os.path.abspath(path) else: node_file = '<?>' if modname.endswith('.__init__'): modname = modname[:-9] package = True else: package = path and path.find('__init__.py') > -1 or False builder = rebuilder.TreeRebuilder(self._manager) module = builder.visit_module(node, modname, node_file, package) module._import_from_nodes = builder._import_from_nodes module._delayed_assattr = builder._delayed_assattr return module
def __init__(self, wrapped): try: wrapped.__name__ except AttributeError: util.reraise( TypeError('%s must have a __name__ attribute' % wrapped)) self.wrapped = wrapped
def instance_getitem(self, index, context=None): # Rewrap index to Const for this case if context: new_context = context.clone() else: context = new_context = contextmod.InferenceContext() # Create a new callcontext for providing index as an argument. new_context.callcontext = contextmod.CallContext(args=[index]) new_context.boundnode = self method = next(self.igetattr('__getitem__', context=context)) if not isinstance(method, bases.BoundMethod): raise exceptions.InferenceError( 'Could not find __getitem__ for {node!r}.', node=self, context=context) try: return next(method.infer_call_result(self, new_context)) except StopIteration: util.reraise( exceptions.InferenceError( message='Inference for {node!r}[{index!s}] failed.', node=self, index=index, context=context))
def infer_import_from(self, context=None, asname=True): """infer a ImportFrom node: return the imported module/object""" name = context.lookupname if name is None: raise exceptions.InferenceError(node=self, context=context) if asname: name = self.real_name(name) try: module = self.do_import_module() except exceptions.AstroidBuildingError as exc: util.reraise( exceptions.InferenceError(node=self, error=exc, context=context)) try: context = contextmod.copy_context(context) context.lookupname = name stmts = module.getattr(name, ignore_locals=module is self.root()) return bases._infer_stmts(stmts, context) except exceptions.AttributeInferenceError as error: util.reraise( exceptions.InferenceError(error.message, target=self, attribute=name, context=context))
def ast_from_module_name(self, modname, context_file=None): """given a module name, return the astroid object""" if modname in self.astroid_cache: return self.astroid_cache[modname] if modname == '__main__': return self._build_stub_module(modname) old_cwd = os.getcwd() if context_file: os.chdir(os.path.dirname(context_file)) try: found_spec = self.file_from_module_name(modname, context_file) # pylint: disable=no-member if found_spec.type == spec.ModuleType.PY_ZIPMODULE: # pylint: disable=no-member module = self.zip_import_data(found_spec.location) if module is not None: return module elif found_spec.type in (spec.ModuleType.C_BUILTIN, spec.ModuleType.C_EXTENSION): # pylint: disable=no-member if (found_spec.type == spec.ModuleType.C_EXTENSION and not self._can_load_extension(modname)): return self._build_stub_module(modname) try: module = modutils.load_module_from_name(modname) except Exception as ex: # pylint: disable=broad-except util.reraise(exceptions.AstroidImportError( 'Loading {modname} failed with:\n{error}', modname=modname, path=found_spec.location, error=ex)) return self.ast_from_module(module, modname) elif found_spec.type == spec.ModuleType.PY_COMPILED: raise exceptions.AstroidImportError( "Unable to load compiled module {modname}.", # pylint: disable=no-member modname=modname, path=found_spec.location) elif found_spec.type == spec.ModuleType.PY_NAMESPACE: return self._build_namespace_module(modname, # pylint: disable=no-member found_spec.submodule_search_locations) # pylint: disable=no-member if found_spec.location is None: raise exceptions.AstroidImportError( "Can't find a file for module {modname}.", modname=modname) # pylint: disable=no-member return self.ast_from_file(found_spec.location, modname, fallback=False) except exceptions.AstroidBuildingError as e: for hook in self._failed_import_hooks: try: return hook(modname) except exceptions.AstroidBuildingError: pass raise e finally: os.chdir(old_cwd)
def ast_from_module_name(self, modname, context_file=None): """given a module name, return the astroid object""" if modname in self.astroid_cache: return self.astroid_cache[modname] if modname == '__main__': return self._build_stub_module(modname) old_cwd = os.getcwd() if context_file: os.chdir(os.path.dirname(context_file)) try: found_spec = self.file_from_module_name(modname, context_file) # pylint: disable=no-member if found_spec.type == spec.ModuleType.PY_ZIPMODULE: # pylint: disable=no-member module = self.zip_import_data(found_spec.location) if module is not None: return module elif found_spec.type in (spec.ModuleType.C_BUILTIN, spec.ModuleType.C_EXTENSION): # pylint: disable=no-member if (found_spec.type == spec.ModuleType.C_EXTENSION and not self._can_load_extension(modname)): return self._build_stub_module(modname) try: module = modutils.load_module_from_name(modname) except Exception as ex: # pylint: disable=broad-except util.reraise(exceptions.AstroidImportError( 'Loading {modname} failed with:\n{error}', modname=modname, path=spec.location, error=ex)) return self.ast_from_module(module, modname) elif found_spec.type == spec.ModuleType.PY_COMPILED: raise exceptions.AstroidImportError( "Unable to load compiled module {modname}.", # pylint: disable=no-member modname=modname, path=found_spec.location) elif found_spec.type == spec.ModuleType.PY_NAMESPACE: return self._build_namespace_module(modname, # pylint: disable=no-member found_spec.submodule_search_locations) # pylint: disable=no-member if found_spec.location is None: raise exceptions.AstroidImportError( "Can't find a file for module {modname}.", modname=modname) # pylint: disable=no-member return self.ast_from_file(found_spec.location, modname, fallback=False) except exceptions.AstroidBuildingError as e: for hook in self._failed_import_hooks: try: return hook(modname) except exceptions.AstroidBuildingError: pass raise e finally: os.chdir(old_cwd)
def getattr(self, name, context=None, lookupclass=True): try: values = self._proxied.instance_attr(name, context) except exceptions.AttributeInferenceError: if name == '__class__': return [self._proxied] if lookupclass: # Class attributes not available through the instance # unless they are explicitly defined. if name in ('__name__', '__bases__', '__mro__', '__subclasses__'): return self._proxied.local_attr(name) return self._proxied.getattr(name, context, class_context=False) util.reraise(exceptions.AttributeInferenceError(target=self, attribute=name, context=context)) # since we've no context information, return matching class members as # well if lookupclass: try: return values + self._proxied.getattr(name, context, class_context=False) except exceptions.AttributeInferenceError: pass return values
def infer_subscript(self, context=None): """Inference for subscripts We're understanding if the index is a Const or a slice, passing the result of inference to the value's `getitem` method, which should handle each supported index type accordingly. """ value = next(self.value.infer(context)) if value is util.Uninferable: yield util.Uninferable return index = next(self.slice.infer(context)) if index is util.Uninferable: yield util.Uninferable return if value.__class__ == bases.Instance: index_value = index else: index_value = _SLICE_SENTINEL if isinstance(index, nodes.Const): index_value = index.value elif isinstance(index, nodes.Slice): # Infer slices from the original object. lower = _slice_value(index.lower, context) upper = _slice_value(index.upper, context) step = _slice_value(index.step, context) if all(elem is not _SLICE_SENTINEL for elem in (lower, upper, step)): index_value = slice(lower, upper, step) elif isinstance(index, bases.Instance): index = helpers.class_instance_as_index(index) if index: index_value = index.value else: raise exceptions.InferenceError(node=self, context=context) if index_value is _SLICE_SENTINEL: raise exceptions.InferenceError(node=self, context=context) try: assigned = value.getitem(index_value, context) except (IndexError, TypeError, AttributeError) as exc: util.reraise(exceptions.InferenceError(node=self, error=exc, context=context)) # Prevent inferring if the inferred subscript # is the same as the original subscripted object. if self is assigned or assigned is util.Uninferable: yield util.Uninferable return for inferred in assigned.infer(context): yield inferred # Explicit StopIteration to return error information, see comment # in raise_if_nothing_inferred. raise StopIteration(dict(node=self, context=context))
def parse(string, default=None): string = string or default try: return tuple(int(v) for v in string.split('.')) except ValueError: util.reraise( ValueError('%s is not a correct version : should be X.Y[.Z].' % string))
def infer_global(self, context=None): if context.lookupname is None: raise exceptions.InferenceError(node=self, context=context) try: return bases._infer_stmts(self.root().getattr(context.lookupname), context) except exceptions.AttributeInferenceError as error: util.reraise(exceptions.InferenceError( error.message, target=self, attribute=name, context=context))
def infer_subscript(self, context=None): """Inference for subscripts We're understanding if the index is a Const or a slice, passing the result of inference to the value's `getitem` method, which should handle each supported index type accordingly. """ try: value = next(self.value.infer(context)) except StopIteration: return None if value is util.Uninferable: yield util.Uninferable return None try: index = next(self.slice.infer(context)) except StopIteration: return None if index is util.Uninferable: yield util.Uninferable return None # Try to deduce the index value. index_value = _SUBSCRIPT_SENTINEL if value.__class__ == bases.Instance: index_value = index else: if index.__class__ == bases.Instance: instance_as_index = helpers.class_instance_as_index(index) if instance_as_index: index_value = instance_as_index else: index_value = index if index_value is _SUBSCRIPT_SENTINEL: raise exceptions.InferenceError(node=self, context=context) try: assigned = value.getitem(index_value, context) except (exceptions.AstroidTypeError, exceptions.AstroidIndexError, exceptions.AttributeInferenceError, AttributeError) as exc: util.reraise( exceptions.InferenceError(node=self, error=exc, context=context)) # Prevent inferring if the inferred subscript # is the same as the original subscripted object. if self is assigned or assigned is util.Uninferable: yield util.Uninferable return None for inferred in assigned.infer(context): yield inferred # Explicit StopIteration to return error information, see comment # in raise_if_nothing_inferred. return dict(node=self, context=context)
def with_assigned_stmts(self, node=None, context=None, asspath=None): """Infer names and other nodes from a *with* statement. This enables only inference for name binding in a *with* statement. For instance, in the following code, inferring `func` will return the `ContextManager` class, not whatever ``__enter__`` returns. We are doing this intentionally, because we consider that the context manager result is whatever __enter__ returns and what it is binded using the ``as`` keyword. class ContextManager(object): def __enter__(self): return 42 with ContextManager() as f: pass # ContextManager().infer() will return ContextManager # f.infer() will return 42. Arguments: self: nodes.With node: The target of the assignment, `as (a, b)` in `with foo as (a, b)`. context: TODO asspath: TODO """ mgr = next(mgr for (mgr, vars) in self.items if vars == node) if asspath is None: for result in _infer_context_manager(self, mgr, context): yield result else: for result in _infer_context_manager(self, mgr, context): # Walk the asspath and get the item at the final index. obj = result for index in asspath: if not hasattr(obj, 'elts'): raise exceptions.InferenceError( 'Wrong type ({targets!r}) for {node!r} assignment', node=self, targets=node, assign_path=asspath, context=context) try: obj = obj.elts[index] except IndexError: util.reraise(exceptions.InferenceError( 'Tried to infer a nonexistent target with index {index} ' 'in {node!r}.', node=self, targets=node, assign_path=asspath, context=context)) except TypeError: util.reraise(exceptions.InferenceError( 'Tried to unpack an non-iterable value ' 'in {node!r}.', node=self, targets=node, assign_path=asspath, context=context)) yield obj # Explicit StopIteration to return error information, see comment # in raise_if_nothing_inferred. raise StopIteration(dict(node=self, unknown=node, assign_path=asspath, context=context))
def with_assigned_stmts(self, node=None, context=None, asspath=None): """Infer names and other nodes from a *with* statement. This enables only inference for name binding in a *with* statement. For instance, in the following code, inferring `func` will return the `ContextManager` class, not whatever ``__enter__`` returns. We are doing this intentionally, because we consider that the context manager result is whatever __enter__ returns and what it is binded using the ``as`` keyword. class ContextManager(object): def __enter__(self): return 42 with ContextManager() as f: pass # ContextManager().infer() will return ContextManager # f.infer() will return 42. Arguments: self: nodes.With node: The target of the assignment, `as (a, b)` in `with foo as (a, b)`. context: TODO asspath: TODO """ mgr = next(mgr for (mgr, vars) in self.items if vars == node) if asspath is None: for result in _infer_context_manager(self, mgr, context): yield result else: for result in _infer_context_manager(self, mgr, context): # Walk the asspath and get the item at the final index. obj = result for index in asspath: if not hasattr(obj, 'elts'): raise exceptions.InferenceError( 'Wrong type ({targets!r}) for {node!r} assignment', node=self, targets=node, assign_path=asspath, context=context) try: obj = obj.elts[index] except IndexError: util.reraise( exceptions.InferenceError( 'Tried to infer a nonexistent target with index {index} ' 'in {node!r}.', node=self, targets=node, assign_path=asspath, context=context)) yield obj # Explicit StopIteration to return error information, see comment # in raise_if_nothing_inferred. raise StopIteration( dict(node=self, unknown=node, assign_path=asspath, context=context))
def infer_global(self, context=None): if context.lookupname is None: raise exceptions.InferenceError(node=self, context=context) try: return bases._infer_stmts(self.root().getattr(context.lookupname), context) except exceptions.AttributeInferenceError as error: util.reraise(exceptions.InferenceError( error.message, target=self, attribute=context.lookupname, context=context))
def ast_from_class(self, klass, modname=None): """get astroid for the given class""" if modname is None: try: modname = klass.__module__ except AttributeError: util.reraise(exceptions.AstroidBuildingError( 'Unable to get module for class {class_name}.', cls=klass, class_repr=safe_repr(klass), modname=modname)) modastroid = self.ast_from_module_name(modname) return modastroid.getattr(klass.__name__)[0] # XXX
def sequence_assigned_stmts(self, node=None, context=None, asspath=None): if asspath is None: asspath = [] try: index = self.elts.index(node) except ValueError: util.reraise(exceptions.InferenceError( 'Tried to retrieve a node {node!r} which does not exist', node=self, assign_path=asspath, context=context)) asspath.insert(0, index) return self.parent.assigned_stmts(node=self, context=context, asspath=asspath)
def infer_subscript(self, context=None): """Inference for subscripts We're understanding if the index is a Const or a slice, passing the result of inference to the value's `getitem` method, which should handle each supported index type accordingly. """ value = next(self.value.infer(context)) if value is util.Uninferable: yield util.Uninferable return index = next(self.slice.infer(context)) if index is util.Uninferable: yield util.Uninferable return # Try to deduce the index value. index_value = _SUBSCRIPT_SENTINEL if value.__class__ == bases.Instance: index_value = index else: if index.__class__ == bases.Instance: instance_as_index = helpers.class_instance_as_index(index) if instance_as_index: index_value = instance_as_index else: index_value = index if index_value is _SUBSCRIPT_SENTINEL: raise exceptions.InferenceError(node=self, context=context) try: assigned = value.getitem(index_value, context) except (exceptions.AstroidTypeError, exceptions.AstroidIndexError, exceptions.AttributeInferenceError, AttributeError) as exc: util.reraise(exceptions.InferenceError(node=self, error=exc, context=context)) # Prevent inferring if the inferred subscript # is the same as the original subscripted object. if self is assigned or assigned is util.Uninferable: yield util.Uninferable return for inferred in assigned.infer(context): yield inferred # Explicit StopIteration to return error information, see comment # in raise_if_nothing_inferred. raise StopIteration(dict(node=self, context=context))
def igetattr(self, name, context=None): """Retrieve the inferred values of the given attribute name.""" local_name = self._model.get(name) if local_name: yield local_name return try: mro = self.super_mro() # Don't let invalid MROs or invalid super calls # leak out as is from this function. except exceptions.SuperError as exc: util.reraise(exceptions.AttributeInferenceError( ('Lookup for {name} on {target!r} because super call {super!r} ' 'is invalid.'), target=self, attribute=name, context=context, super_=exc.super_)) except exceptions.MroError as exc: util.reraise(exceptions.AttributeInferenceError( ('Lookup for {name} on {target!r} failed because {cls!r} has an ' 'invalid MRO.'), target=self, attribute=name, context=context, mros=exc.mros, cls=exc.cls)) found = False for cls in mro: if name not in cls.locals: continue found = True for inferred in bases._infer_stmts([cls[name]], context, frame=self): if not isinstance(inferred, scoped_nodes.FunctionDef): yield inferred continue # We can obtain different descriptors from a super depending # on what we are accessing and where the super call is. if inferred.type == 'classmethod': yield bases.BoundMethod(inferred, cls) elif self._scope.type == 'classmethod' and inferred.type == 'method': yield inferred elif self._class_based or inferred.type == 'staticmethod': yield inferred elif bases._is_property(inferred): # TODO: support other descriptors as well. for value in inferred.infer_call_result(self, context): yield value else: yield bases.BoundMethod(inferred, cls) if not found: raise exceptions.AttributeInferenceError(target=self, attribute=name, context=context)
def igetattr(self, name, context=None): """Retrieve the inferred values of the given attribute name.""" if name in self.special_attributes: yield self.special_attributes.lookup(name) return try: mro = self.super_mro() # Don't let invalid MROs or invalid super calls # leak out as is from this function. except exceptions.SuperError as exc: util.reraise(exceptions.AttributeInferenceError( ('Lookup for {name} on {target!r} because super call {super!r} ' 'is invalid.'), target=self, attribute=name, context=context, super_=exc.super_)) except exceptions.MroError as exc: util.reraise(exceptions.AttributeInferenceError( ('Lookup for {name} on {target!r} failed because {cls!r} has an ' 'invalid MRO.'), target=self, attribute=name, context=context, mros=exc.mros, cls=exc.cls)) found = False for cls in mro: if name not in cls.locals: continue found = True for inferred in bases._infer_stmts([cls[name]], context, frame=self): if not isinstance(inferred, scoped_nodes.FunctionDef): yield inferred continue # We can obtain different descriptors from a super depending # on what we are accessing and where the super call is. if inferred.type == 'classmethod': yield bases.BoundMethod(inferred, cls) elif self._scope.type == 'classmethod' and inferred.type == 'method': yield inferred elif self._class_based or inferred.type == 'staticmethod': yield inferred elif bases._is_property(inferred): # TODO: support other descriptors as well. for value in inferred.infer_call_result(self, context): yield value else: yield bases.BoundMethod(inferred, cls) if not found: raise exceptions.AttributeInferenceError(target=self, attribute=name, context=context)
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: util.reraise(exceptions.AstroidBuildingError( 'Unable to get module for {class_repr}.', cls=klass, class_repr=safe_repr(klass))) except Exception as ex: # pylint: disable=broad-except util.reraise(exceptions.AstroidImportError( 'Unexpected error while retrieving module for {class_repr}:\n' '{error}', cls=klass, class_repr=safe_repr(klass), error=ex)) try: name = klass.__name__ except AttributeError: util.reraise(exceptions.AstroidBuildingError( 'Unable to get name for {class_repr}:\n', cls=klass, class_repr=safe_repr(klass))) except Exception as ex: # pylint: disable=broad-except util.reraise(exceptions.AstroidImportError( 'Unexpected error while retrieving name for {class_repr}:\n' '{error}', cls=klass, class_repr=safe_repr(klass), error=ex)) # 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 infer_import(self, context=None, asname=True): """infer an Import node: return the imported module/object""" name = context.lookupname if name is None: raise exceptions.InferenceError(node=self, context=context) try: if asname: yield self.do_import_module(self.real_name(name)) else: yield self.do_import_module(name) except exceptions.AstroidBuildingError as exc: util.reraise(exceptions.InferenceError(node=self, error=exc, context=context))
def infer_import(self, context=None, asname=True): """infer an Import node: return the imported module/object""" name = context.lookupname if name is None: raise exceptions.InferenceError(node=self, context=context) try: if asname: yield self.do_import_module(self.real_name(name)) else: yield self.do_import_module(name) except exceptions.AstroidBuildingError as exc: util.reraise( exceptions.InferenceError(node=self, error=exc, context=context))
def ast_from_module_name(self, modname, context_file=None): """given a module name, return the astroid object""" if modname in self.astroid_cache: return self.astroid_cache[modname] if modname == '__main__': return self._build_stub_module(modname) old_cwd = os.getcwd() if context_file: os.chdir(os.path.dirname(context_file)) try: filepath, mp_type = self.file_from_module_name( modname, context_file) if mp_type == modutils.PY_ZIPMODULE: module = self.zip_import_data(filepath) if module is not None: return module elif mp_type in (imp.C_BUILTIN, imp.C_EXTENSION): if mp_type == imp.C_EXTENSION and not self._can_load_extension( modname): return self._build_stub_module(modname) try: module = modutils.load_module_from_name(modname) except Exception as ex: # pylint: disable=broad-except util.reraise( exceptions.AstroidImportError( 'Loading {modname} failed with:\n{error}', modname=modname, path=filepath, error=ex)) return self.ast_from_module(module, modname) elif mp_type == imp.PY_COMPILED: raise exceptions.AstroidImportError( "Unable to load compiled module {modname}.", modname=modname, path=filepath) if filepath is None: raise exceptions.AstroidImportError( "Can't find a file for module {modname}.", modname=modname) return self.ast_from_file(filepath, modname, fallback=False) except exceptions.AstroidBuildingError as e: for hook in self._failed_import_hooks: try: return hook(modname) except exceptions.AstroidBuildingError: pass raise e finally: os.chdir(old_cwd)
def ast_from_module_name(self, modname, context_file=None): """given a module name, return the astroid object""" if modname in self.astroid_cache: return self.astroid_cache[modname] if modname == '__main__': return self._build_stub_module(modname) old_cwd = os.getcwd() if context_file: os.chdir(os.path.dirname(context_file)) try: filepath, mp_type = self.file_from_module_name(modname, context_file) if mp_type == modutils.PY_ZIPMODULE: module = self.zip_import_data(filepath) if module is not None: return module elif mp_type in (imp.C_BUILTIN, imp.C_EXTENSION): if mp_type == imp.C_EXTENSION and not self._can_load_extension(modname): return self._build_stub_module(modname) try: module = modutils.load_module_from_name(modname) except Exception as ex: # pylint: disable=broad-except util.reraise(exceptions.AstroidImportError( 'Loading {modname} failed with:\n{error}', modname=modname, path=filepath, error=ex)) return self.ast_from_module(module, modname) elif mp_type == imp.PY_COMPILED: raise exceptions.AstroidImportError( "Unable to load compiled module {modname}.", modname=modname, path=filepath) if filepath is None: raise exceptions.AstroidImportError( "Can't find a file for module {modname}.", modname=modname) return self.ast_from_file(filepath, modname, fallback=False) except exceptions.AstroidBuildingError as e: for hook in self._failed_import_hooks: try: return hook(modname) except exceptions.AstroidBuildingError: pass raise e finally: os.chdir(old_cwd)
def _data_build(data, modname, path): """Build tree node from data and add some informations""" try: node = _parse(data + '\n') except (TypeError, ValueError, SyntaxError) as exc: util.reraise(exceptions.AstroidSyntaxError( 'Parsing Python code failed:\n{error}', source=data, modname=modname, path=path, error=exc)) if path is not None: node_file = os.path.abspath(path) else: node_file = '<?>' if modname.endswith('.__init__'): modname = modname[:-9] package = True else: package = path and path.find('__init__.py') > -1 or False builder = rebuilder.TreeRebuilder() module = builder.visit_module(node, modname, node_file, package) return module
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 IOError as exc: util.reraise(exceptions.AstroidBuildingError( 'Unable to load file {path}:\n{error}', modname=modname, path=path, error=exc)) except (SyntaxError, LookupError) as exc: util.reraise(exceptions.AstroidSyntaxError( 'Python 3 encoding specification error or unknown encoding:\n' '{error}', modname=modname, path=path, error=exc)) except UnicodeError: # wrong encoding # detect_encoding returns utf-8 if no encoding specified util.reraise(exceptions.AstroidBuildingError( 'Wrong or no encoding specified for {filename}.', filename=path)) 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 _data_build(self, data, modname, path): """Build tree node from data and add some informations""" try: node = _parse(data + '\n') except (TypeError, ValueError, SyntaxError) as exc: util.reraise(exceptions.AstroidSyntaxError( 'Parsing Python code failed:\n{error}', source=data, modname=modname, path=path, error=exc)) if path is not None: node_file = os.path.abspath(path) else: node_file = '<?>' if modname.endswith('.__init__'): modname = modname[:-9] package = True else: package = path is not None and os.path.splitext(os.path.basename(path))[0] == '__init__' builder = rebuilder.TreeRebuilder(self._manager) module = builder.visit_module(node, modname, node_file, package) module._import_from_nodes = builder._import_from_nodes module._delayed_assattr = builder._delayed_assattr return module
def infer_import_from(self, context=None, asname=True): """infer a ImportFrom node: return the imported module/object""" name = context.lookupname if name is None: raise exceptions.InferenceError(node=self, context=context) if asname: name = self.real_name(name) try: module = self.do_import_module() except exceptions.AstroidBuildingError as exc: util.reraise(exceptions.InferenceError(node=self, error=exc, context=context)) try: context = contextmod.copy_context(context) context.lookupname = name stmts = module.getattr(name, ignore_locals=module is self.root()) return bases._infer_stmts(stmts, context) except exceptions.AttributeInferenceError as error: util.reraise(exceptions.InferenceError( error.message, target=self, attribute=name, context=context))
def instance_getitem(self, index, context=None): # Rewrap index to Const for this case if context: new_context = context.clone() else: context = new_context = contextmod.InferenceContext() # Create a new callcontext for providing index as an argument. new_context.callcontext = contextmod.CallContext(args=[index]) new_context.boundnode = self method = next(self.igetattr('__getitem__', context=context)) if not isinstance(method, bases.BoundMethod): raise exceptions.InferenceError( 'Could not find __getitem__ for {node!r}.', node=self, context=context) try: return next(method.infer_call_result(self, new_context)) except StopIteration: util.reraise(exceptions.InferenceError( message='Inference for {node!r}[{index!s}] failed.', node=self, index=index, context=context))
def igetattr(self, name, context=None): """inferred getattr""" if not context: context = contextmod.InferenceContext() try: # avoid recursively inferring the same attr on the same class if context.push((self._proxied, name)): return # XXX frame should be self._proxied, or not ? get_attr = self.getattr(name, context, lookupclass=False) for stmt in _infer_stmts(self._wrap_attr(get_attr, context), context, frame=self): yield stmt except exceptions.AttributeInferenceError: try: # fallback to class.igetattr since it has some logic to handle # descriptors for stmt in self._wrap_attr(self._proxied.igetattr(name, context), context): yield stmt except exceptions.AttributeInferenceError as error: util.reraise(exceptions.InferenceError(**vars(error)))
def parse(string, default=None): string = string or default try: return tuple(int(v) for v in string.split('.')) except ValueError: util.reraise(ValueError('%s is not a correct version : should be X.Y[.Z].' % version))