Beispiel #1
0
def impl_extend(l, iterable):
    if not isinstance(l, types.ListType):
        return
    if not isinstance(iterable, types.IterableType):
        raise TypingError("extend argument must be iterable")

    _check_for_none_typed(l, 'extend')

    def select_impl():
        if isinstance(iterable, types.ListType):

            def impl(l, iterable):
                if not l._is_mutable():
                    raise ValueError("list is immutable")
                # guard against l.extend(l)
                if l is iterable:
                    iterable = iterable.copy()
                for i in iterable:
                    l.append(i)

            return impl
        else:

            def impl(l, iterable):
                for i in iterable:
                    l.append(i)

            return impl

    if l.is_precise():
        # Handle the precise case.
        return select_impl()
    else:
        # Handle the imprecise case, try to 'guess' the underlying type of the
        # values in the iterable.
        if hasattr(iterable, "dtype"):  # tuples and arrays
            ty = iterable.dtype
        elif hasattr(iterable, "item_type"):  # lists
            ty = iterable.item_type
        elif hasattr(iterable, "yield_type"):  # iterators and generators
            ty = iterable.yield_type
        elif isinstance(iterable, types.UnicodeType):
            ty = iterable
        else:
            raise TypingError("unable to extend list, iterable is missing "
                              "either *dtype*, *item_type* or *yield_type*.")
        l = l.refine(ty)
        # Create the signature that we wanted this impl to have
        sig = typing.signature(types.void, l, iterable)
        return sig, select_impl()
def sdc_pandas_series_operator_comp_binop(self, other):
    """
    Pandas Series operator :attr:`pandas.Series.comp_binop` implementation

    .. only:: developer

    **Test**: python -m sdc.runtests -k sdc.tests.test_series.TestSeries.test_series_op7*
              python -m sdc.runtests -k sdc.tests.test_series.TestSeries.test_series_operator_comp_binop*

    Parameters
    ----------
    series: :obj:`pandas.Series`
        Input series
    other: :obj:`pandas.Series` or :obj:`scalar`
        Series or scalar value to be used as a second argument of binary operation

    Returns
    -------
    :obj:`pandas.Series`
        The result of the operation
    """

    _func_name = 'Operator comp_binop().'
    ty_checker = TypeChecker(_func_name)
    self_is_series, other_is_series = isinstance(self, SeriesType), isinstance(other, SeriesType)
    if not (self_is_series or other_is_series):
        return None

    if not isinstance(self, (SeriesType, types.Number, types.UnicodeType)):
        ty_checker.raise_exc(self, 'pandas.series or scalar', 'self')

    if not isinstance(other, (SeriesType, types.Number, types.UnicodeType)):
        ty_checker.raise_exc(other, 'pandas.series or scalar', 'other')

    operands_are_series = self_is_series and other_is_series
    if operands_are_series:
        series_indexes_comparable = check_types_comparable(self.index, other.index)
        if not series_indexes_comparable:
            raise TypingError('{} Not implemented for series with not-comparable indexes. \
            Given: self.index={}, other.index={}'.format(_func_name, self.index, other.index))

    series_data_comparable = check_types_comparable(self, other)
    if not series_data_comparable:
        raise TypingError('{} Not supported for not-comparable operands. \
        Given: self={}, other={}'.format(_func_name, self, other))

    def series_operator_comp_binop_wrapper(self, other):
        return sdc_comp_binop(self, other)

    return series_operator_comp_binop_wrapper
