29
29
is_datetime64_dtype ,
30
30
is_float_dtype ,
31
31
is_list_like ,
32
+ is_object_dtype ,
32
33
is_period_dtype ,
33
34
pandas_dtype ,
34
35
)
41
42
)
42
43
from pandas .core .dtypes .missing import isna , notna
43
44
45
+ from pandas .core import ops
44
46
import pandas .core .algorithms as algos
45
47
from pandas .core .arrays import datetimelike as dtl
46
48
import pandas .core .common as com
@@ -92,22 +94,44 @@ def wrapper(self, other):
92
94
self ._check_compatible_with (other )
93
95
94
96
result = ordinal_op (other .ordinal )
95
- elif isinstance (other , cls ):
96
- self ._check_compatible_with (other )
97
-
98
- result = ordinal_op (other .asi8 )
99
-
100
- mask = self ._isnan | other ._isnan
101
- if mask .any ():
102
- result [mask ] = nat_result
103
97
104
- return result
105
98
elif other is NaT :
106
99
result = np .empty (len (self .asi8 ), dtype = bool )
107
100
result .fill (nat_result )
108
- else :
101
+
102
+ elif not is_list_like (other ):
109
103
return invalid_comparison (self , other , op )
110
104
105
+ else :
106
+ if isinstance (other , list ):
107
+ # TODO: could use pd.Index to do inference?
108
+ other = np .array (other )
109
+
110
+ if not isinstance (other , (np .ndarray , cls )):
111
+ return invalid_comparison (self , other , op )
112
+
113
+ if is_object_dtype (other ):
114
+ with np .errstate (all = "ignore" ):
115
+ result = ops .comp_method_OBJECT_ARRAY (
116
+ op , self .astype (object ), other
117
+ )
118
+ o_mask = isna (other )
119
+
120
+ elif not is_period_dtype (other ):
121
+ # e.g. is_timedelta64_dtype(other)
122
+ return invalid_comparison (self , other , op )
123
+
124
+ else :
125
+ assert isinstance (other , cls ), type (other )
126
+
127
+ self ._check_compatible_with (other )
128
+
129
+ result = ordinal_op (other .asi8 )
130
+ o_mask = other ._isnan
131
+
132
+ if o_mask .any ():
133
+ result [o_mask ] = nat_result
134
+
111
135
if self ._hasnans :
112
136
result [self ._isnan ] = nat_result
113
137
@@ -215,12 +239,7 @@ def __init__(self, values, freq=None, dtype=None, copy=False):
215
239
216
240
if isinstance (values , type (self )):
217
241
if freq is not None and freq != values .freq :
218
- msg = DIFFERENT_FREQ .format (
219
- cls = type (self ).__name__ ,
220
- own_freq = values .freq .freqstr ,
221
- other_freq = freq .freqstr ,
222
- )
223
- raise IncompatibleFrequency (msg )
242
+ raise raise_on_incompatible (values , freq )
224
243
values , freq = values ._data , values .freq
225
244
226
245
values = np .array (values , dtype = "int64" , copy = copy )
@@ -323,7 +342,7 @@ def _check_compatible_with(self, other):
323
342
if other is NaT :
324
343
return
325
344
if self .freqstr != other .freqstr :
326
- _raise_on_incompatible (self , other )
345
+ raise raise_on_incompatible (self , other )
327
346
328
347
# --------------------------------------------------------------------
329
348
# Data / Attributes
@@ -332,7 +351,7 @@ def _check_compatible_with(self, other):
332
351
def dtype (self ):
333
352
return self ._dtype
334
353
335
- # read -only property overwriting read/ write
354
+ # error: Read -only property cannot override read- write property [misc]
336
355
@property # type: ignore
337
356
def freq (self ):
338
357
"""
@@ -654,7 +673,7 @@ def _sub_period(self, other):
654
673
return new_data
655
674
656
675
def _addsub_int_array (
657
- self , other : np .ndarray , op : Callable [[Any ], Any ],
676
+ self , other : np .ndarray , op : Callable [[Any , Any ], Any ],
658
677
) -> "PeriodArray" :
659
678
"""
660
679
Add or subtract array of integers; equivalent to applying
@@ -682,7 +701,7 @@ def _add_offset(self, other):
682
701
assert not isinstance (other , Tick )
683
702
base = libfrequencies .get_base_alias (other .rule_code )
684
703
if base != self .freq .rule_code :
685
- _raise_on_incompatible (self , other )
704
+ raise raise_on_incompatible (self , other )
686
705
687
706
# Note: when calling parent class's _add_timedeltalike_scalar,
688
707
# it will call delta_to_nanoseconds(delta). Because delta here
@@ -750,7 +769,7 @@ def _add_delta(self, other):
750
769
"""
751
770
if not isinstance (self .freq , Tick ):
752
771
# We cannot add timedelta-like to non-tick PeriodArray
753
- _raise_on_incompatible (self , other )
772
+ raise raise_on_incompatible (self , other )
754
773
755
774
new_ordinals = super ()._add_delta (other )
756
775
return type (self )(new_ordinals , freq = self .freq )
@@ -802,28 +821,29 @@ def _check_timedeltalike_freq_compat(self, other):
802
821
# by which will be added to self.
803
822
return delta
804
823
805
- _raise_on_incompatible (self , other )
824
+ raise raise_on_incompatible (self , other )
806
825
807
826
808
827
PeriodArray ._add_comparison_ops ()
809
828
810
829
811
- def _raise_on_incompatible (left , right ):
830
+ def raise_on_incompatible (left , right ):
812
831
"""
813
832
Helper function to render a consistent error message when raising
814
833
IncompatibleFrequency.
815
834
816
835
Parameters
817
836
----------
818
837
left : PeriodArray
819
- right : DateOffset, Period, ndarray, or timedelta-like
838
+ right : None, DateOffset, Period, ndarray, or timedelta-like
820
839
821
- Raises
840
+ Returns
822
841
------
823
842
IncompatibleFrequency
843
+ Exception to be raised by the caller.
824
844
"""
825
845
# GH#24283 error message format depends on whether right is scalar
826
- if isinstance (right , np .ndarray ):
846
+ if isinstance (right , np .ndarray ) or right is None :
827
847
other_freq = None
828
848
elif isinstance (right , (ABCPeriodIndex , PeriodArray , Period , DateOffset )):
829
849
other_freq = right .freqstr
@@ -833,7 +853,7 @@ def _raise_on_incompatible(left, right):
833
853
msg = DIFFERENT_FREQ .format (
834
854
cls = type (left ).__name__ , own_freq = left .freqstr , other_freq = other_freq
835
855
)
836
- raise IncompatibleFrequency (msg )
856
+ return IncompatibleFrequency (msg )
837
857
838
858
839
859
# -------------------------------------------------------------------
0 commit comments