diff --git a/pandas-stubs/_typing.pyi b/pandas-stubs/_typing.pyi index 0afa9c520..ab3915548 100644 --- a/pandas-stubs/_typing.pyi +++ b/pandas-stubs/_typing.pyi @@ -223,7 +223,7 @@ IndexT = TypeVar("IndexT", bound=Index) IntervalClosedType: TypeAlias = Literal["left", "right", "both", "neither"] -DateTimeErrorChoices: TypeAlias = Literal["ignore", "raise", "coerce"] +IgnoreRaiseCoerce: TypeAlias = Literal["ignore", "raise", "coerce"] # Shared by functions such as drop and astype IgnoreRaise: TypeAlias = Literal["ignore", "raise"] diff --git a/pandas-stubs/core/tools/datetimes.pyi b/pandas-stubs/core/tools/datetimes.pyi index 6ed6fe864..fa32eceff 100644 --- a/pandas-stubs/core/tools/datetimes.pyi +++ b/pandas-stubs/core/tools/datetimes.pyi @@ -26,9 +26,9 @@ from typing_extensions import TypeAlias from pandas._libs.tslibs import NaTType from pandas._typing import ( AnyArrayLike, - DateTimeErrorChoices, DictConvertible, IgnoreRaise, + IgnoreRaiseCoerce, TimestampConvertibleTypes, npt, ) @@ -70,7 +70,7 @@ def to_datetime( @overload def to_datetime( arg: Series | DictConvertible, - errors: DateTimeErrorChoices = ..., + errors: IgnoreRaiseCoerce = ..., dayfirst: bool = ..., yearfirst: bool = ..., utc: bool | None = ..., @@ -91,7 +91,7 @@ def to_datetime( | npt.NDArray[np.int_] | Index | ExtensionArray, - errors: DateTimeErrorChoices = ..., + errors: IgnoreRaiseCoerce = ..., dayfirst: bool = ..., yearfirst: bool = ..., utc: bool | None = ..., diff --git a/pandas-stubs/core/tools/numeric.pyi b/pandas-stubs/core/tools/numeric.pyi index e7303c19d..a44b12575 100644 --- a/pandas-stubs/core/tools/numeric.pyi +++ b/pandas-stubs/core/tools/numeric.pyi @@ -1 +1,42 @@ -def to_numeric(arg, errors: str = ..., downcast=...): ... +from typing import ( + Literal, + Union, + overload, +) + +import numpy as np +import pandas as pd +from typing_extensions import TypeAlias + +from pandas._typing import ( + IgnoreRaiseCoerce, + Scalar, + npt, +) + +_Downcast: TypeAlias = Union[Literal["integer", "signed", "unsigned", "float"], None] + +@overload +def to_numeric( + arg: Scalar, + errors: Literal["raise", "coerce"] = ..., + downcast: _Downcast = ..., +) -> float: ... +@overload +def to_numeric( + arg: Scalar, + errors: Literal["ignore"], + downcast: _Downcast = ..., +) -> Scalar: ... +@overload +def to_numeric( + arg: list | tuple | np.ndarray, + errors: IgnoreRaiseCoerce = ..., + downcast: _Downcast = ..., +) -> npt.NDArray: ... +@overload +def to_numeric( + arg: pd.Series, + errors: IgnoreRaiseCoerce = ..., + downcast: _Downcast = ..., +) -> pd.Series: ... diff --git a/pandas-stubs/core/tools/timedeltas.pyi b/pandas-stubs/core/tools/timedeltas.pyi index c2b881628..5f6817b8f 100644 --- a/pandas-stubs/core/tools/timedeltas.pyi +++ b/pandas-stubs/core/tools/timedeltas.pyi @@ -16,20 +16,20 @@ from pandas._libs.tslibs import Timedelta from pandas._libs.tslibs.timedeltas import TimeDeltaUnitChoices from pandas._typing import ( ArrayLike, - DateTimeErrorChoices, + IgnoreRaiseCoerce, ) @overload def to_timedelta( arg: str | float | timedelta, unit: TimeDeltaUnitChoices | None = ..., - errors: DateTimeErrorChoices = ..., + errors: IgnoreRaiseCoerce = ..., ) -> Timedelta: ... @overload def to_timedelta( arg: Series, unit: TimeDeltaUnitChoices | None = ..., - errors: DateTimeErrorChoices = ..., + errors: IgnoreRaiseCoerce = ..., ) -> TimedeltaSeries: ... @overload def to_timedelta( @@ -40,5 +40,5 @@ def to_timedelta( | ArrayLike | Index, unit: TimeDeltaUnitChoices | None = ..., - errors: DateTimeErrorChoices = ..., + errors: IgnoreRaiseCoerce = ..., ) -> TimedeltaIndex: ... diff --git a/tests/test_pandas.py b/tests/test_pandas.py index 2c9751818..d5f73991b 100644 --- a/tests/test_pandas.py +++ b/tests/test_pandas.py @@ -457,6 +457,111 @@ def test_eval(): ) +def test_to_numeric_scalar() -> None: + check(assert_type(pd.to_numeric(1), float), int) + check(assert_type(pd.to_numeric("1.2"), float), float) + check(assert_type(pd.to_numeric("blerg", errors="coerce"), float), float) + check(assert_type(pd.to_numeric("blerg", errors="ignore"), Scalar), str) + check(assert_type(pd.to_numeric(1, downcast="signed"), float), int) + check(assert_type(pd.to_numeric(1, downcast="unsigned"), float), int) + check(assert_type(pd.to_numeric(1, downcast="float"), float), int) + check(assert_type(pd.to_numeric(1, downcast="integer"), float), int) + + +def test_to_numeric_array_like() -> None: + check( + assert_type( + pd.to_numeric([1, 2, 3]), + npt.NDArray, + ), + np.ndarray, + ) + check( + assert_type( + pd.to_numeric([1.0, 2.0, 3.0]), + npt.NDArray, + ), + np.ndarray, + ) + check( + assert_type( + pd.to_numeric([1.0, 2.0, "3.0"]), + npt.NDArray, + ), + np.ndarray, + ) + check( + assert_type( + pd.to_numeric(np.array([1.0, 2.0, "3.0"], dtype=object)), + npt.NDArray, + ), + np.ndarray, + ) + check( + assert_type( + pd.to_numeric([1.0, 2.0, "blerg"], errors="coerce"), + npt.NDArray, + ), + np.ndarray, + ) + check( + assert_type(pd.to_numeric([1.0, 2.0, "blerg"], errors="ignore"), npt.NDArray), + np.ndarray, + ) + check( + assert_type( + pd.to_numeric((1.0, 2.0, 3.0)), + npt.NDArray, + ), + np.ndarray, + ) + check( + assert_type(pd.to_numeric([1, 2, 3], downcast="unsigned"), npt.NDArray), + np.ndarray, + ) + + +def test_to_numeric_array_series() -> None: + check( + assert_type( + pd.to_numeric(pd.Series([1, 2, 3])), + pd.Series, + ), + pd.Series, + ) + check( + assert_type( + pd.to_numeric(pd.Series([1, 2, "blerg"]), errors="coerce"), + pd.Series, + ), + pd.Series, + ) + check( + assert_type( + pd.to_numeric(pd.Series([1, 2, "blerg"]), errors="ignore"), pd.Series + ), + pd.Series, + ) + check( + assert_type(pd.to_numeric(pd.Series([1, 2, 3]), downcast="signed"), pd.Series), + pd.Series, + ) + check( + assert_type( + pd.to_numeric(pd.Series([1, 2, 3]), downcast="unsigned"), pd.Series + ), + pd.Series, + ) + check( + assert_type(pd.to_numeric(pd.Series([1, 2, 3]), downcast="integer"), pd.Series), + pd.Series, + ) + check( + assert_type(pd.to_numeric(pd.Series([1, 2, 3]), downcast="float"), pd.Series), + pd.Series, + ) + + def test_wide_to_long(): df = pd.DataFrame( {