Beispiel #3
0
    def matmul_typer(self, a, b, out=None):
        """
        Typer function for Numpy matrix multiplication.
        """
        if not isinstance(a, types.Array) or not isinstance(b, types.Array):
            return
        if not all(x.ndim in (1, 2) for x in (a, b)):
            raise TypingError("%s only supported on 1-D and 2-D arrays" %
                              (self.func_name, ))
        # Output dimensionality
        ndims = set([a.ndim, b.ndim])
        if ndims == set([2]):
            # M * M
            out_ndim = 2
        elif ndims == set([1, 2]):
            # M* V and V * M
            out_ndim = 1
        elif ndims == set([1]):
            # V * V
            out_ndim = 0

        if out is not None:
            if out_ndim == 0:
                raise TypeError(
                    "explicit output unsupported for vector * vector")
            elif out.ndim != out_ndim:
                raise TypeError("explicit output has incorrect dimensionality")
            if not isinstance(out, types.Array) or out.layout != 'C':
                raise TypeError("output must be a C-contiguous array")
            all_args = (a, b, out)
        else:
            all_args = (a, b)

        if not (config.DISABLE_PERFORMANCE_WARNINGS or all(x.layout in 'CF'
                                                           for x in (a, b))):
            msg = ("%s is faster on contiguous arrays, called on %s" %
                   (self.func_name, (a, b)))
            warnings.warn(NumbaPerformanceWarning(msg))
        if not all(x.dtype == a.dtype for x in all_args):
            raise TypingError("%s arguments must all have "
                              "the same dtype" % (self.func_name, ))
        if not isinstance(a.dtype, (types.Float, types.Complex)):
            raise TypingError("%s only supported on "
                              "float and complex arrays" % (self.func_name, ))
        if out:
            return out
        elif out_ndim > 0:
            return types.Array(a.dtype, out_ndim, 'C')
        else:
            return a.dtype
Beispiel #4
0
 def __call__(self, *args, **kwargs):
     if kwargs:
         raise TypingError("List() takes no keyword arguments")
     elif args:
         if not 0 <= len(args) <= 1:
             raise TypingError(
                 "List() expected at most 1 argument, got {}".format(
                     len(args)))
         rt = types.ListType(_guess_dtype(args[0]))
         self.attach_sig()
         return Signature(rt, args, None, pysig=self.pysig)
     else:
         item_type = types.undefined
         return types.ListType(item_type)
Beispiel #5
0
 def resolve_argsort(self, ary, args, kws):
     assert not args
     kwargs = dict(kws)
     kind = kwargs.pop('kind', types.StringLiteral('quicksort'))
     if not isinstance(kind, types.StringLiteral):
         raise TypingError('"kind" must be a string literal')
     if kwargs:
         msg = "Unsupported keywords: {!r}"
         raise TypingError(msg.format([k for k in kwargs.keys()]))
     if ary.ndim == 1:
         def argsort_stub(kind='quicksort'):
             pass
         pysig = utils.pysignature(argsort_stub)
         sig = signature(types.Array(types.intp, 1, 'C'), kind).replace(pysig=pysig)
         return sig
Beispiel #6
0
 def typer(a, b):
     if not isinstance(a, types.Array) or not isinstance(b, types.Array):
         return
     if not all(x.ndim == 1 for x in (a, b)):
         raise TypingError("np.vdot() only supported on 1-D arrays")
     if not all(x.layout in 'CF' for x in (a, b)):
         warnings.warn("np.vdot() is faster on contiguous arrays, called on %s"
                       % ((a, b),), NumbaPerformanceWarning)
     if not all(x.dtype == a.dtype for x in (a, b)):
         raise TypingError("np.vdot() arguments must all have "
                           "the same dtype")
     if not isinstance(a.dtype, (types.Float, types.Complex)):
         raise TypingError("np.vdot() only supported on "
                           "float and complex arrays")
     return a.dtype
