def _infer_pandas_series_contents(s: pd.Series) -> dt.DataType: """Infer the type of the **contents** of a pd.Series. No dispatch for this because there is no class representing "the contents of a Series". Instead, this is meant to be used internally, mainly by `infer_pandas_series`. Parameters ---------- s : pd.Series The Series whose contents we want to know the type of Returns ------- dtype : dt.DataType The dtype of the contents of the Series """ if s.dtype == np.object_: inferred_dtype = infer_pandas_dtype(s, skipna=True) if inferred_dtype == 'mixed': # We need to inspect an element to determine the Ibis dtype value = s.iloc[0] if isinstance(value, (np.ndarray, list, pd.Series)): # Defer to individual `infer` functions for these return dt.infer(value) else: return dt.dtype('binary') else: return _inferable_pandas_dtypes[inferred_dtype] else: return dt.dtype(s.dtype)
def literal(value, type=None): """Create a scalar expression from a Python value. Parameters ---------- value : some Python basic type A Python value type : ibis type or string, optional An instance of :class:`ibis.expr.datatypes.DataType` or a string indicating the ibis type of `value`. This parameter should only be used in cases where ibis's type inference isn't sufficient for discovering the type of `value`. Returns ------- literal_value : Literal An expression representing a literal value Examples -------- >>> import ibis >>> x = ibis.literal(42) >>> x.type() int8 >>> y = ibis.literal(42, type='double') >>> y.type() double >>> ibis.literal('foobar', type='int64') # doctest: +ELLIPSIS Traceback (most recent call last): ... TypeError: Value 'foobar' cannot be safely coerced to int64 """ import ibis.expr.datatypes as dt import ibis.expr.operations as ops if hasattr(value, 'op') and isinstance(value.op(), ops.Literal): return value if value is null: dtype = dt.null else: dtype = dt.infer(value) if type is not None: try: # check that dtype is implicitly castable to explicitly given dtype dtype = dtype.cast(type, value=value) except com.IbisTypeError: raise TypeError('Value {!r} cannot be safely coerced ' 'to {}'.format(value, type)) if dtype is dt.null: return null().cast(dtype) else: return ops.Literal(value, dtype=dtype).to_expr()
def _promote_numeric_binop(exprs, op): bounds, dtypes = [], [] for arg in exprs: dtypes.append(arg.type()) if hasattr(arg.op(), 'value'): # arg.op() is a literal bounds.append([arg.op().value]) else: bounds.append(arg.type().bounds) # In some cases, the bounding type might be int8, even though neither # of the types are that small. We want to ensure the containing type is # _at least_ as large as the smallest type in the expression. values = starmap(op, product(*bounds)) dtypes += [dt.infer(value, allow_overflow=True) for value in values] return dt.highest_precedence(dtypes)
def test_infer_dtype(value, expected_dtype): assert dt.infer(value) == expected_dtype # test literal creation value = ibis.literal(value, type=expected_dtype) assert value.type() == expected_dtype
def literal(value, type=None): """Create a scalar expression from a Python value. Parameters ---------- value : some Python basic type A Python value type : ibis type or string, optional An instance of :class:`ibis.expr.datatypes.DataType` or a string indicating the ibis type of `value`. This parameter should only be used in cases where ibis's type inference isn't sufficient for discovering the type of `value`. Returns ------- literal_value : Literal An expression representing a literal value Examples -------- >>> import ibis >>> x = ibis.literal(42) >>> x.type() int8 >>> y = ibis.literal(42, type='double') >>> y.type() float64 >>> ibis.literal('foobar', type='int64') # doctest: +ELLIPSIS Traceback (most recent call last): ... TypeError: Value 'foobar' cannot be safely coerced to int64 """ import ibis.expr.datatypes as dt import ibis.expr.operations as ops if hasattr(value, 'op') and isinstance(value.op(), ops.Literal): return value try: inferred_dtype = dt.infer(value) except com.InputTypeError: has_inferred = False else: has_inferred = True if type is None: has_explicit = False else: has_explicit = True explicit_dtype = dt.dtype(type) if has_explicit and has_inferred: try: # ensure type correctness: check that the inferred dtype is # implicitly castable to the explicitly given dtype and value dtype = inferred_dtype.cast(explicit_dtype, value=value) except com.IbisTypeError: raise TypeError( 'Value {!r} cannot be safely coerced to {}'.format(value, type) ) elif has_explicit: dtype = explicit_dtype elif has_inferred: dtype = inferred_dtype else: raise TypeError( 'The datatype of value {!r} cannot be inferred, try ' 'passing it explicitly with the `type` keyword.'.format(value) ) if dtype is dt.null: return null().cast(dtype) else: return ops.Literal(value, dtype=dtype).to_expr()
def literal(value, type=None): """Create a scalar expression from a Python value. Parameters ---------- value : some Python basic type A Python value type : ibis type or string, optional An instance of :class:`ibis.expr.datatypes.DataType` or a string indicating the ibis type of `value`. This parameter should only be used in cases where ibis's type inference isn't sufficient for discovering the type of `value`. Returns ------- literal_value : Literal An expression representing a literal value Examples -------- >>> import ibis >>> x = ibis.literal(42) >>> x.type() int8 >>> y = ibis.literal(42, type='double') >>> y.type() float64 >>> ibis.literal('foobar', type='int64') # doctest: +ELLIPSIS Traceback (most recent call last): ... TypeError: Value 'foobar' cannot be safely coerced to int64 """ import ibis.expr.datatypes as dt import ibis.expr.operations as ops if hasattr(value, 'op') and isinstance(value.op(), ops.Literal): return value try: inferred_dtype = dt.infer(value) except com.InputTypeError: has_inferred = False else: has_inferred = True if type is None: has_explicit = False else: has_explicit = True explicit_dtype = dt.dtype(type) if has_explicit and has_inferred: try: # ensure type correctness: check that the inferred dtype is # implicitly castable to the explicitly given dtype and value dtype = inferred_dtype.cast(explicit_dtype, value=value) except com.IbisTypeError: raise TypeError('Value {!r} cannot be safely coerced to {}'.format( value, type)) elif has_explicit: dtype = explicit_dtype elif has_inferred: dtype = inferred_dtype else: raise TypeError( 'The datatype of value {!r} cannot be inferred, try ' 'passing it explicitly with the `type` keyword.'.format(value)) if dtype is dt.null: return null().cast(dtype) else: return ops.Literal(value, dtype=dtype).to_expr()
def test_infer_dtype(value, expected_dtype): assert dt.infer(value) == expected_dtype
def infer_literal_type(value): # TODO: depricate? if value is null: return dt.null return dt.infer(value)
def _smallest_int_containing(values, allow_overflow=False): containing_types = [ dt.infer(x, allow_overflow=allow_overflow) for x in values ] return _largest_int(containing_types)
def literal(value: Any, type: dt.DataType | str | None = None) -> Scalar: """Create a scalar expression from a Python value. !!! tip "Use specific functions for arrays, structs and maps" Ibis supports literal construction of arrays using the following functions: 1. [`ibis.array`][ibis.array] 1. [`ibis.struct`][ibis.struct] 1. [`ibis.map`][ibis.map] Constructing these types using `literal` will be deprecated in a future release. Parameters ---------- value A Python value type An instance of [`DataType`][ibis.expr.datatypes.DataType] or a string indicating the ibis type of `value`. This parameter can be used in cases where ibis's type inference isn't sufficient for discovering the type of `value`. Returns ------- Scalar An expression representing a literal value Examples -------- Construct an integer literal >>> import ibis >>> x = ibis.literal(42) >>> x.type() Int8(nullable=True) Construct a `float64` literal from an `int` >>> y = ibis.literal(42, type='double') >>> y.type() Float64(nullable=True) Ibis checks for invalid types >>> ibis.literal('foobar', type='int64') # doctest: +ELLIPSIS Traceback (most recent call last): ... TypeError: Value 'foobar' cannot be safely coerced to int64 """ import ibis.expr.datatypes as dt import ibis.expr.operations as ops if hasattr(value, 'op') and isinstance(value.op(), ops.Literal): return value try: inferred_dtype = dt.infer(value) except com.InputTypeError: has_inferred = False else: has_inferred = True if type is None: has_explicit = False else: has_explicit = True explicit_dtype = dt.dtype(type) if has_explicit and has_inferred: try: # ensure type correctness: check that the inferred dtype is # implicitly castable to the explicitly given dtype and value dtype = inferred_dtype.cast(explicit_dtype, value=value) except com.IbisTypeError: raise TypeError( f'Value {value!r} cannot be safely coerced to {type}') elif has_explicit: dtype = explicit_dtype elif has_inferred: dtype = inferred_dtype else: raise TypeError( 'The datatype of value {!r} cannot be inferred, try ' 'passing it explicitly with the `type` keyword.'.format(value)) if dtype is dt.null: return null().cast(dtype) else: value = dt._normalize(dtype, value) return ops.Literal(value, dtype=dtype).to_expr()
def test_infer_np_array(value, expected_dtypes): assert dt.infer(value) in expected_dtypes