Package osh :: Package command :: Module timer
[frames] | no frames]

Source Code for Module osh.command.timer

  1  # osh 
  2  # Copyright (C) 2005 Jack Orenstein <jao@geophile.com> 
  3  # 
  4  # This program is free software; you can redistribute it and/or modify 
  5  # it under the terms of the GNU General Public License as published by 
  6  # the Free Software Foundation; either version 2 of the License, or 
  7  # (at your option) any later version. 
  8  # 
  9  # This program is distributed in the hope that it will be useful, 
 10  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 11  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 12  # GNU General Public License for more details. 
 13  # 
 14  # You should have received a copy of the GNU General Public License 
 15  # along with this program; if not, write to the Free Software 
 16  # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 17   
 18  """C{timer INTERVAL} 
 19       
 20  Generates a sequence of timestamps, separated in time by the specified C{INTERVAL} 
 21  (approximately). The C{INTERVAL} format is:: 
 22       
 23      HH:MM:SS 
 24   
 25  where C{HH} is hours, C{MM} is minutes, C{SS} is seconds.  C{HH:} and 
 26  C{HH:MM:} may be omitted. 
 27   
 28  B{Examples}:: 
 29   
 30      INTERVAL        meaning 
 31      ----------------------------- 
 32      5               5 seconds 
 33      1:30            1 minute, 30 seconds 
 34      1:00:00         1 hour 
 35   
 36  The output timestamp is a tuple, matching what is returned by 
 37  C{time.gmtime()} and C{time.localtime()}: (year, month, day of month, 
 38  hour, minute, second, day of week, day of year, dst). 
 39   
 40  Notes: 
 41      - month is 1-based (January = 1, February = 2, ...) 
 42      - day of month is 1-based. 
 43      - second can go as high as 61 due to leap-seconds. 
 44      - day of week is 0-based, Monday = 0. 
 45      - day of year is 1-based. 
 46      - dst is 1 if Daylight Savings Time is in effect, 0 otherwise. 
 47  """ 
 48   
 49  import threading 
 50  import time 
 51   
 52  import osh.core 
 53   
 54  # CLI 
55 -def _timer():
56 return _Timer()
57 58 # API
59 -def timer(interval):
60 """Generates a sequence of timestamps, separated in time by the 61 specified C{interval} (approximately). The C{interval} format is 62 C{HH:MM:SS}, where C{HH} is hours, C{MM} is minutes, C{SS} is 63 seconds. C{HH:} and C{HH:MM:} may be omitted. 64 """ 65 return _Timer().process_args(interval)
66
67 -class _Timer(osh.core.Generator):
68 69 _metronome = None 70 _lock = None 71 _now = None 72 _done = False 73 74 # object interface 75
76 - def __init__(self):
77 osh.core.Generator.__init__(self, '' ,(1, 1))
78 79 80 # BaseOp interface 81
82 - def doc(self):
83 return __doc__
84
85 - def setup(self):
86 args = self.args() 87 if args.has_next(): 88 interval = self.parse_interval(args.next_string()) 89 if args.has_next(): 90 self.usage() 91 self._metronome = _Metronome(interval, self) 92 self._lock = threading.Condition() 93 else: 94 self.usage()
95 96 97 # Generator interface 98
99 - def execute(self):
100 # Timer events are generated by the metronome class, which is a separate 101 # thread. This keeps the intervals close to what is specified. If the 102 # timer is run in the current thread, then the interval would control 103 # the time between completion of downstream computing (invoked by self.send) 104 # and the next timer event. 105 self._metronome.start() 106 while not self._done: 107 self._lock.acquire() 108 while self._now is None: 109 # If the timeout is omitted from the wait call, then ctrl-c 110 # cannot interrupt. The threading module implements wait 111 # differently if a timeout is specified, waking up periodically. 112 self._lock.wait(1.0) 113 now = self._now 114 self._now = None 115 self._lock.release() 116 self.send(now)
117 118 # For use by this module 119
120 - def parse_interval(self, interval):
121 colon1 = interval.find(':') 122 colon2 = -1 123 if colon1 > 0: 124 colon2 = interval.find(':', colon1 + 1) 125 # Normalize 126 if colon1 < 0: 127 # No colons 128 interval = '0:0:' + interval 129 elif colon2 < 0: 130 # One colon 131 interval = '0:' + interval 132 colon1 = interval.find(':') 133 colon2 = interval.find(':', colon1 + 1) 134 HH = int(interval[:colon1]) 135 MM = int(interval[colon1 + 1 : colon2]) 136 SS = int(interval[colon2 + 1 :]) 137 return HH * 3600 + MM * 60 + SS
138
139 - def register_tick(self):
140 self._lock.acquire() 141 self._now = time.localtime() 142 self._lock.notifyAll() 143 self._lock.release()
144
145 -class _Metronome(threading.Thread):
146 147 _interval = None 148 _timer = None 149
150 - def __init__(self, interval, timer):
151 threading.Thread.__init__(self) 152 self._interval = interval 153 self._timer = timer 154 self.setDaemon(True)
155
156 - def run(self):
157 while True: 158 self._timer.register_tick() 159 time.sleep(self._interval)
160