Recurring dates module [was: Project dream]

Robert Brewer fumanchu at amor.org
Sun Jan 4 07:56:39 CET 2004


I offered:
> > > first attempt (*very* alpha); feedback/additions appreciated.
> > > 
> > > http://www.aminus.org/rbre/python/recur.py
> > > http://www.aminus.org/rbre/python/test_recur.py
> > 
> > I updated this today, including time functions in addition 
> > to the date functions and generally "filling in the corners".
> > I also included 
> > an interval calculation function for e.g., threading.Timer.

and eltronic replied:
> rats, datetime IIR is only py2.3 unless it already works in py2*
> or some kind soul has backported it ala sets and some of itertools.

Yes, sorry about that. Now that I'm fully 2.3 I didn't feel the need
(yet) to generalize the date types. I did try, however, to keep all of
the calls "method-centric"--that is, I don't ever check type/subclass
explicitly. Perhaps for older versions someone might write a wrapper for
mxDateTime which makes it behave like the new datetime module. I had
that mostly done at one time, then threw it away when datetime made it
into the Library.

> I envision a timer prog that wakes up every 45 or so seconds
> parses an event list and acts on those of the current minute.
> but something like recur would be needed for up/down counters.
> I guess all counters can derive their data from one main counter.
> the thought of starting each alarm in a thread maybe minutes 
> days or months in advance is not going to survive reboots well.

I considered that; it's one of the reasons that I decided to use
iteration/generators as the primary mode of operation, and kept the
declaration of recurrence in a vocabulary which is "rigorously
indeterminate". :) That is, the description of recurrence is ambiguous
until you provide a start date/end date to realize it. If your chain of
iteration breaks down, you should be able to pick it up again at any
point without modifying your description. It's also why the base
functionality of recur is available without use the Recurrence
class--that's just syntactic sugar over the bare generator functions.

I am now using recur with threading.Timer, by the way. You don't set up
all your Timers at once (one for each 45 seconds!?)--you code each Timer
so that, when it has completed its task, it starts the next Timer.
That's where recur.interval() comes in. Example:

import threading
import recur

class Worker(object):
    """Perform work on a schedule.
    
    You must subclass work(), which is called at each interval.
    """
    
    def __init__(self, recurrence=None):
        self.recurrence = recurrence
        if self.recurrence:
            # Throw away the first occurrence value,
            # which is almost always .now()
            self.recurrence.next()
    
    def motivate(self):
        """Start a new timed thread for work."""
        if self.recurrence:
            iv = recur.interval(self.recurrence)
            threading.Timer(iv, self._run).start()
    
    def _run(self):
        """Prepare for work."""
        self.work()
        self.motivate()
    
    def work(self):
        raise NotImplementedError



...which survives reboots just fine; just call motivate() on app
startup. Alternately, you could use a single main thread to calculate
the intervals and spawn new threads. That's why I specifically did not
embed threading implementations into recur--it's better to leave it
simpler and just let it play well with other existing modules which have
been written far better than mine.


Robert Brewer
MIS
Amor Ministries
fumanchu at amor.org




More information about the Python-list mailing list