Skip to content

Commit

Permalink
TYP: timedeltas.pyi (#40766)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbrockmendel committed Apr 14, 2021
1 parent ce6162b commit 84d9c5e
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 4 deletions.
100 changes: 100 additions & 0 deletions pandas/_libs/tslibs/timedeltas.pyi
@@ -0,0 +1,100 @@
from datetime import timedelta
from typing import (
ClassVar,
Type,
TypeVar,
overload,
)

import numpy as np

from pandas._libs.tslibs import (
NaTType,
Tick,
)

_S = TypeVar("_S")


def ints_to_pytimedelta(
arr: np.ndarray, # const int64_t[:]
box: bool = ...,
) -> np.ndarray: ... # np.ndarray[object]


def array_to_timedelta64(
values: np.ndarray, # ndarray[object]
unit: str | None = ...,
errors: str = ...,
) -> np.ndarray: ... # np.ndarray[m8ns]


def parse_timedelta_unit(unit: str | None) -> str: ...


def delta_to_nanoseconds(delta: Tick | np.timedelta64 | timedelta | int) -> int: ...


class Timedelta(timedelta):
min: ClassVar[Timedelta]
max: ClassVar[Timedelta]
resolution: ClassVar[Timedelta]
value: int # np.int64

# error: "__new__" must return a class instance (got "Union[Timedelta, NaTType]")
def __new__( # type: ignore[misc]
cls: Type[_S],
value=...,
unit=...,
**kwargs
) -> _S | NaTType: ...

@property
def days(self) -> int: ...
@property
def seconds(self) -> int: ...
@property
def microseconds(self) -> int: ...
def total_seconds(self) -> float: ...

def to_pytimedelta(self) -> timedelta: ...
def to_timedelta64(self) -> np.timedelta64: ...

@property
def asm8(self) -> np.timedelta64: ...

# TODO: round/floor/ceil could return NaT?
def round(self: _S, freq) -> _S: ...
def floor(self: _S, freq) -> _S: ...
def ceil(self: _S, freq) -> _S: ...

@property
def resolution_string(self) -> str: ...

def __add__(self, other: timedelta) -> timedelta: ...
def __radd__(self, other: timedelta) -> timedelta: ...
def __sub__(self, other: timedelta) -> timedelta: ...
def __rsub__(self, other: timedelta) -> timedelta: ...
def __neg__(self) -> timedelta: ...
def __pos__(self) -> timedelta: ...
def __abs__(self) -> timedelta: ...
def __mul__(self, other: float) -> timedelta: ...
def __rmul__(self, other: float) -> timedelta: ...

@overload
def __floordiv__(self, other: timedelta) -> int: ...
@overload
def __floordiv__(self, other: int) -> timedelta: ...

@overload
def __truediv__(self, other: timedelta) -> float: ...
@overload
def __truediv__(self, other: float) -> timedelta: ...
def __mod__(self, other: timedelta) -> timedelta: ...
def __divmod__(self, other: timedelta) -> tuple[int, timedelta]: ...

def __le__(self, other: timedelta) -> bool: ...
def __lt__(self, other: timedelta) -> bool: ...
def __ge__(self, other: timedelta) -> bool: ...
def __gt__(self, other: timedelta) -> bool: ...
def __hash__(self) -> int: ...
17 changes: 14 additions & 3 deletions pandas/core/dtypes/cast.py
Expand Up @@ -191,9 +191,15 @@ def maybe_box_native(value: Scalar) -> Scalar:
if is_datetime_or_timedelta_dtype(value):
value = maybe_box_datetimelike(value)
elif is_float(value):
value = float(value)
# error: Argument 1 to "float" has incompatible type
# "Union[Union[str, int, float, bool], Union[Any, Any, Timedelta, Any]]";
# expected "Union[SupportsFloat, _SupportsIndex, str]"
value = float(value) # type: ignore[arg-type]
elif is_integer(value):
value = int(value)
# error: Argument 1 to "int" has incompatible type
# "Union[Union[str, int, float, bool], Union[Any, Any, Timedelta, Any]]";
# pected "Union[str, SupportsInt, _SupportsIndex, _SupportsTrunc]"
value = int(value) # type: ignore[arg-type]
elif is_bool(value):
value = bool(value)
return value
Expand Down Expand Up @@ -2107,10 +2113,15 @@ def validate_numeric_casting(dtype: np.dtype, value: Scalar) -> None:
------
ValueError
"""
# error: Argument 1 to "__call__" of "ufunc" has incompatible type
# "Union[Union[str, int, float, bool], Union[Any, Any, Timedelta, Any]]";
# expected "Union[Union[int, float, complex, str, bytes, generic],
# Sequence[Union[int, float, complex, str, bytes, generic]],
# Sequence[Sequence[Any]], _SupportsArray]"
if (
issubclass(dtype.type, (np.integer, np.bool_))
and is_float(value)
and np.isnan(value)
and np.isnan(value) # type: ignore[arg-type]
):
raise ValueError("Cannot assign nan to integer series")

Expand Down
7 changes: 7 additions & 0 deletions pandas/core/reshape/tile.py
@@ -1,6 +1,11 @@
"""
Quantilization functions and related stuff
"""
from typing import (
Any,
Callable,
)

import numpy as np

from pandas._libs import (
Expand Down Expand Up @@ -550,6 +555,8 @@ def _format_labels(
""" based on the dtype, return our labels """
closed = "right" if right else "left"

formatter: Callable[[Any], Timestamp] | Callable[[Any], Timedelta]

if is_datetime64tz_dtype(dtype):
formatter = lambda x: Timestamp(x, tz=dtype.tz)
adjust = lambda x: x - Timedelta("1ns")
Expand Down
7 changes: 6 additions & 1 deletion pandas/core/tools/timedeltas.py
Expand Up @@ -5,7 +5,10 @@
import numpy as np

from pandas._libs import lib
from pandas._libs.tslibs import NaT
from pandas._libs.tslibs import (
NaT,
NaTType,
)
from pandas._libs.tslibs.timedeltas import (
Timedelta,
parse_timedelta_unit,
Expand Down Expand Up @@ -141,6 +144,8 @@ def to_timedelta(arg, unit=None, errors="raise"):

def _coerce_scalar_to_timedelta_type(r, unit="ns", errors="raise"):
"""Convert string 'r' to a timedelta object."""
result: Timedelta | NaTType # TODO: alias?

try:
result = Timedelta(r, unit)
except ValueError:
Expand Down

0 comments on commit 84d9c5e

Please sign in to comment.