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