diff --git a/crates/polars-core/src/utils/supertype.rs b/crates/polars-core/src/utils/supertype.rs index 30895f9e01fe..9a73f66d8303 100644 --- a/crates/polars-core/src/utils/supertype.rs +++ b/crates/polars-core/src/utils/supertype.rs @@ -537,17 +537,24 @@ fn super_type_structs(fields_a: &[Field], fields_b: &[Field]) -> Option AnyValue<'static> { // Try to get the "smallest" fitting value. // TODO! next breaking go to true smallest. - match i32::try_from(v).ok() { - Some(v) => AnyValue::Int32(v), - None => match i64::try_from(v).ok() { - Some(v) => AnyValue::Int64(v), - None => match u64::try_from(v).ok() { - Some(v) => AnyValue::UInt64(v), - None => AnyValue::Null, - }, - }, + if let Ok(v) = i32::try_from(v) { + return AnyValue::Int32(v); + } + if let Ok(v) = i64::try_from(v) { + return AnyValue::Int64(v); + } + if let Ok(v) = u64::try_from(v) { + return AnyValue::UInt64(v); } + #[cfg(feature = "dtype-i128")] + { + AnyValue::Int128(v) + } + + #[cfg(not(feature = "dtype-i128"))] + AnyValue::Null } + fn materialize_dyn_int_pos(v: i128) -> AnyValue<'static> { // Try to get the "smallest" fitting value. // TODO! next breaking go to true smallest. diff --git a/py-polars/tests/unit/expr/test_literal.py b/py-polars/tests/unit/expr/test_literal.py index 31567e7bc116..d53b52e19165 100644 --- a/py-polars/tests/unit/expr/test_literal.py +++ b/py-polars/tests/unit/expr/test_literal.py @@ -19,3 +19,12 @@ def test_literal_scalar_list_18686() -> None: ("lit2", pl.List(pl.Null)), ] ) + + +def test_literal_integer_20807() -> None: + for i in range(100): + value = 2**i + assert pl.select(pl.lit(value)).item() == value + assert pl.select(pl.lit(-value)).item() == -value + assert pl.select(pl.lit(value, dtype=pl.Int128)).item() == value + assert pl.select(pl.lit(-value, dtype=pl.Int128)).item() == -value diff --git a/py-polars/tests/unit/operations/test_index_of.py b/py-polars/tests/unit/operations/test_index_of.py index bb72e8afdfe7..7301d6dfd311 100644 --- a/py-polars/tests/unit/operations/test_index_of.py +++ b/py-polars/tests/unit/operations/test_index_of.py @@ -17,13 +17,21 @@ from polars.testing import assert_frame_equal +def isnan(value: object) -> bool: + if isinstance(value, int): + return False + if not isinstance(value, (np.number, float)): + return False + return np.isnan(value) # type: ignore[no-any-return] + + def assert_index_of( series: pl.Series, value: IntoExpr, convert_to_literal: bool = False, ) -> None: """``Series.index_of()`` returns the index, or ``None`` if it can't be found.""" - if isinstance(value, (np.number, float, int)) and np.isnan(value): + if isnan(value): expected_index = None for i, o in enumerate(series.to_list()): if o is not None and np.isnan(o): @@ -93,10 +101,27 @@ def test_empty() -> None: @pytest.mark.parametrize( "dtype", - [pl.Int8, pl.Int16, pl.Int32, pl.Int64, pl.UInt8, pl.UInt16, pl.UInt32, pl.UInt64], + [ + pl.Int8, + pl.Int16, + pl.Int32, + pl.Int64, + pl.UInt8, + pl.UInt16, + pl.UInt32, + pl.UInt64, + pl.Int128, + ], ) def test_integer(dtype: pl.DataType) -> None: - values = [51, 3, None, 4] + values = [ + 51, + 3, + None, + 4, + pl.select(dtype.max()).item(), # type: ignore[attr-defined] + pl.select(dtype.min()).item(), # type: ignore[attr-defined] + ] series = pl.Series(values, dtype=dtype) sorted_series_asc = series.sort(descending=False) sorted_series_desc = series.sort(descending=True) @@ -104,7 +129,7 @@ def test_integer(dtype: pl.DataType) -> None: [pl.Series([100, 7], dtype=dtype), series], rechunk=False ) - extra_values = [pl.select(v).item() for v in [dtype.max(), dtype.min()]] # type: ignore[attr-defined] + extra_values = [pl.select(v).item() for v in [dtype.max() - 1, dtype.min() + 1]] # type: ignore[attr-defined] for s in [series, sorted_series_asc, sorted_series_desc, chunked_series]: value: IntoExpr for value in values: