def play(self): '''round-robin''' self.open_start_urls() loops_without_progress = 0 while True: import time start = time.time() if len(self.bots) == 0: return # bots got stuck if there's 2 wait pages in a row if loops_without_progress > 10: raise AssertionError('Bots got stuck') results = Chan(buflen=len(self.bots)) threads = [] for bot in self.bots.values(): if bot.on_wait_page(): pass else: thread = SubmitThread(bot, results) threads.append(thread) thread.start() for thread in threads: bot, status = results.get() if isinstance(status, Exception): raise status elif status == 'finished': del self.bots[bot.participant.id] else: bot.submit(status) results.close() if not threads: loops_without_progress += 1
def test_buf_simple(self): S = 5 c = Chan(S) for i in range(S): c.put(i) c.close() results = list(c) self.assertEqual(results, list(range(S)))
class Subscription(object): def __init__(self, fetcher): self.fetcher = fetcher self.updates_chan = Chan() self.quit = Chan() self.thread = threading.Thread( name='Subscription', target=self._run) #self.thread.daemon = True self.thread.start() def _run(self): next_time = time.time() pending = [] # First is most recent. Should be a deque err = None while True: start_fetch = timeout_after(max(0.0, next_time - time.time())) # Does or doesn't wait on updates_chan depending on if we have # items ready. if pending: outchans = [(self.updates_chan, pending[0])] else: outchans = [] ch, value = chanselect([self.quit, start_fetch], outchans) if ch == self.quit: errc = value self.updates_chan.close() errc.put(err) return elif ch == start_fetch: try: err = None item_list, next_time = self.fetcher.fetch() except Exception as ex: err = ex next_time = time.time() + 10.0 continue pending.extend(item_list) else: # self.updates_chan pending.pop(0) # Pops the sent item def updates(self): return self.updates_chan def close(self): errc = Chan() self.quit.put(errc) result = errc.get() self.thread.join(0.2) assert not self.thread.is_alive() return result
class Subscription(object): def __init__(self, fetcher): self.fetcher = fetcher self.updates_chan = Chan() self.quit = Chan() self.thread = threading.Thread(name='Subscription', target=self._run) #self.thread.daemon = True self.thread.start() def _run(self): next_time = time.time() pending = [] # First is most recent. Should be a deque err = None while True: start_fetch = timeout_after(max(0.0, next_time - time.time())) # Does or doesn't wait on updates_chan depending on if we have # items ready. if pending: outchans = [(self.updates_chan, pending[0])] else: outchans = [] ch, value = chanselect([self.quit, start_fetch], outchans) if ch == self.quit: errc = value self.updates_chan.close() errc.put(err) return elif ch == start_fetch: try: err = None item_list, next_time = self.fetcher.fetch() except Exception as ex: err = ex next_time = time.time() + 10.0 continue pending.extend(item_list) else: # self.updates_chan pending.pop(0) # Pops the sent item def updates(self): return self.updates_chan def close(self): errc = Chan() self.quit.put(errc) result = errc.get() self.thread.join(0.2) assert not self.thread.is_alive() return result
class Merged(object): def __init__(self, subscriptions): self.subscriptions = subscriptions self.updates_chan = Chan() self.quit = Chan() self.thread = threading.Thread( name="Merged", target=self._run) self.thread.start() def _close_subs_collect_errs(self): return [sub.close() for sub in self.subscriptions] def _run(self): subchans = [sub.updates() for sub in self.subscriptions] while True: c, value = chanselect(subchans + [self.quit], []) if c == self.quit: value.put(self._close_subs_collect_errs()) self.updates_chan.close() return else: item = value c, _ = chanselect([self.quit], [(self.updates_chan, item)]) if c == self.quit: value.put(self._close_subs_collect_errs()) self.updates_chan.close() return else: pass # Send successful def updates(self): return self.updates_chan def close(self): errc = Chan() self.quit.put(errc) result = errc.get() self.thread.join(timeout=0.2) assert not self.thread.is_alive() return result
class Merged(object): def __init__(self, subscriptions): self.subscriptions = subscriptions self.updates_chan = Chan() self.quit = Chan() self.thread = threading.Thread(name="Merged", target=self._run) self.thread.start() def _close_subs_collect_errs(self): return [sub.close() for sub in self.subscriptions] def _run(self): subchans = [sub.updates() for sub in self.subscriptions] while True: c, value = chanselect(subchans + [self.quit], []) if c == self.quit: value.put(self._close_subs_collect_errs()) self.updates_chan.close() return else: item = value c, _ = chanselect([self.quit], [(self.updates_chan, item)]) if c == self.quit: value.put(self._close_subs_collect_errs()) self.updates_chan.close() return else: pass # Send successful def updates(self): return self.updates_chan def close(self): errc = Chan() self.quit.put(errc) result = errc.get() self.thread.join(timeout=0.2) assert not self.thread.is_alive() return result
class SolidTimer(object): def __init__(self, color, blink=False, period=0.5): self.blink = blink self.period = period self.color = color.split('-')[0] self.chan = Chan() self._stop = threading.Event() self._thread = threading.Thread(name='LightTimer', target=self.run) self._thread.daemon = True self._thread.start() def run(self): STATE = [] if self.color == 'red': STATE = [lights.RED1, lights.RED2] elif self.color == 'yellow': STATE = [lights.YLW1, lights.YLW2] elif self.color == 'green': STATE = [lights.GRN1, lights.GRN2] on = True while not self._stop.is_set(): if on: if self.blink: self.chan.put([STATE[0]]) on = False time.sleep(self.period) else: self.chan.put(STATE) time.sleep(5) else: self.chan.put([STATE[1]]) on = True time.sleep(self.period) self.chan.close() def stop(self): self._stop.set()
class LightTimer(object): def __init__(self, period=DEFAULT_PERIOD, yellow=DEFAULT_YELLOW): self.period = period self.yellow = yellow self.trip = False self._stop = threading.Event() self.chan = Chan() self._thread = threading.Thread(name='LightTimer', target=self.run) self._thread.daemon = True self._thread.start() def run(self): STATES = [ [lights.RED1, lights.GRN2], [lights.RED1, lights.YLW2], [lights.GRN1, lights.RED2], [lights.YLW1, lights.RED2], ] state_i = len(STATES) - 1 t_last = 0 while not self._stop.is_set(): t_yellow = min(0.25 * self.period, DEFAULT_YELLOW) t_green = self.period - t_yellow dur = t_green if state_i % 2 == 0 else t_yellow now = time.time() if now > t_last + dur or self.trip: t_last = now state_i = (state_i + 1) % len(STATES) self.chan.put(STATES[state_i]) self.trip = False time.sleep(0.1) self.chan.close() def stop(self): self._stop.set()