Beispiel #7
0
    def generic(self, args, kws):
        ufunc = self.ufunc
        base_types, explicit_outputs, ndims, layout = self._handle_inputs(
            ufunc, args, kws)
        ufunc_loop = ufunc_find_matching_loop(ufunc, base_types)
        if ufunc_loop is None:
            raise TypingError("can't resolve ufunc {0} for types {1}".format(
                ufunc.__name__, args))

        # check if all the types involved in the ufunc loop are supported in this mode
        if not supported_ufunc_loop(ufunc, ufunc_loop):
            msg = "ufunc '{0}' using the loop '{1}' not supported in this mode"
            raise TypingError(
                msg=msg.format(ufunc.__name__, ufunc_loop.ufunc_sig))

        # if there is any explicit output type, check that it is valid
        explicit_outputs_np = [as_dtype(tp.dtype) for tp in explicit_outputs]

        # Numpy will happily use unsafe conversions (although it will actually warn)
        if not all(
                np.can_cast(fromty, toty, 'unsafe')
                for (fromty, toty
                     ) in zip(ufunc_loop.numpy_outputs, explicit_outputs_np)):
            msg = "ufunc '{0}' can't cast result to explicit result type"
            raise TypingError(msg=msg.format(ufunc.__name__))

        # A valid loop was found that is compatible. The result of type inference should
        # be based on the explicit output types, and when not available with the type given
        # by the selected NumPy loop
        out = list(explicit_outputs)
        implicit_output_count = ufunc.nout - len(explicit_outputs)
        if implicit_output_count > 0:
            # XXX this is sometimes wrong for datetime64 and timedelta64,
            # as ufunc_find_matching_loop() doesn't do any type inference
            ret_tys = ufunc_loop.outputs[-implicit_output_count:]
            if ndims > 0:
                assert layout is not None
                ret_tys = [
                    types.Array(dtype=ret_ty, ndim=ndims, layout=layout)
                    for ret_ty in ret_tys
                ]
                ret_tys = [
                    resolve_output_type(self.context, args, ret_ty)
                    for ret_ty in ret_tys
                ]
            out.extend(ret_tys)

        return _ufunc_loop_sig(out, args)
def _sentry_safe_cast(fromty, toty):
    """Check and raise TypingError if *fromty* cannot be safely cast to *toty*"""
    tyctxt = cpu_target.typing_context
    fromty, toty = map(types.unliteral, (fromty, toty))
    by = tyctxt.can_convert(fromty, toty)

    def warn():
        m = "unsafe cast from {} to {}. Precision may be lost."
        warnings.warn(m.format(fromty, toty), category=NumbaTypeSafetyWarning)

    isint = lambda x: isinstance(x, types.Integer)
    isflt = lambda x: isinstance(x, types.Float)
    iscmplx = lambda x: isinstance(x, types.Complex)
    # Only check against numeric types.
    if by is None or by > Conversion.safe:
        if isint(fromty) and isint(toty):
            # Accept if both types are ints
            warn()
        elif isint(fromty) and isflt(toty):
            # Accept if ints to floats
            warn()
        elif isflt(fromty) and isflt(toty):
            # Accept if floats to floats
            warn()
        elif iscmplx(fromty) and iscmplx(toty):
            # Accept if complex to complex
            warn()
        elif not isinstance(toty, types.Number):
            # Non-numbers
            warn()
        else:
            # Make it a hard error for numeric type that changes domain.
            m = "cannot safely cast {} to {}. Please cast explicitly."
            raise TypingError(m.format(fromty, toty))
Beispiel #9
0
def _check_for_none_typed(lst, method):
    if isinstance(lst.dtype, NoneType):
        raise TypingError(
            "method support for List[None] is limited, not supported: '{}'.".format(
                method
            )
        )
Beispiel #10
0
def get_nan_mask_overload(arr):

    _func_name = "Function: get_nan_mask"

    def get_nan_mask_via_isna_impl(arr):
        len_arr = len(arr)
        res = np.empty(len_arr, dtype=np.bool_)
        for i in numba.prange(len_arr):
            res[i] = isna(arr, i)
        return res

    if isinstance(arr, types.Array):
        dtype = arr.dtype
        if isinstance(dtype, types.Float):
            return lambda arr: np.isnan(arr)
        elif isinstance(dtype, (types.Boolean, types.Integer)):
            return lambda arr: np.zeros(len(arr), np.bool_)
        elif isinstance(dtype, (types.NPDatetime, types.NPTimedelta)):
            return get_nan_mask_via_isna_impl
        else:
            raise TypingError(
                '{} Not implemented for arrays with dtype: {}'.format(
                    _func_name, dtype))
    else:
        # for StringArrayType and other cases rely on isna implementation
        return get_nan_mask_via_isna_impl
