A Reminder defines an instant in time when something should happen.
>>> from chandler.reminder import *
>>> rem = Reminder()
>>> rem.type
'triage'
What exactly happens when a reminder fires will depend on the reminder’s type. The simplest example is to change an item’s triage status.
trigger for a Reminder is determined either relative to an event, by setting a delta or with a fixed_trigger. By default, both are None.
>>> rem.delta is None
True
>>> rem.fixed_trigger is None
True
>>> rem.trigger is None
True
To associate a Reminder with an item, it should be added to the item’s ReminderList AddOn. Note that ReminderList isn’t an Extension, so there’s no need to call add().
>>> from chandler import time_services
>>> from chandler.core import Item
>>> from datetime import datetime, timedelta
>>> april_fools = datetime(2006, 4, 1, 12, tzinfo=time_services.TimeZone.eastern)
>>> time_services.setNow(april_fools)
>>> item = Item()
>>> rem.item = item
>>> ReminderList(item).reminders.append(rem)
Setting delta for an item that isn’t an event leaves trigger as None:
>>> rem.delta = timedelta(hours=1)
>>> rem.trigger is None
True
Similarly, if start is None, trigger will be, too.
>>> from chandler.event import Event
>>> event = Event(item).add()
>>> event.start is None
True
>>> rem.trigger is None
True
But if start is set, trigger will be, too.
>>> event.tzinfo = time_services.TimeZone.eastern
>>> event.base_start = april_fools + timedelta(hours=3)
>>> rem.trigger
datetime.datetime(2006, 4, 1, 16, 0, tzinfo=<ICUtzinfo: US/Eastern>)
If a Reminder has both a delta and a fixed_start, the fixed_start takes precedence.
>>> rem.fixed_trigger = april_fools + timedelta(minutes=5)
>>> rem.trigger
datetime.datetime(2006, 4, 1, 12, 5, tzinfo=<ICUtzinfo: US/Eastern>)
Rather than creating a Reminder and setting its item, you can use ReminderList.add_reminder().
>>> rem2 = ReminderList(item).add_reminder()
>>> rem2.item == item
True
>>> ReminderList(item).reminders == [rem, rem2]
True
You can pass in cell values for the new reminder, too:
>>> rem3 = ReminderList(item).add_reminder(delta=timedelta(days=2))
>>> rem3.delta
datetime.timedelta(2)
You can also remove all reminders:
>>> len(ReminderList(item).reminders)
3
>>> ReminderList(item).remove_all_reminders()
>>> len(ReminderList(item).reminders)
0
When a reminder is added to an item, its triage status and triage position depend on the reminder.
>>> from chandler.triage import *
>>> item = Item()
>>> triage = Triage(item)
>>> triage.calculated == NOW
True
>>> triage_position = TriagePosition(item)
>>> triage_position.position == item.created
True
>>> rem = ReminderList(item).add_reminder(fixed_trigger=april_fools + timedelta(days=2))
>>> triage.calculated == LATER
True
>>> triage_position.position == time_services.timestamp(rem.trigger)
True
>>> time_services.setNow(april_fools + timedelta(days=3))
>>> triage.calculated == NOW
True
An Event with an associated Reminder may have its triage position depend on either.
>>> rem.fixed_trigger = None
>>> rem.delta = timedelta(hours=-1)
>>> event = Event(item).add()
>>> event.base_start = april_fools
>>> triage_position.position == time_services.timestamp(event.start)
True
If both the event and the reminder are in the past, position will be the latter of the two.
>>> rem.delta = timedelta(hours=1)
>>> triage_position.position == time_services.timestamp(event.start)
False
>>> triage_position.position == time_services.timestamp(rem.trigger)
True
If one is in the future, the other in the past, position will depend on calculated triage.
>>> event.base_start = april_fools + timedelta(days=3)
>>> triage.calculated
100.0
>>> triage_position.position == time_services.timestamp(event.start)
True
>>> triage.manual = LATER
>>> triage_position.position == time_services.timestamp(rem.trigger)
True
XXX Reminder should be a scheduled, test/document reminder fire
XXX should all reminders get the triage behavior?
XXX snooze_until, cleared
XXX Hook for adding different types of reminders?
XXX reversible in time explanation