Example #1
0
 def __init__(self, wrapped):
     try:
         wrapped.__name__
     except AttributeError:
         util.reraise(TypeError('%s must have a __name__ attribute'
                                % wrapped))
     self.wrapped = wrapped
Example #2
0
    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)))
Example #3
0
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))
Example #4
0
    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
Example #5
0
 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
Example #6
0
 def __init__(self, wrapped):
     try:
         wrapped.__name__
     except AttributeError:
         util.reraise(
             TypeError('%s must have a __name__ attribute' % wrapped))
     self.wrapped = wrapped
Example #7
0
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))
Example #8
0
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))
Example #9
0
    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)
Example #10
0
    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)
Example #11
0
 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
Example #12
0
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))
Example #13
0
 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))
Example #15
0
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))
Example #17
0
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))
Example #18
0
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))
Example #19
0
 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
Example #20
0
 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)
Example #22
0
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)
Example #23
0
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))
Example #24
0
    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)
Example #25
0
    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)
Example #26
0
 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()
Example #27
0
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))
Example #28
0
 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()
Example #29
0
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))
Example #30
0
 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)
Example #31
0
 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)
Example #32
0
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
Example #33
0
    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)
Example #34
0
    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)
Example #35
0
 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
Example #36
0
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))
Example #37
0
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))
Example #38
0
    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)))
Example #39
0
 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))