Skip to content

Commit 0c1df38

Browse files
committed
Merge remote-tracking branch 'upstream/main' into docs_bisect
2 parents 046badb + e6024c1 commit 0c1df38

17 files changed

+122
-123
lines changed

pandas/core/apply.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ def agg_dict_like(self) -> DataFrame | Series:
506506
ktu._set_names(selected_obj.columns.names)
507507
keys_to_use = ktu
508508

509-
axis = 0 if isinstance(obj, ABCSeries) else 1
509+
axis: AxisInt = 0 if isinstance(obj, ABCSeries) else 1
510510
# error: Key expression in dictionary comprehension has incompatible type
511511
# "Hashable"; expected type "NDFrame" [misc]
512512
result = concat(
@@ -932,7 +932,7 @@ def apply_str(self) -> DataFrame | Series:
932932

933933

934934
class FrameRowApply(FrameApply):
935-
axis = 0
935+
axis: AxisInt = 0
936936

937937
def apply_broadcast(self, target: DataFrame) -> DataFrame:
938938
return super().apply_broadcast(target)
@@ -992,7 +992,7 @@ def wrap_results_for_axis(
992992

993993

994994
class FrameColumnApply(FrameApply):
995-
axis = 1
995+
axis: AxisInt = 1
996996

997997
def apply_broadcast(self, target: DataFrame) -> DataFrame:
998998
result = super().apply_broadcast(target.T)
@@ -1069,7 +1069,7 @@ def infer_to_same_shape(self, results: ResType, res_index: Index) -> DataFrame:
10691069

10701070
class SeriesApply(NDFrameApply):
10711071
obj: Series
1072-
axis = 0
1072+
axis: AxisInt = 0
10731073

10741074
def __init__(
10751075
self,
@@ -1199,7 +1199,7 @@ def transform(self):
11991199

12001200

12011201
class ResamplerWindowApply(Apply):
1202-
axis = 0
1202+
axis: AxisInt = 0
12031203
obj: Resampler | BaseWindow
12041204

12051205
def __init__(

pandas/core/arrays/datetimelike.py

+35-47
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
Period,
3737
Resolution,
3838
Tick,
39+
Timedelta,
3940
Timestamp,
4041
astype_overflowsafe,
4142
delta_to_nanoseconds,
@@ -1122,7 +1123,7 @@ def _get_i8_values_and_mask(
11221123
if isinstance(other, Period):
11231124
i8values = other.ordinal
11241125
mask = None
1125-
elif isinstance(other, Timestamp):
1126+
elif isinstance(other, (Timestamp, Timedelta)):
11261127
i8values = other.value
11271128
mask = None
11281129
else:
@@ -1203,33 +1204,12 @@ def _sub_datetimelike_scalar(self, other: datetime | np.datetime64):
12031204
self = cast("DatetimeArray", self)
12041205
# subtract a datetime from myself, yielding a ndarray[timedelta64[ns]]
12051206

1206-
# error: Non-overlapping identity check (left operand type: "Union[datetime,
1207-
# datetime64]", right operand type: "NaTType") [comparison-overlap]
1208-
assert other is not NaT # type: ignore[comparison-overlap]
1209-
other = Timestamp(other)
1210-
# error: Non-overlapping identity check (left operand type: "Timestamp",
1211-
# right operand type: "NaTType")
1212-
if other is NaT: # type: ignore[comparison-overlap]
1207+
if isna(other):
1208+
# i.e. np.datetime64("NaT")
12131209
return self - NaT
12141210

1215-
try:
1216-
self._assert_tzawareness_compat(other)
1217-
except TypeError as err:
1218-
new_message = str(err).replace("compare", "subtract")
1219-
raise type(err)(new_message) from err
1220-
1221-
i8 = self.asi8
1222-
result = checked_add_with_arr(i8, -other.value, arr_mask=self._isnan)
1223-
res_m8 = result.view(f"timedelta64[{self._unit}]")
1224-
1225-
new_freq = None
1226-
if isinstance(self.freq, Tick):
1227-
# adding a scalar preserves freq
1228-
new_freq = self.freq
1229-
1230-
from pandas.core.arrays import TimedeltaArray
1231-
1232-
return TimedeltaArray._simple_new(res_m8, dtype=res_m8.dtype, freq=new_freq)
1211+
other = Timestamp(other)
1212+
return self._sub_datetimelike(other)
12331213

12341214
@final
12351215
def _sub_datetime_arraylike(self, other):
@@ -1241,19 +1221,28 @@ def _sub_datetime_arraylike(self, other):
12411221

12421222
self = cast("DatetimeArray", self)
12431223
other = ensure_wrapped_if_datetimelike(other)
1224+
return self._sub_datetimelike(other)
1225+
1226+
@final
1227+
def _sub_datetimelike(self, other: Timestamp | DatetimeArray) -> TimedeltaArray:
1228+
self = cast("DatetimeArray", self)
1229+
1230+
from pandas.core.arrays import TimedeltaArray
12441231

12451232
try:
12461233
self._assert_tzawareness_compat(other)
12471234
except TypeError as err:
12481235
new_message = str(err).replace("compare", "subtract")
12491236
raise type(err)(new_message) from err
12501237

1251-
self_i8 = self.asi8
1252-
other_i8 = other.asi8
1253-
new_values = checked_add_with_arr(
1254-
self_i8, -other_i8, arr_mask=self._isnan, b_mask=other._isnan
1238+
other_i8, o_mask = self._get_i8_values_and_mask(other)
1239+
res_values = checked_add_with_arr(
1240+
self.asi8, -other_i8, arr_mask=self._isnan, b_mask=o_mask
12551241
)
1256-
return new_values.view("timedelta64[ns]")
1242+
res_m8 = res_values.view(f"timedelta64[{self._unit}]")
1243+
1244+
new_freq = self._get_arithmetic_result_freq(other)
1245+
return TimedeltaArray._simple_new(res_m8, dtype=res_m8.dtype, freq=new_freq)
12571246

12581247
@final
12591248
def _sub_period(self, other: Period) -> npt.NDArray[np.object_]:
@@ -1289,24 +1278,15 @@ def _add_timedeltalike_scalar(self, other):
12891278
Same type as self
12901279
"""
12911280
if isna(other):
1292-
# i.e np.timedelta64("NaT"), not recognized by delta_to_nanoseconds
1281+
# i.e np.timedelta64("NaT")
12931282
new_values = np.empty(self.shape, dtype="i8").view(self._ndarray.dtype)
12941283
new_values.fill(iNaT)
12951284
return type(self)._simple_new(new_values, dtype=self.dtype)
12961285

12971286
# PeriodArray overrides, so we only get here with DTA/TDA
12981287
self = cast("DatetimeArray | TimedeltaArray", self)
1299-
inc = delta_to_nanoseconds(other, reso=self._reso)
1300-
1301-
new_values = checked_add_with_arr(self.asi8, inc, arr_mask=self._isnan)
1302-
new_values = new_values.view(self._ndarray.dtype)
1303-
1304-
new_freq = None
1305-
if isinstance(self.freq, Tick) or is_period_dtype(self.dtype):
1306-
# adding a scalar preserves freq
1307-
new_freq = self.freq
1308-
1309-
return type(self)._simple_new(new_values, dtype=self.dtype, freq=new_freq)
1288+
other = Timedelta(other)._as_unit(self._unit)
1289+
return self._add_timedeltalike(other)
13101290

13111291
def _add_timedelta_arraylike(
13121292
self, other: TimedeltaArray | npt.NDArray[np.timedelta64]
@@ -1334,13 +1314,21 @@ def _add_timedelta_arraylike(
13341314
else:
13351315
other = other._as_unit(self._unit)
13361316

1337-
self_i8 = self.asi8
1338-
other_i8 = other.asi8
1317+
return self._add_timedeltalike(other)
1318+
1319+
@final
1320+
def _add_timedeltalike(self, other: Timedelta | TimedeltaArray):
1321+
self = cast("DatetimeArray | TimedeltaArray", self)
1322+
1323+
other_i8, o_mask = self._get_i8_values_and_mask(other)
13391324
new_values = checked_add_with_arr(
1340-
self_i8, other_i8, arr_mask=self._isnan, b_mask=other._isnan
1325+
self.asi8, other_i8, arr_mask=self._isnan, b_mask=o_mask
13411326
)
13421327
res_values = new_values.view(self._ndarray.dtype)
1343-
return type(self)._simple_new(res_values, dtype=self.dtype)
1328+
1329+
new_freq = self._get_arithmetic_result_freq(other)
1330+
1331+
return type(self)._simple_new(res_values, dtype=self.dtype, freq=new_freq)
13441332

13451333
@final
13461334
def _add_nat(self):

pandas/core/construction.py

+9
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
)
5050
from pandas.core.dtypes.common import (
5151
is_datetime64_ns_dtype,
52+
is_dtype_equal,
5253
is_extension_array_dtype,
5354
is_float_dtype,
5455
is_integer_dtype,
@@ -328,6 +329,14 @@ def array(
328329
if isinstance(dtype, str):
329330
dtype = registry.find(dtype) or dtype
330331

332+
if isinstance(data, ExtensionArray) and (
333+
dtype is None or is_dtype_equal(dtype, data.dtype)
334+
):
335+
# e.g. TimedeltaArray[s], avoid casting to PandasArray
336+
if copy:
337+
return data.copy()
338+
return data
339+
331340
if is_extension_array_dtype(dtype):
332341
cls = cast(ExtensionDtype, dtype).construct_array_type()
333342
return cls._from_sequence(data, dtype=dtype, copy=copy)

pandas/core/frame.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -7586,7 +7586,7 @@ class diet
75867586
# Arithmetic Methods
75877587

75887588
def _cmp_method(self, other, op):
7589-
axis = 1 # only relevant for Series other case
7589+
axis: Literal[1] = 1 # only relevant for Series other case
75907590

75917591
self, other = ops.align_method_FRAME(self, other, axis, flex=False, level=None)
75927592

@@ -7598,7 +7598,7 @@ def _arith_method(self, other, op):
75987598
if ops.should_reindex_frame_op(self, other, op, 1, 1, None, None):
75997599
return ops.frame_arith_method_with_reindex(self, other, op)
76007600

7601-
axis = 1 # only relevant for Series other case
7601+
axis: Literal[1] = 1 # only relevant for Series other case
76027602
other = ops.maybe_prepare_scalar_for_op(other, (self.shape[axis],))
76037603

76047604
self, other = ops.align_method_FRAME(self, other, axis, flex=True, level=None)
@@ -10657,7 +10657,7 @@ def c(x):
1065710657
if not drop:
1065810658
# Find non-matching labels along the given axis
1065910659
# and append missing correlations (GH 22375)
10660-
raxis = 1 if axis == 0 else 0
10660+
raxis: AxisInt = 1 if axis == 0 else 0
1066110661
result_index = this._get_axis(raxis).union(other._get_axis(raxis))
1066210662
idx_diff = result_index.difference(correl.index)
1066310663

@@ -11666,7 +11666,7 @@ def isin(self, values: Series | DataFrame | Sequence | Mapping) -> DataFrame:
1166611666
"columns": 1,
1166711667
}
1166811668
_AXIS_LEN = len(_AXIS_ORDERS)
11669-
_info_axis_number = 1
11669+
_info_axis_number: Literal[1] = 1
1167011670
_info_axis_name: Literal["columns"] = "columns"
1167111671

1167211672
index = properties.AxisProperty(

pandas/core/generic.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ def _get_axis(self, axis: Axis) -> Index:
577577

578578
@final
579579
@classmethod
580-
def _get_block_manager_axis(cls, axis: Axis) -> int:
580+
def _get_block_manager_axis(cls, axis: Axis) -> AxisInt:
581581
"""Map the axis to the block_manager axis."""
582582
axis = cls._get_axis_number(axis)
583583
ndim = cls._AXIS_LEN
@@ -1705,7 +1705,7 @@ def _is_level_reference(self, key: Level, axis: Axis = 0) -> bool_t:
17051705
)
17061706

17071707
@final
1708-
def _is_label_reference(self, key: Level, axis: int = 0) -> bool_t:
1708+
def _is_label_reference(self, key: Level, axis: Axis = 0) -> bool_t:
17091709
"""
17101710
Test whether a key is a label reference for a given axis.
17111711
@@ -1725,8 +1725,8 @@ def _is_label_reference(self, key: Level, axis: int = 0) -> bool_t:
17251725
-------
17261726
is_label: bool
17271727
"""
1728-
axis = self._get_axis_number(axis)
1729-
other_axes = (ax for ax in range(self._AXIS_LEN) if ax != axis)
1728+
axis_int = self._get_axis_number(axis)
1729+
other_axes = (ax for ax in range(self._AXIS_LEN) if ax != axis_int)
17301730

17311731
return (
17321732
key is not None

pandas/core/indexing.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1111,7 +1111,7 @@ class _LocIndexer(_LocationIndexer):
11111111
# Key Checks
11121112

11131113
@doc(_LocationIndexer._validate_key)
1114-
def _validate_key(self, key, axis: AxisInt):
1114+
def _validate_key(self, key, axis: Axis):
11151115
# valid for a collection of labels (we check their presence later)
11161116
# slice of labels (where start-end in labels)
11171117
# slice of integers (only if in the labels)

pandas/core/reshape/concat.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
from pandas._typing import (
2323
Axis,
24+
AxisInt,
2425
HashableT,
2526
)
2627
from pandas.util._decorators import (
@@ -636,7 +637,7 @@ def _get_new_axes(self) -> list[Index]:
636637
for i in range(ndim)
637638
]
638639

639-
def _get_comb_axis(self, i: int) -> Index:
640+
def _get_comb_axis(self, i: AxisInt) -> Index:
640641
data_axis = self.objs[0]._get_block_manager_axis(i)
641642
return get_objs_combined_axis(
642643
self.objs,

pandas/core/series.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -6228,7 +6228,7 @@ def mask( # type: ignore[override]
62286228
# Add index
62296229
_AXIS_ORDERS: list[Literal["index", "columns"]] = ["index"]
62306230
_AXIS_LEN = len(_AXIS_ORDERS)
6231-
_info_axis_number = 0
6231+
_info_axis_number: Literal[0] = 0
62326232
_info_axis_name: Literal["index"] = "index"
62336233

62346234
index = properties.AxisProperty(

pandas/io/excel/_base.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1662,7 +1662,7 @@ def __init__(
16621662
f"only the xls format is supported. Install openpyxl instead."
16631663
)
16641664
elif ext and ext != "xls":
1665-
stacklevel = find_stack_level()
1665+
stacklevel = find_stack_level(inspect.currentframe())
16661666
warnings.warn(
16671667
f"Your version of xlrd is {xlrd_version}. In xlrd >= 2.0, "
16681668
f"only the xls format is supported. Install "

0 commit comments

Comments
 (0)