1from __future__ import annotations
2
3from typing import (
4 TYPE_CHECKING,
5 Any,
6)
7
8import numpy as np
9
10from pandas._config import is_nan_na
11
12from pandas._libs import lib
13from pandas._libs.missing import NA
14from pandas.errors import LossySetitemError
15
16from pandas.core.dtypes.cast import np_can_hold_element
17from pandas.core.dtypes.common import is_numeric_dtype
18
19if TYPE_CHECKING:
20 from pandas._typing import (
21 npt,
22 )
23
24 from pandas.core.arrays.base import ExtensionArray
25
26
27def to_numpy_dtype_inference(
28 arr: ExtensionArray,
29 dtype: npt.DTypeLike | None,
30 na_value,
31 hasna: bool,
32) -> tuple[np.dtype | None, Any]:
33 result_dtype: np.dtype | None
34 inferred_numeric_dtype = False
35 if dtype is None and is_numeric_dtype(arr.dtype):
36 inferred_numeric_dtype = True
37 if hasna:
38 if arr.dtype.kind == "b":
39 result_dtype = np.dtype(np.object_)
40 else:
41 if arr.dtype.kind in "iu":
42 result_dtype = np.dtype(np.float64)
43 else:
44 result_dtype = arr.dtype.numpy_dtype # type: ignore[attr-defined]
45 if na_value is lib.no_default:
46 if not is_nan_na():
47 na_value = NA
48 dtype = np.dtype(object)
49 else:
50 na_value = np.nan
51 else:
52 result_dtype = arr.dtype.numpy_dtype # type: ignore[attr-defined]
53 elif dtype is not None:
54 result_dtype = np.dtype(dtype)
55 else:
56 result_dtype = None
57
58 if na_value is lib.no_default:
59 if result_dtype is None or not hasna:
60 na_value = arr.dtype.na_value
61 elif result_dtype.kind == "f":
62 na_value = np.nan
63 elif result_dtype.kind == "M":
64 unit = np.datetime_data(result_dtype)[0] # type: ignore[arg-type]
65 na_value = np.datetime64("NaT", unit) # type: ignore[call-overload]
66 elif result_dtype.kind == "m":
67 unit = np.datetime_data(result_dtype)[0] # type: ignore[arg-type]
68 na_value = np.timedelta64("NaT", unit) # type: ignore[call-overload]
69 else:
70 na_value = arr.dtype.na_value
71
72 if inferred_numeric_dtype and hasna:
73 try:
74 np_can_hold_element(result_dtype, na_value) # type: ignore[arg-type]
75 except LossySetitemError:
76 result_dtype = np.dtype(np.object_)
77 return result_dtype, na_value