Skip to content

Commit 4145278

Browse files
authored
TYP: format.formats (#55393)
* TYP: format.formats * Fix MultiIndex._values
1 parent 364c9cb commit 4145278

File tree

4 files changed

+44
-37
lines changed

4 files changed

+44
-37
lines changed

pandas/core/arrays/categorical.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1819,23 +1819,27 @@ def _empty( # type: ignore[override]
18191819

18201820
return arr._from_backing_data(backing)
18211821

1822-
def _internal_get_values(self):
1822+
def _internal_get_values(self) -> ArrayLike:
18231823
"""
18241824
Return the values.
18251825
18261826
For internal compatibility with pandas formatting.
18271827
18281828
Returns
18291829
-------
1830-
np.ndarray or Index
1831-
A numpy array of the same dtype as categorical.categories.dtype or
1832-
Index if datetime / periods.
1830+
np.ndarray or ExtensionArray
1831+
A numpy array or ExtensionArray of the same dtype as
1832+
categorical.categories.dtype.
18331833
"""
18341834
# if we are a datetime and period index, return Index to keep metadata
18351835
if needs_i8_conversion(self.categories.dtype):
1836-
return self.categories.take(self._codes, fill_value=NaT)
1836+
return self.categories.take(self._codes, fill_value=NaT)._values
18371837
elif is_integer_dtype(self.categories.dtype) and -1 in self._codes:
1838-
return self.categories.astype("object").take(self._codes, fill_value=np.nan)
1838+
return (
1839+
self.categories.astype("object")
1840+
.take(self._codes, fill_value=np.nan)
1841+
._values
1842+
)
18391843
return np.array(self)
18401844

18411845
def check_for_ordered(self, op) -> None:

pandas/core/arrays/timedeltas.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ def _format_native_types(
471471
from pandas.io.formats.format import get_format_timedelta64
472472

473473
# Relies on TimeDelta._repr_base
474-
formatter = get_format_timedelta64(self._ndarray, na_rep)
474+
formatter = get_format_timedelta64(self, na_rep)
475475
# equiv: np.array([formatter(x) for x in self._ndarray])
476476
# but independent of dimension
477477
return np.frompyfunc(formatter, 1, 1)(self._ndarray)

pandas/core/indexes/multi.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,7 @@
7373
)
7474
from pandas.core.dtypes.generic import (
7575
ABCDataFrame,
76-
ABCDatetimeIndex,
7776
ABCSeries,
78-
ABCTimedeltaIndex,
7977
)
8078
from pandas.core.dtypes.inference import is_array_like
8179
from pandas.core.dtypes.missing import (
@@ -768,8 +766,8 @@ def _values(self) -> np.ndarray:
768766
vals = cast("CategoricalIndex", vals)
769767
vals = vals._data._internal_get_values()
770768

771-
if isinstance(vals.dtype, ExtensionDtype) or isinstance(
772-
vals, (ABCDatetimeIndex, ABCTimedeltaIndex)
769+
if isinstance(vals.dtype, ExtensionDtype) or lib.is_np_dtype(
770+
vals.dtype, "mM"
773771
):
774772
vals = vals.astype(object)
775773

pandas/io/formats/format.py

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
from pandas.core.arrays import (
7373
Categorical,
7474
DatetimeArray,
75+
ExtensionArray,
7576
TimedeltaArray,
7677
)
7778
from pandas.core.arrays.string_ import StringDtype
@@ -108,6 +109,7 @@
108109
SequenceNotStr,
109110
StorageOptions,
110111
WriteBuffer,
112+
npt,
111113
)
112114

113115
from pandas import (
@@ -1216,7 +1218,7 @@ def get_buffer(
12161218

12171219

12181220
def format_array(
1219-
values: Any,
1221+
values: ArrayLike,
12201222
formatter: Callable | None,
12211223
float_format: FloatFormatType | None = None,
12221224
na_rep: str = "NaN",
@@ -1233,7 +1235,7 @@ def format_array(
12331235
12341236
Parameters
12351237
----------
1236-
values
1238+
values : np.ndarray or ExtensionArray
12371239
formatter
12381240
float_format
12391241
na_rep
@@ -1258,10 +1260,13 @@ def format_array(
12581260
fmt_klass: type[GenericArrayFormatter]
12591261
if lib.is_np_dtype(values.dtype, "M"):
12601262
fmt_klass = Datetime64Formatter
1263+
values = cast(DatetimeArray, values)
12611264
elif isinstance(values.dtype, DatetimeTZDtype):
12621265
fmt_klass = Datetime64TZFormatter
1266+
values = cast(DatetimeArray, values)
12631267
elif lib.is_np_dtype(values.dtype, "m"):
12641268
fmt_klass = Timedelta64Formatter
1269+
values = cast(TimedeltaArray, values)
12651270
elif isinstance(values.dtype, ExtensionDtype):
12661271
fmt_klass = ExtensionArrayFormatter
12671272
elif lib.is_np_dtype(values.dtype, "fc"):
@@ -1300,7 +1305,7 @@ def format_array(
13001305
class GenericArrayFormatter:
13011306
def __init__(
13021307
self,
1303-
values: Any,
1308+
values: ArrayLike,
13041309
digits: int = 7,
13051310
formatter: Callable | None = None,
13061311
na_rep: str = "NaN",
@@ -1622,9 +1627,11 @@ def _format_strings(self) -> list[str]:
16221627

16231628

16241629
class Datetime64Formatter(GenericArrayFormatter):
1630+
values: DatetimeArray
1631+
16251632
def __init__(
16261633
self,
1627-
values: np.ndarray | Series | DatetimeIndex | DatetimeArray,
1634+
values: DatetimeArray,
16281635
nat_rep: str = "NaT",
16291636
date_format: None = None,
16301637
**kwargs,
@@ -1637,21 +1644,23 @@ def _format_strings(self) -> list[str]:
16371644
"""we by definition have DO NOT have a TZ"""
16381645
values = self.values
16391646

1640-
if not isinstance(values, DatetimeIndex):
1641-
values = DatetimeIndex(values)
1647+
dti = DatetimeIndex(values)
16421648

16431649
if self.formatter is not None and callable(self.formatter):
1644-
return [self.formatter(x) for x in values]
1650+
return [self.formatter(x) for x in dti]
16451651

1646-
fmt_values = values._data._format_native_types(
1652+
fmt_values = dti._data._format_native_types(
16471653
na_rep=self.nat_rep, date_format=self.date_format
16481654
)
16491655
return fmt_values.tolist()
16501656

16511657

16521658
class ExtensionArrayFormatter(GenericArrayFormatter):
1659+
values: ExtensionArray
1660+
16531661
def _format_strings(self) -> list[str]:
16541662
values = extract_array(self.values, extract_numpy=True)
1663+
values = cast(ExtensionArray, values)
16551664

16561665
formatter = self.formatter
16571666
fallback_formatter = None
@@ -1813,13 +1822,10 @@ def get_format_datetime64(
18131822

18141823

18151824
def get_format_datetime64_from_values(
1816-
values: np.ndarray | DatetimeArray | DatetimeIndex, date_format: str | None
1825+
values: DatetimeArray, date_format: str | None
18171826
) -> str | None:
18181827
"""given values and a date_format, return a string format"""
1819-
if isinstance(values, np.ndarray) and values.ndim > 1:
1820-
# We don't actually care about the order of values, and DatetimeIndex
1821-
# only accepts 1D values
1822-
values = values.ravel()
1828+
assert isinstance(values, DatetimeArray)
18231829

18241830
ido = is_dates_only(values)
18251831
if ido:
@@ -1829,6 +1835,8 @@ def get_format_datetime64_from_values(
18291835

18301836

18311837
class Datetime64TZFormatter(Datetime64Formatter):
1838+
values: DatetimeArray
1839+
18321840
def _format_strings(self) -> list[str]:
18331841
"""we by definition have a TZ"""
18341842
ido = is_dates_only(self.values)
@@ -1842,9 +1850,11 @@ def _format_strings(self) -> list[str]:
18421850

18431851

18441852
class Timedelta64Formatter(GenericArrayFormatter):
1853+
values: TimedeltaArray
1854+
18451855
def __init__(
18461856
self,
1847-
values: np.ndarray | TimedeltaIndex,
1857+
values: TimedeltaArray,
18481858
nat_rep: str = "NaT",
18491859
box: bool = False,
18501860
**kwargs,
@@ -1861,7 +1871,7 @@ def _format_strings(self) -> list[str]:
18611871

18621872

18631873
def get_format_timedelta64(
1864-
values: np.ndarray | TimedeltaIndex | TimedeltaArray,
1874+
values: TimedeltaArray,
18651875
nat_rep: str | float = "NaT",
18661876
box: bool = False,
18671877
) -> Callable:
@@ -1872,18 +1882,13 @@ def get_format_timedelta64(
18721882
If box, then show the return in quotes
18731883
"""
18741884
values_int = values.view(np.int64)
1885+
values_int = cast("npt.NDArray[np.int64]", values_int)
18751886

18761887
consider_values = values_int != iNaT
18771888

18781889
one_day_nanos = 86400 * 10**9
1879-
# error: Unsupported operand types for % ("ExtensionArray" and "int")
1880-
not_midnight = values_int % one_day_nanos != 0 # type: ignore[operator]
1881-
# error: Argument 1 to "__call__" of "ufunc" has incompatible type
1882-
# "Union[Any, ExtensionArray, ndarray]"; expected
1883-
# "Union[Union[int, float, complex, str, bytes, generic],
1884-
# Sequence[Union[int, float, complex, str, bytes, generic]],
1885-
# Sequence[Sequence[Any]], _SupportsArray]"
1886-
both = np.logical_and(consider_values, not_midnight) # type: ignore[arg-type]
1890+
not_midnight = values_int % one_day_nanos != 0
1891+
both = np.logical_and(consider_values, not_midnight)
18871892
even_days = both.sum() == 0
18881893

18891894
if even_days:
@@ -1941,7 +1946,7 @@ def just(x: str) -> str:
19411946
return result
19421947

19431948

1944-
def _trim_zeros_complex(str_complexes: np.ndarray, decimal: str = ".") -> list[str]:
1949+
def _trim_zeros_complex(str_complexes: ArrayLike, decimal: str = ".") -> list[str]:
19451950
"""
19461951
Separates the real and imaginary parts from the complex number, and
19471952
executes the _trim_zeros_float method on each of those.
@@ -1987,7 +1992,7 @@ def _trim_zeros_single_float(str_float: str) -> str:
19871992

19881993

19891994
def _trim_zeros_float(
1990-
str_floats: np.ndarray | list[str], decimal: str = "."
1995+
str_floats: ArrayLike | list[str], decimal: str = "."
19911996
) -> list[str]:
19921997
"""
19931998
Trims the maximum number of trailing zeros equally from
@@ -2000,7 +2005,7 @@ def _trim_zeros_float(
20002005
def is_number_with_decimal(x) -> bool:
20012006
return re.match(number_regex, x) is not None
20022007

2003-
def should_trim(values: np.ndarray | list[str]) -> bool:
2008+
def should_trim(values: ArrayLike | list[str]) -> bool:
20042009
"""
20052010
Determine if an array of strings should be trimmed.
20062011

0 commit comments

Comments
 (0)