Beispiel #11
0
def _get_proper_func(func_32, func_64, dtype, dist_name="the given"):
    """
        Most of the standard NumPy distributions that accept dtype argument
        only support either np.float32 or np.float64 as dtypes.

        This is a helper function that helps Numba select the proper underlying
        implementation according to provided dtype.
    """
    if isinstance(dtype, types.Omitted):
        dtype = dtype.value

    np_dt = dtype
    if isinstance(dtype, type):
        nb_dt = from_dtype(np.dtype(dtype))
    elif isinstance(dtype, types.NumberClass):
        nb_dt = dtype
        np_dt = as_dtype(nb_dt)

    if np_dt not in [np.float32, np.float64]:
        raise TypingError("Argument dtype is not one of the" +
                          " expected type(s): " + " np.float32 or np.float64")

    if np_dt == np.float32:
        next_func = func_32
    else:
        next_func = func_64

    return next_func, nb_dt
def impl_delitem(l, index):
    if not isinstance(l, types.ListType):
        return

    _check_for_none_typed(l, 'delitem')

    if index in index_types:

        def integer_impl(l, index):
            cindex = _cast(handle_index(l, index), INDEXTY)
            status = _list_delitem(l, cindex)
            if status == ListStatus.LIST_OK:
                return
            elif status == ListStatus.LIST_ERR_IMMUTABLE:
                raise ValueError("list is immutable")
            else:
                raise AssertionError("internal list error during delitem")

        return integer_impl

    elif isinstance(index, types.SliceType):

        def slice_impl(l, index):
            slice_range = handle_slice(l, index)
            status = _list_delete_slice(l, slice_range.start, slice_range.stop,
                                        slice_range.step)
            if status == ListStatus.LIST_ERR_MUTATED:
                raise ValueError("list is immutable")

        return slice_impl

    else:
        raise TypingError("list indices must be integers or slices")
Beispiel #13
0
def impl_delitem(l, index):
    if not isinstance(l, types.ListType):
        return

    if index in index_types:

        def integer_impl(l, index):
            l.pop(index)

        return integer_impl

    elif isinstance(index, types.SliceType):

        def slice_impl(l, index):
            slice_range = handle_slice(l, index)
            status = _list_delete_slice(
                l, slice_range.start, slice_range.stop, slice_range.step
            )
            if status == ListStatus.LIST_ERR_MUTATED:
                raise ValueError("list is immutable")

        return slice_impl

    else:
        raise TypingError("list indices must be integers or slices")
Beispiel #14
0
def pd_positional_index_reindex_overload(self,
                                         target,
                                         method=None,
                                         level=None,
                                         limit=None,
                                         tolerance=None):
    if not isinstance(self, PositionalIndexType):
        return None

    _func_name = 'Method reindex().'
    if not isinstance(target, sdc_pandas_index_types):
        raise SDCLimitation(
            f"{_func_name} Unsupported parameter. Given 'target': {target}")

    if not check_types_comparable(self, target):
        raise TypingError('{} Not allowed for non comparable indexes. \
        Given: self={}, target={}'.format(_func_name, self, target))

    def pd_positional_index_reindex_impl(self,
                                         target,
                                         method=None,
                                         level=None,
                                         limit=None,
                                         tolerance=None):
        return sdc_indexes_reindex(self,
                                   target=target,
                                   method=method,
                                   level=level,
                                   tolerance=tolerance)

    return pd_positional_index_reindex_impl
Beispiel #15
0
def pd_positional_index_ne_overload(self, other):

    _func_name = 'Operator ne.'
    if not check_types_comparable(self, other):
        raise TypingError('{} Not allowed for non comparable indexes. \
        Given: self={}, other={}'.format(_func_name, self, other))

    self_is_positional_index = isinstance(self, PositionalIndexType)
    other_is_positional_index = isinstance(other, PositionalIndexType)

    possible_arg_types = (types.Array, types.Number) + sdc_pandas_index_types
    if not (
            self_is_positional_index and other_is_positional_index or
        (self_is_positional_index and isinstance(other, possible_arg_types)) or
        (isinstance(self, possible_arg_types) and other_is_positional_index)):
        return None

    def pd_positional_index_ne_impl(self, other):

        eq_res = np.asarray(
            self ==
            other)  # FIXME_Numba#5157: remove np.asarray and return as list
        return list(~eq_res)

    return pd_positional_index_ne_impl
