Skip to content

Commit 537ab5a

Browse files
authored
INT: take DateOffset out of the inheritance tree for BaseOffset subclasses (#34147)
1 parent 23d141e commit 537ab5a

File tree

3 files changed

+26
-15
lines changed

3 files changed

+26
-15
lines changed

pandas/_libs/tslibs/offsets.pyx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,11 @@ class _BaseOffset:
733733
)
734734
return self.is_anchored()
735735

736+
def is_anchored(self) -> bool:
737+
# TODO: Does this make sense for the general case? It would help
738+
# if there were a canonical docstring for what is_anchored means.
739+
return self.n == 1
740+
736741

737742
class BaseOffset(_BaseOffset):
738743
# Here we add __rfoo__ methods that don't play well with cdef classes

pandas/tseries/frequencies.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ def _get_offset(name: str) -> DateOffset:
219219
klass = prefix_mapping[split[0]]
220220
# handles case where there's no suffix (and will TypeError if too
221221
# many '-')
222-
offset = klass._from_name(*split[1:])
222+
offset = klass._from_name(*split[1:]) # type: ignore
223223
except (ValueError, TypeError, KeyError) as err:
224224
# bad prefix or suffix
225225
raise ValueError(libfreqs.INVALID_FREQ_ERR_MSG.format(name)) from err

pandas/tseries/offsets.py

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,22 @@
7575
# DateOffset
7676

7777

78-
class DateOffset(BaseOffset):
78+
class OffsetMeta(type):
79+
"""
80+
Metaclass that allows us to pretend that all BaseOffset subclasses
81+
inherit from DateOffset (which is needed for backward-compatibility).
82+
"""
83+
84+
@classmethod
85+
def __instancecheck__(cls, obj) -> bool:
86+
return isinstance(obj, BaseOffset)
87+
88+
@classmethod
89+
def __subclasscheck__(cls, obj) -> bool:
90+
return issubclass(obj, BaseOffset)
91+
92+
93+
class DateOffset(BaseOffset, metaclass=OffsetMeta):
7994
"""
8095
Standard kind of date increment used for a date range.
8196
@@ -274,25 +289,16 @@ def apply_index(self, i):
274289
"applied vectorized"
275290
)
276291

277-
def is_anchored(self) -> bool:
278-
# TODO: Does this make sense for the general case? It would help
279-
# if there were a canonical docstring for what is_anchored means.
280-
return self.n == 1
281-
282292
def is_on_offset(self, dt):
283293
if self.normalize and not is_normalized(dt):
284294
return False
285295
# TODO, see #1395
286296
return True
287297

288298

289-
class SingleConstructorOffset(DateOffset):
290-
# All DateOffset subclasses (other than Tick) subclass SingleConstructorOffset
291-
__init__ = BaseOffset.__init__
292-
_attributes = BaseOffset._attributes
293-
apply_index = BaseOffset.apply_index
294-
is_on_offset = BaseOffset.is_on_offset
295-
_adjust_dst = True
299+
class SingleConstructorOffset(BaseOffset):
300+
_params = cache_readonly(BaseOffset._params.fget)
301+
freqstr = cache_readonly(BaseOffset.freqstr.fget)
296302

297303
@classmethod
298304
def _from_name(cls, suffix=None):
@@ -2305,7 +2311,7 @@ class Nano(Tick):
23052311
CDay = CustomBusinessDay
23062312

23072313
prefix_mapping = {
2308-
offset._prefix: offset
2314+
offset._prefix: offset # type: ignore
23092315
for offset in [
23102316
YearBegin, # 'AS'
23112317
YearEnd, # 'A'

0 commit comments

Comments
 (0)