1from __future__ import annotations
2
3from typing import (
4 TYPE_CHECKING,
5 Any,
6)
7
8import numpy as np
9
10from pandas._libs import lib
11from pandas.errors import LossySetitemError
12
13from pandas.core.dtypes.cast import np_can_hold_element
14from pandas.core.dtypes.common import is_numeric_dtype
15
16if TYPE_CHECKING:
17 from pandas._typing import (
18 ArrayLike,
19 npt,
20 )
21
22
23def to_numpy_dtype_inference(
24 arr: ArrayLike, dtype: npt.DTypeLike | None, na_value, hasna: bool
25) -> tuple[npt.DTypeLike, Any]:
26 if dtype is None and is_numeric_dtype(arr.dtype):
27 dtype_given = False
28 if hasna:
29 if arr.dtype.kind == "b":
30 dtype = np.dtype(np.object_)
31 else:
32 if arr.dtype.kind in "iu":
33 dtype = np.dtype(np.float64)
34 else:
35 dtype = arr.dtype.numpy_dtype # type: ignore[union-attr]
36 if na_value is lib.no_default:
37 na_value = np.nan
38 else:
39 dtype = arr.dtype.numpy_dtype # type: ignore[union-attr]
40 elif dtype is not None:
41 dtype = np.dtype(dtype)
42 dtype_given = True
43 else:
44 dtype_given = True
45
46 if na_value is lib.no_default:
47 if dtype is None or not hasna:
48 na_value = arr.dtype.na_value
49 elif dtype.kind == "f": # type: ignore[union-attr]
50 na_value = np.nan
51 elif dtype.kind == "M": # type: ignore[union-attr]
52 na_value = np.datetime64("nat")
53 elif dtype.kind == "m": # type: ignore[union-attr]
54 na_value = np.timedelta64("nat")
55 else:
56 na_value = arr.dtype.na_value
57
58 if not dtype_given and hasna:
59 try:
60 np_can_hold_element(dtype, na_value) # type: ignore[arg-type]
61 except LossySetitemError:
62 dtype = np.dtype(np.object_)
63 return dtype, na_value