Skip to content

Commit

Permalink
fix(rust, python): Implement missing extract conversion for Time
Browse files Browse the repository at this point in the history
…datatype (#5161)
  • Loading branch information
alexander-beedie committed Oct 11, 2022
1 parent 72884e1 commit 1dd7578
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 14 deletions.
2 changes: 2 additions & 0 deletions polars/polars-core/src/datatypes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,8 @@ impl<'a> AnyValue<'a> {
Date(v) => NumCast::from(*v),
#[cfg(feature = "dtype-datetime")]
Datetime(v, _, _) => NumCast::from(*v),
#[cfg(feature = "dtype-time")]
Time(v) => NumCast::from(*v),
#[cfg(feature = "dtype-duration")]
Duration(v, _) => NumCast::from(*v),
Boolean(v) => {
Expand Down
1 change: 1 addition & 0 deletions polars/polars-core/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ macro_rules! apply_method_all_arrow_series {
DataType::Int64 => $self.i64().unwrap().$method($($args),*),
DataType::Float32 => $self.f32().unwrap().$method($($args),*),
DataType::Float64 => $self.f64().unwrap().$method($($args),*),
DataType::Time => $self.time().unwrap().$method($($args),*),
DataType::Date => $self.date().unwrap().$method($($args),*),
DataType::Datetime(_, _) => $self.datetime().unwrap().$method($($args),*),
DataType::List(_) => $self.list().unwrap().$method($($args),*),
Expand Down
2 changes: 1 addition & 1 deletion polars/polars-lazy/polars-plan/src/logical_plan/lit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ impl TryFrom<AnyValue<'_>> for LiteralValue {
),
}),
#[cfg(all(feature = "temporal", feature = "dtype-datetime"))]
AnyValue::Time(nano_secs_sinds_midnight) => Ok(Self::Int64(nano_secs_sinds_midnight)),
AnyValue::Time(nanosecs_since_midnight) => Ok(Self::Int64(nanosecs_since_midnight)),
AnyValue::List(l) => Ok(Self::Series(SpecialEq::new(l))),
AnyValue::Utf8Owned(o) => Ok(Self::Utf8(o.into())),
#[cfg(feature = "dtype-categorical")]
Expand Down
1 change: 1 addition & 0 deletions py-polars/polars/datatypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,7 @@ def __hash__(self) -> int:
tuple: List,
Decimal: Float64,
bytes: Binary,
object: Object,
}

_PY_STR_TO_DTYPE: dict[str, PolarsDataType] = {
Expand Down
18 changes: 14 additions & 4 deletions py-polars/src/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ impl<'s> FromPyObject<'s> for Wrap<AnyValue<'s>> {
Ok(AnyValue::Float64(v).into())
} else if let Ok(v) = ob.extract::<&'s str>() {
Ok(AnyValue::Utf8(v).into())
} else if ob.get_type().name()?.contains("datetime") {
} else if ob.get_type().name()?.eq("datetime") {
Python::with_gil(|py| {
// windows
#[cfg(target_arch = "windows")]
Expand Down Expand Up @@ -579,7 +579,7 @@ impl<'s> FromPyObject<'s> for Wrap<AnyValue<'s>> {
let py_pyseries = ob.getattr("_s").unwrap();
let series = py_pyseries.extract::<PySeries>().unwrap().series;
Ok(Wrap(AnyValue::List(series)))
} else if ob.get_type().name()?.contains("date") {
} else if ob.get_type().name()?.eq("date") {
Python::with_gil(|py| {
let date = py_modules::UTILS
.getattr(py, "_date_to_pl_date")
Expand All @@ -589,7 +589,7 @@ impl<'s> FromPyObject<'s> for Wrap<AnyValue<'s>> {
let v = date.extract::<i32>(py).unwrap();
Ok(Wrap(AnyValue::Date(v)))
})
} else if ob.get_type().name()?.contains("timedelta") {
} else if ob.get_type().name()?.eq("timedelta") {
Python::with_gil(|py| {
let td = py_modules::UTILS
.getattr(py, "_timedelta_to_pl_timedelta")
Expand All @@ -599,11 +599,21 @@ impl<'s> FromPyObject<'s> for Wrap<AnyValue<'s>> {
let v = td.extract::<i64>(py).unwrap();
Ok(Wrap(AnyValue::Duration(v, TimeUnit::Microseconds)))
})
} else if ob.get_type().name()?.eq("time") {
Python::with_gil(|py| {
let time = py_modules::UTILS
.getattr(py, "_time_to_pl_time")
.unwrap()
.call1(py, (ob,))
.unwrap();
let v = time.extract::<i64>(py).unwrap();
Ok(Wrap(AnyValue::Time(v)))
})
} else if let Ok(v) = ob.extract::<&'s [u8]>() {
Ok(AnyValue::Binary(v).into())
} else {
Err(PyErr::from(PyPolarsErr::Other(format!(
"row type not supported {:?}",
"object type not supported {:?}",
ob
))))
}
Expand Down
53 changes: 44 additions & 9 deletions py-polars/tests/unit/test_datelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@

import polars as pl
from polars.datatypes import DTYPE_TEMPORAL_UNITS, TemporalDataType
from polars.testing import assert_series_equal, verify_series_and_expr_api
from polars.testing import (
assert_frame_equal,
assert_series_equal,
verify_series_and_expr_api,
)

if TYPE_CHECKING:
from polars.internals.type_aliases import TimeUnit
Expand Down Expand Up @@ -999,15 +1003,46 @@ def test_asof_join() -> None:
].to_list() == [51.95, 51.95, None, None, 720.77, None, None, None]


def test_lambda_with_python_datetime_return_type() -> None:
df = pl.DataFrame({"timestamp": [1284286794, 1234567890]})
def test_temporal_dtypes_apply() -> None:
df = pl.DataFrame(
{"timestamp": [1284286794000, None, 1234567890000]},
columns=[("timestamp", pl.Datetime("ms"))],
)
const_dtm = datetime(2010, 9, 12)

assert df.with_column(
pl.col("timestamp").apply(lambda x: datetime(2010, 9, 12)).alias("my_date_time")
)["my_date_time"].to_list() == [
datetime(2010, 9, 12),
datetime(2010, 9, 12),
]
assert_frame_equal(
df.with_columns(
[
# don't actually do any of this; native expressions are MUCH faster ;)
pl.col("timestamp").apply(lambda x: const_dtm).alias("const_dtm"),
pl.col("timestamp").apply(lambda x: x and x.date()).alias("date"),
pl.col("timestamp").apply(lambda x: x and x.time()).alias("time"),
]
),
pl.DataFrame(
[
(
datetime(2010, 9, 12, 10, 19, 54),
datetime(2010, 9, 12, 0, 0),
date(2010, 9, 12),
time(10, 19, 54),
),
(None, const_dtm, None, None),
(
datetime(2009, 2, 13, 23, 31, 30),
datetime(2010, 9, 12, 0, 0),
date(2009, 2, 13),
time(23, 31, 30),
),
],
columns={
"timestamp": pl.Datetime("ms"),
"const_dtm": pl.Datetime("us"),
"date": pl.Date,
"time": pl.Time,
},
),
)


def test_timelike_init() -> None:
Expand Down

0 comments on commit 1dd7578

Please sign in to comment.