Beispiel #16
0
def pd_range_index_equals_overload(self, other):
    if not isinstance(self, RangeIndexType):
        return None

    _func_name = 'Method equals().'
    if not isinstance(other, sdc_pandas_index_types):
        raise SDCLimitation(
            f"{_func_name} Unsupported parameter. Given 'other': {other}")

    if not check_types_comparable(self, other):
        raise TypingError('{} Not allowed for non comparable indexes. \
        Given: self={}, other={}'.format(_func_name, self, other))

    if isinstance(other, sdc_indexes_range_like):

        def pd_range_index_equals_impl(self, other):

            if len(self) != len(other):
                return False
            if len(self) == 0:
                return True

            if len(self) == 1:
                return self.start == other.start

            return self.start == other.start and self.step == other.step
    else:

        def pd_range_index_equals_impl(self, other):
            return sdc_numeric_indexes_equals(self, other)

    return pd_range_index_equals_impl
Beispiel #17
0
def csv_reader_infer_nb_arrow_type(
    filepath_or_buffer, delimiter=',', names=None, usecols=None, dtype=None, skiprows=None, parse_dates=False
):

    read_opts, parse_opts, convert_opts = get_pyarrow_read_csv_options(
                                                delimiter, names, usecols, dtype, skiprows, parse_dates)
    csv_reader = csv.open_csv(filepath_or_buffer,
                              read_options=read_opts,
                              parse_options=parse_opts,
                              convert_options=convert_opts)

    table_schema = csv_reader.schema

    nb_arrow_column_types = []
    for i, pa_data_type in enumerate(table_schema.types):
        nb_type = numpy_support.from_dtype(pa_data_type.to_pandas_dtype())

        if isinstance(nb_type, types.PyObject):
            if pa_data_type == pa.string():
                nb_type = StdStringViewType()
            else:
                raise TypingError("Cannot infer numba type for: ", pa_data_type, f"of column={table_schema.names[i]}")

        nb_arrow_column_types.append(nb_type)

    table_column_names = table_schema.names if not names else (names if usecols is None else usecols)

    arrow_table_type = ArrowTableType(nb_arrow_column_types, table_column_names)
    return arrow_table_type
Beispiel #18
0
def pd_int64_index_append_overload(self, other):
    if not isinstance(self, Int64IndexType):
        return None

    _func_name = 'Method append().'
    ty_checker = TypeChecker(_func_name)

    if not isinstance(other, sdc_pandas_index_types):
        ty_checker.raise_exc(other, 'pandas index', 'other')

    if not check_types_comparable(self, other):
        raise TypingError('{} Not allowed for non comparable indexes. \
        Given: self={}, other={}'.format(_func_name, self, other))

    convert_other = not isinstance(other, types.Array)
    _, res_index_dtype = find_index_common_dtype(self, other)
    return_as_array_index = res_index_dtype is not types.int64

    def pd_int64_index_append_impl(self, other):
        _other = other.values if convert_other == True else other  # noqa
        new_index_data = hpat_arrays_append(self._data, _other)
        # this is only needed while some indexes are represented with arrays
        # TO-DO: support pd.Index() overload with dtype arg to create indexes
        if return_as_array_index == False:  # noqa
            return pd.Int64Index(new_index_data)
        else:
            return new_index_data

    return pd_int64_index_append_impl
Beispiel #19
0
    def generic(self, args, kws):
        pysig = None
        if kws:
            if self.method_name == 'sum':
                if 'axis' in kws and 'dtype' not in kws:
                    def sum_stub(arr, axis):
                        pass
                    pysig = utils.pysignature(sum_stub)
                elif 'dtype' in kws and 'axis' not in kws:
                    def sum_stub(arr, dtype):
                        pass
                    pysig = utils.pysignature(sum_stub)
                elif 'dtype' in kws and 'axis' in kws:
                    def sum_stub(arr, axis, dtype):
                        pass
                    pysig = utils.pysignature(sum_stub)
            elif self.method_name == 'argsort':
                def argsort_stub(arr, kind='quicksort'):
                    pass
                pysig = utils.pysignature(argsort_stub)
            else:
                fmt = "numba doesn't support kwarg for {}"
                raise TypingError(fmt.format(self.method_name))

        arr = args[0]
        # This will return a BoundFunction
        meth_ty = self.context.resolve_getattr(arr, self.method_name)
        # Resolve arguments on the bound function
        meth_sig = self.context.resolve_function_type(meth_ty, args[1:], kws)
        if meth_sig is not None:
            return meth_sig.as_function().replace(pysig=pysig)
Beispiel #20
0
 def check_arg(arg, name):
     if not (
         arg is None
         or arg in index_types
         or isinstance(arg, (types.Omitted, types.NoneType))
     ):
         raise TypingError("{} argument for index must be an integer".format(name))
Beispiel #21
0
def _ov_literally(obj):
    if isinstance(obj, types.Literal):
        lit = obj.literal_value
        return lambda obj: lit
    else:
        m = "Invalid use of non-Literal type in literally({})".format(obj)
        raise TypingError(m)
Beispiel #22
0
def impl_pop(l, index=-1):
    if not isinstance(l, types.ListType):
        return

    _check_for_none_typed(l, 'pop')

    indexty = INDEXTY

    # FIXME: this type check works, but it isn't clear why and if it optimal
    if (isinstance(index, int) or index in index_types
            or isinstance(index, types.Omitted)):

        def impl(l, index=-1):
            if len(l) == 0:
                raise IndexError("pop from empty list")
            index = handle_index(l, index)
            castedindex = _cast(index, indexty)
            status, item = _list_pop(l, castedindex)
            if status == ListStatus.LIST_OK:
                return _nonoptional(item)
            elif status == ListStatus.LIST_ERR_IMMUTABLE:
                raise ValueError("list is immutable")
            else:
                raise AssertionError("internal list error during pop")

        return impl

    else:
        raise TypingError("argument for pop must be an integer")
Beispiel #23
0
def ol_sum(iterable, start=0):
    # Cpython explicitly rejects strings, bytes and bytearrays
    # https://github.com/python/cpython/blob/3.9/Python/bltinmodule.c#L2310-L2329 # noqa: E501
    error = None
    if isinstance(start, types.UnicodeType):
        error = ('strings', '')
    elif isinstance(start, types.Bytes):
        error = ('bytes', 'b')
    elif isinstance(start, types.ByteArray):
        error = ('bytearray', 'b')

    if error is not None:
        msg = "sum() can't sum {} [use {}''.join(seq) instead]".format(*error)
        raise TypingError(msg)

    # if the container is homogeneous then it's relatively easy to handle.
    if isinstance(iterable, (types.containers._HomogeneousTuple, types.List,
                             types.ListType, types.Array, types.RangeType)):
        iterator = iter
    elif isinstance(iterable, (types.containers._HeterogeneousTuple)):
        # if container is heterogeneous then literal unroll and hope for the
        # best.
        iterator = literal_unroll
    else:
        return None

    def impl(iterable, start=0):
        acc = start
        for x in iterator(iterable):
            # This most likely widens the type, this is expected Numba behaviour
            acc = acc + x
        return acc

    return impl
Beispiel #24
0
def to_scalar(x):
    if isinstance(x, (numba.types.Number, numba.types.Boolean)):
        return lambda x: x
    elif isinstance(x, numba.types.Array):
        return lambda x: x.item()
    else:
        raise TypingError(f"{x} must be a scalar compatible type.")
Beispiel #25
0
def literal_unroll_impl(container):
    if isinstance(container, types.Poison):
        m = f"Invalid use of non-Literal type in literal_unroll({container})"
        raise TypingError(m)

    def impl(container):
        return container
    return impl
Beispiel #26
0
 def generic(self, args, kws):
     if kws or len(args) != 1:
         return
     [ary] = args
     if not isinstance(ary, types.Buffer):
         raise TypingError(
             "from_buffer() expected a buffer object, got %s" % (ary, ))
     if ary.layout not in ('C', 'F'):
         raise TypingError(
             "from_buffer() unsupported on non-contiguous buffers (got %s)"
             % (ary, ))
     if ary.layout != 'C' and ary.ndim > 1:
         raise TypingError(
             "from_buffer() only supports multidimensional arrays with C layout (got %s)"
             % (ary, ))
     ptr = types.CPointer(ary.dtype)
     return templates.signature(ptr, ary)
Beispiel #27
0
def kb_declare(self, subscriber):
    if (not isinstance(subscriber, types.StructRef)):
        raise TypingError(f"Cannot add subscriber of type '{type(fact)}'.")

    def impl(self, subscriber):
        return add_subscriber(self, subscriber)

    return impl
