I am trying to extend arrow
and fail to understand how I can replicate the functionality of the base classes. This is probably due to a lack of clear understanding on how to extend classes in modules (emphasized by my arrow
case - this is to say that the question is probably more general than limited to arrow
only).
arrow
basic usage:
>>> import arrow
>>> arrow.now()
<Arrow [2016-11-19T15:13:23.897484+01:00]>
>>> arrow.get("2016-11-20")
<Arrow [2016-11-20T00:00:00+00:00]>
I would like to add a when
method which will return 'today', 'tomorrow' or 'later'. I first tried this:
import arrow
class MyArrow(arrow.Arrow):
def __init__(self, *args):
arrow.Arrow.__init__(self, *args)
def when(self):
now = arrow.now()
end_today = now.ceil('day')
end_tomorrow = now.replace(days=+1).ceil('day')
start_tomorrow = now.replace(days=+1).floor('day')
if self < end_today:
return 'today'
elif self < end_tomorrow:
return 'tomorrow'
else:
return 'later'
if __name__ == "__main__":
tom = MyArrow.now().replace(days=+1)
print(tom.when())
someday = MyArrow.get("2016-11-19")
The result is
tomorrow
Traceback (most recent call last):
File "D:/Dropbox/dev/domotique/testing/myarrow.py", line 23, in <module>
someday = MyArrow.get("2016-11-19")
AttributeError: type object 'MyArrow' has no attribute 'get'
So the first part worked, but get()
failed. I had a look at the sources and get
is in ArrowFactory
. If I extend ArrowFactory
instead of Arrow
I will be able to use get
but not now()
anymore.
This is the point I am at loss: the "basic usage" above shows that I can call arrow.whatever_is_available
no matter if it is defined in the class Arrow
or ArrowFactory
.
How does this work?
How can I add my when
method to keep the rest of arrow
as it is (and all its methods)?
- Extensible for your own Arrow-derived types
is one of the highlighted features in Arrow's documentation, which actually demonstrates exactly how to create and use a custom Arrow
subclass:
Factories
Use factories to harness Arrow’s module API for a custom Arrow-derived type. First, derive your type:
>>> class CustomArrow(arrow.Arrow): ... ... def days_till_xmas(self): ... ... xmas = arrow.Arrow(self.year, 12, 25) ... ... if self > xmas: ... xmas = xmas.replace(years=1) ... ... return (xmas - self).days
Then get and use a factory for it:
>>> factory = arrow.Factory(CustomArrow) >>> custom = factory.utcnow() >>> custom >>> <CustomArrow [2013-05-27T23:35:35.533160+00:00]> >>> custom.days_till_xmas() >>> 211
You can then call the .get
, .now
and .utcnow
methods on the factory
and get your custom subclass, with its .when
method.
This is specific to dealing with Arrow and its module-level API; with simpler modules, you could just subclass their classes directly.