11from __future__ import annotations
22
3- import numbers
43from datetime import datetime
54from datetime import timedelta
65from functools import wraps
4645
4746T = TypeVar ("T" )
4847
48+ NON_TEMPORAL_SCALAR_TYPES = (
49+ bool ,
50+ bytes ,
51+ str ,
52+ int ,
53+ float ,
54+ complex ,
55+ )
56+
4957
5058@overload
5159def to_native (
@@ -843,16 +851,10 @@ def to_py_scalar(scalar_like: Any) -> Any:
843851 >>> nw.to_py_scalar(1)
844852 1
845853 """
846-
847- pa = get_pyarrow ()
848- if pa and isinstance (scalar_like , pa .Scalar ):
849- return scalar_like .as_py ()
850-
851- cupy = get_cupy ()
852- if ( # pragma: no cover
853- cupy and isinstance (scalar_like , cupy .ndarray ) and scalar_like .size == 1
854- ):
855- return scalar_like .item ()
854+ if scalar_like is None :
855+ return None
856+ if isinstance (scalar_like , NON_TEMPORAL_SCALAR_TYPES ):
857+ return scalar_like
856858
857859 np = get_numpy ()
858860 if np and np .isscalar (scalar_like ) and hasattr (scalar_like , "item" ):
@@ -863,21 +865,30 @@ def to_py_scalar(scalar_like: Any) -> Any:
863865 return scalar_like .to_pydatetime ()
864866 if pd and isinstance (scalar_like , pd .Timedelta ):
865867 return scalar_like .to_pytimedelta ()
866-
867- all_scalar_types = (
868- int ,
869- float ,
870- complex ,
871- bool ,
872- bytes ,
873- str ,
874- datetime ,
875- timedelta ,
876- numbers .Number ,
877- )
878- if isinstance (scalar_like , all_scalar_types ):
868+ if pd and pd .api .types .is_scalar (scalar_like ):
869+ try :
870+ is_na = pd .isna (scalar_like )
871+ except Exception : # pragma: no cover # noqa: BLE001, S110
872+ pass
873+ else :
874+ if is_na :
875+ return None
876+
877+ # pd.Timestamp and pd.Timedelta subclass datetime and timedelta,
878+ # so we need to check this separately
879+ if isinstance (scalar_like , (datetime , timedelta )):
879880 return scalar_like
880881
882+ pa = get_pyarrow ()
883+ if pa and isinstance (scalar_like , pa .Scalar ):
884+ return scalar_like .as_py ()
885+
886+ cupy = get_cupy ()
887+ if ( # pragma: no cover
888+ cupy and isinstance (scalar_like , cupy .ndarray ) and scalar_like .size == 1
889+ ):
890+ return scalar_like .item ()
891+
881892 msg = (
882893 f"Expected object convertible to a scalar, found { type (scalar_like )} . "
883894 "Please report a bug to https://github.com/narwhals-dev/narwhals/issues"
0 commit comments