Beispiel #28
0
def resolve_getattr(tyctx, obj, name, default):
    if not isinstance(name, types.StringLiteral):
        raise RequireLiteralValue("argument 'name' must be a literal string")
    lname = name.literal_value
    fn = tyctx.resolve_getattr(obj, lname)
    # Cannot handle things like `getattr(np, 'cos')` as the return type is
    # types.Function.
    if isinstance(fn, types.Function):
        msg = ("Returning function objects is not implemented. "
               f"getattr() was requested to return {fn} from attribute "
               f"'{lname}' of {obj}.")
        raise TypingError(msg)

    if fn is None:  # No attribute

        # if default is not _getattr_default then return the default
        if not (isinstance(default, types.NamedTuple)
                and default.instance_class == _getattr_default_type):
            # it's not the marker default value, so return it
            sig = default(obj, name, default)

            def impl(cgctx, builder, sig, llargs):
                tmp = llargs[-1]
                cgctx.nrt.incref(builder, default, tmp)
                return tmp
        else:
            # else wire in raising an AttributeError
            fnty = tyctx.resolve_value_type(_getattr_raise_attr_exc)
            raise_sig = fnty.get_call_type(tyctx, (obj, name), {})
            sig = types.none(obj, name, default)

            def impl(cgctx, builder, sig, llargs):
                native_impl = cgctx.get_function(fnty, raise_sig)
                return native_impl(builder, llargs[:-1])

    else:  # Attribute present, wire in handing it back to the overload(getattr)
        sig = fn(obj, name, default)
        if isinstance(fn, types.BoundFunction):
            # It's a method on an object
            def impl(cgctx, builder, sig, ll_args):
                cast_type = fn.this
                casted = cgctx.cast(builder, ll_args[0], obj, cast_type)
                res = cgctx.get_bound_function(builder, casted, cast_type)
                cgctx.nrt.incref(builder, fn, res)
                return res
        else:
            # Else it's some other type of attribute.
            # Ensure typing calls occur at typing time, not at lowering
            attrty = tyctx.resolve_getattr(obj, lname)

            def impl(cgctx, builder, sig, ll_args):
                attr_impl = cgctx.get_getattr(obj, lname)
                res = attr_impl(cgctx, builder, obj, ll_args[0], lname)
                casted = cgctx.cast(builder, res, attrty, fn)
                cgctx.nrt.incref(builder, fn, casted)
                return casted

    return sig, impl
Beispiel #29
0
def impl_insert(l, index, item):
    if not isinstance(l, types.ListType):
        return

    _check_for_none_typed(l, 'insert')
    # insert can refine
    if isinstance(item, NoneType):
        raise TypingError("method support for List[None] is limited")

    if index in index_types:

        def impl(l, index, item):
            # If the index is larger than the size of the list or if the list is
            # empty, just append.
            if index >= len(l) or len(l) == 0:
                l.append(item)
            # Else, do the insert dance
            else:
                # convert negative indices
                if index < 0:
                    # if the index is still negative after conversion, use 0
                    index = max(len(l) + index, 0)
                # grow the list by one, make room for item to insert
                l.append(l[0])
                # reverse iterate over the list and shift all elements
                i = len(l) - 1
                while (i > index):
                    l[i] = l[i - 1]
                    i -= 1
                # finally, insert the item
                l[index] = item

        if l.is_precise():
            # Handle the precise case.
            return impl
        else:
            # Handle the imprecise case
            l = l.refine(item)
            # Re-bind the item type to match the arguments.
            itemty = l.item_type
            # Create the signature that we wanted this impl to have.
            sig = typing.signature(types.void, l, INDEXTY, itemty)
            return sig, impl
    else:
        raise TypingError("list insert indices must be integers")
Beispiel #30
0
    def get_call_type(self, context, args, kws):
        from numba.core import typing

        if not self.cm.is_callable:
            msg = "contextmanager {} is not callable".format(self.cm)
            raise TypingError(msg)

        posargs = list(args) + [v for k, v in sorted(kws.items())]
        return typing.signature(self, *posargs)