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

Source Code for Module osh.command.timer

  1  # osh 
  2  # Copyright (C) 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 [-t] 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 time in seconds since 1/1/1970. If C{-t} is specified, 
 37  then the output timestamp is a tuple, matching what is returned by 
 38  C{time.gmtime()} and C{time.localtime()}: (year, month, day of month, 
 39  hour, minute, second, day of week, day of year, dst). 
 40   
 41  Notes: 
 42      - month is 1-based (January = 1, February = 2, ...) 
 43      - day of month is 1-based. 
 44      - second can go as high as 61 due to leap-seconds. 
 45      - day of week is 0-based, Monday = 0. 
 46      - day of year is 1-based. 
 47      - dst is 1 if Daylight Savings Time is in effect, 0 otherwise. 
 48  """ 
 49   
 50  import threading 
 51  import time 
 52   
 53  import osh.core 
 54   
 55  Option = osh.args.Option 
 56   
 57  # CLI 
58 -def _timer():
59 return _Timer()
60 61 # API
62 -def timer(interval, tupleoutput = False):
63 """Generates a sequence of timestamps, separated in time by the 64 specified C{interval} (approximately). The C{interval} format is 65 C{HH:MM:SS}, where C{HH} is hours, C{MM} is minutes, C{SS} is 66 seconds. C{HH:} and C{HH:MM:} may be omitted. Output items are 67 numbers representing seconds since 1/1/1970, if tupleoutput is False, 68 a tuple of (year, month, day of month, 69 hour, minute, second, day of week, day of year, dst) otherwise. 70 """ 71 args = [] 72 if tupleoutput: 73 args.append(Option('-t')) 74 return _Timer().process_args(interval)
75
76 -class _Timer(osh.core.Generator):
77 78 _tupleoutput = None 79 _metronome = None 80 _lock = None 81 _now = None 82 _done = False 83 84 # object interface 85
86 - def __init__(self):
87 osh.core.Generator.__init__(self, 't' ,(1, 1))
88 89 90 # BaseOp interface 91
92 - def doc(self):
93 return __doc__
94
95 - def setup(self):
96 args = self.args() 97 self._tupleoutput = args.flag('-t') 98 if args.has_next(): 99 interval = self.parse_interval(args.next_string()) 100 if args.has_next(): 101 self.usage() 102 self._metronome = _Metronome(interval, self) 103 self._lock = threading.Condition() 104 else: 105 self.usage()
106 107 108 # Generator interface 109
110 - def execute(self):
111 # Timer events are generated by the metronome class, which is a separate 112 # thread. This keeps the intervals close to what is specified. If the 113 # timer is run in the current thread, then the interval would control 114 # the time between completion of downstream computing (invoked by self.send) 115 # and the next timer event. 116 self._metronome.start() 117 while not self._done: 118 self._lock.acquire() 119 while self._now is None: 120 # If the timeout is omitted from the wait call, then ctrl-c 121 # cannot interrupt. The threading module implements wait 122 # differently if a timeout is specified, waking up periodically. 123 self._lock.wait(1.0) 124 now = self._now 125 if (not self._tupleoutput): 126 now = time.mktime(now) 127 self._now = None 128 self._lock.release() 129 self.send(now)
130 131 # For use by this module 132
133 - def parse_interval(self, interval):
134 colon1 = interval.find(':') 135 colon2 = -1 136 if colon1 > 0: 137 colon2 = interval.find(':', colon1 + 1) 138 # Normalize 139 if colon1 < 0: 140 # No colons 141 interval = '0:0:' + interval 142 elif colon2 < 0: 143 # One colon 144 interval = '0:' + interval 145 colon1 = interval.find(':') 146 colon2 = interval.find(':', colon1 + 1) 147 HH = int(interval[:colon1]) 148 MM = int(interval[colon1 + 1 : colon2]) 149 SS = int(interval[colon2 + 1 :]) 150 return HH * 3600 + MM * 60 + SS
151
152 - def register_tick(self):
153 self._lock.acquire() 154 self._now = time.localtime() 155 self._lock.notifyAll() 156 self._lock.release()
157
158 -class _Metronome(threading.Thread):
159 160 _interval = None 161 _timer = None 162
163 - def __init__(self, interval, timer):
164 threading.Thread.__init__(self) 165 self._interval = interval 166 self._timer = timer 167 self.setDaemon(True)
168
169 - def run(self):
170 while True: 171 self._timer.register_tick() 172 time.sleep(self._interval)
173