Esempio n. 1
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))
Esempio n. 2
0
def tl_infer_binary_op(self, opnode, operator, other, context, method):
    not_implemented = nodes.Const(NotImplemented)
    if isinstance(other, self.__class__) and operator == "+":
        node = self.__class__(parent=opnode)
        node.elts = list(
            itertools.chain(
                _filter_uninferable_nodes(self.elts, context),
                _filter_uninferable_nodes(other.elts, context),
            )
        )
        yield node
    elif isinstance(other, nodes.Const) and operator == "*":
        if not isinstance(other.value, int):
            yield not_implemented
            return
        yield _multiply_seq_by_int(self, opnode, other, context)
    elif isinstance(other, bases.Instance) and operator == "*":
        # Verify if the instance supports __index__.
        as_index = helpers.class_instance_as_index(other)
        if not as_index:
            yield util.Uninferable
        else:
            yield _multiply_seq_by_int(self, opnode, as_index, context)
    else:
        yield not_implemented
Esempio n. 3
0
def tl_infer_binary_op(self, opnode, operator, other, context, method):
    not_implemented = nodes.Const(NotImplemented)
    if isinstance(other, self.__class__) and operator == "+":
        node = self.__class__(parent=opnode)
        node.elts = list(
            itertools.chain(
                _filter_uninferable_nodes(self.elts, context),
                _filter_uninferable_nodes(other.elts, context),
            )
        )
        yield node
    elif isinstance(other, nodes.Const) and operator == "*":
        if not isinstance(other.value, int):
            yield not_implemented
            return
        yield _multiply_seq_by_int(self, opnode, other, context)
    elif isinstance(other, bases.Instance) and operator == "*":
        # Verify if the instance supports __index__.
        as_index = helpers.class_instance_as_index(other)
        if not as_index:
            yield util.Uninferable
        else:
            yield _multiply_seq_by_int(self, opnode, as_index, context)
    else:
        yield not_implemented
Esempio n. 4
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))
Esempio n. 5
0
def infer_subscript(
    self: nodes.Subscript,
    context: InferenceContext | None = None,
    **kwargs: Any
) -> Generator[InferenceResult, None, InferenceErrorInfo | 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.
    """

    found_one = False
    for value in self.value.infer(context):
        if value is util.Uninferable:
            yield util.Uninferable
            return None
        for index in self.slice.infer(context):
            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
            elif 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 InferenceError(node=self, context=context)

            try:
                assigned = value.getitem(index_value, context)
            except (
                    AstroidTypeError,
                    AstroidIndexError,
                    AttributeInferenceError,
                    AttributeError,
            ) as exc:
                raise InferenceError(node=self, context=context) from exc

            # 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
            yield from assigned.infer(context)
            found_one = True

    if found_one:
        return InferenceErrorInfo(node=self, context=context)
    return None
Esempio n. 6
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:
        raise exceptions.InferenceError(node=self, context=context) from exc

    # 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
    yield from assigned.infer(context)

    # Explicit StopIteration to return error information, see comment
    # in raise_if_nothing_inferred.
    return dict(node=self, context=context)
Esempio n. 7
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:
        raise exceptions.InferenceError(node=self, context=context) from exc

    # 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
    yield from assigned.infer(context)

    # Explicit StopIteration to return error information, see comment
    # in raise_if_nothing_inferred.
    return dict(node=self, context=context)
Esempio n. 8
0
def query_subscript(self: nodes.Subscript, 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.
    """

    found_one = False
    for value in self.value.query(context):
        if value is util.Uninferable:
            yield util.Uninferable
            return None
        for index in self.slice.query(context):
            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
            elif 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)
                # print(assigned)
            except (
                    exceptions.AstroidTypeError,
                    exceptions.AstroidIndexError,
                    exceptions.AttributeInferenceError,
                    AttributeError,
            ) as exc:
                raise exceptions.InferenceError(node=self,
                                                context=context) from exc

            # Prevent queriing if the queried subscript
            # is the same as the original subscripted object.
            if self is assigned or assigned is util.Uninferable:
                yield util.Uninferable
                return None
            yield from assigned.query(context)
            found_one = True

    if found_one:
        return dict(node=self, context=context)
    return None
Esempio n. 9
0
def tl_infer_binary_op(
    self,
    opnode: nodes.BinOp,
    operator: str,
    other: nodes.NodeNG,
    context: InferenceContext,
    method: nodes.FunctionDef,
) -> Generator[nodes.NodeNG | type[util.Uninferable], None, None]:
    """Infer a binary operation on a tuple or list.

    The instance on which the binary operation is performed is a tuple
    or list. This refers to the left-hand side of the operation, so:
    'tuple() + 1' or '[] + A()'
    """
    # For tuples and list the boundnode is no longer the tuple or list instance
    context.boundnode = None
    not_implemented = nodes.Const(NotImplemented)
    if isinstance(other, self.__class__) and operator == "+":
        node = self.__class__(parent=opnode)
        node.elts = list(
            itertools.chain(
                _filter_uninferable_nodes(self.elts, context),
                _filter_uninferable_nodes(other.elts, context),
            ))
        yield node
    elif isinstance(other, nodes.Const) and operator == "*":
        if not isinstance(other.value, int):
            yield not_implemented
            return
        yield _multiply_seq_by_int(self, opnode, other, context)
    elif isinstance(other, bases.Instance) and operator == "*":
        # Verify if the instance supports __index__.
        as_index = helpers.class_instance_as_index(other)
        if not as_index:
            yield util.Uninferable
        else:
            yield _multiply_seq_by_int(self, opnode, as_index, context)
    else:
        yield not_implemented