def test_nested_timeout(self): with timeout(DELAY, None): with timeout(DELAY*2, None): sleep(DELAY*3) raise AssertionError('should not get there') with timeout(DELAY, _SilentException()): with timeout(DELAY*2, _SilentException()): sleep(DELAY*3) raise AssertionError('should not get there')
def test_nested_timeout(self): with timeout(DELAY, None): with timeout(DELAY * 2, None): sleep(DELAY * 3) raise AssertionError('should not get there') with timeout(DELAY, _SilentException()): with timeout(DELAY * 2, _SilentException()): sleep(DELAY * 3) raise AssertionError('should not get there')
def _reader(self): """Wait forever for new chunks. Notify the user about the good ones through self._on_incoming_cb. If a response to a previously sent chunk is received, pop the corresponding response_cb from self.expected_responses and send the response there. """ error = Failure(ConnectionDone()) try: self.writer_job.link(self.reader_job) try: while self.state in ['CONNECTED', 'FLUSHING']: chunk = self.msrp.read_chunk(self.INCOMING_CHUNK_SIZE) if chunk.method is None: # response self._handle_incoming_response(chunk) elif chunk.method=='SEND': self._handle_incoming_SEND(chunk) elif chunk.method=='REPORT': self._on_incoming_cb(chunk) else: response = make_response(chunk, '501', 'Method unknown') self.outgoing.send((response, None)) except proc.LinkedExited: # writer has exited pass finally: self.writer_job.unlink(self.reader_job) self.writer_job.kill() self.logger.debug('reader: expecting responses only') delay = time() - self.last_expected_response if delay>=0 and self.expected_responses: # continue read the responses until the last timeout expires with api.timeout(delay, None): while self.expected_responses: chunk = self.msrp.read_chunk() if chunk.method is None: self._handle_incoming_response(chunk) else: self.logger.debug('dropping incoming %r' % chunk) # read whatever left in the queue with api.timeout(0, None): while self.msrp._queue: chunk = self.msrp.read_chunk() if chunk.method is None: self._handle_incoming_response(chunk) else: self.logger.debug('dropping incoming %r' % chunk) self.logger.debug('reader: done') except ConnectionClosedErrors, ex: self.logger.debug('reader: exiting because of %r' % ex) error=Failure(ex)
def test_ref(self): err = Error() err_ref = weakref.ref(err) with timeout(DELAY*2, err): sleep(DELAY) del err assert not err_ref(), repr(err_ref())
def test_ref(self): err = Error() err_ref = weakref.ref(err) with timeout(DELAY * 2, err): sleep(DELAY) del err assert not err_ref(), repr(err_ref())
def test_api(self): # Nothing happens if with-block finishes before the timeout expires with timeout(DELAY*2): sleep(DELAY) sleep(DELAY*2) # check if timer was actually cancelled # An exception will be raised if it's not try: with timeout(DELAY): sleep(DELAY*2) except TimeoutError: pass else: raise AssertionError('must raise TimeoutError') # You can customize the exception raised: try: with timeout(DELAY, IOError("Operation takes way too long")): sleep(DELAY*2) except IOError, ex: assert str(ex)=="Operation takes way too long", repr(ex)
def test_api(self): # Nothing happens if with-block finishes before the timeout expires with timeout(DELAY * 2): sleep(DELAY) sleep(DELAY * 2) # check if timer was actually cancelled # An exception will be raised if it's not try: with timeout(DELAY): sleep(DELAY * 2) except TimeoutError: pass else: raise AssertionError('must raise TimeoutError') # You can customize the exception raised: try: with timeout(DELAY, IOError("Operation takes way too long")): sleep(DELAY * 2) except IOError, ex: assert str(ex) == "Operation takes way too long", repr(ex)
def wait(self, timeout=None, *throw_args): """Wait until :meth:`send` or :meth:`send_exception` is called or *timeout* has expired. Return the argument of :meth:`send` or raise the argument of :meth:`send_exception`. If *timeout* has expired, ``None`` is returned. The arguments, when provided, specify how many seconds to wait and what to do when *timeout* has expired. They are treated the same way as :func:`~eventlet.api.timeout` treats them. """ if self.value is not _NOT_USED: if self._exc is None: return self.value else: api.getcurrent().throw(*self._exc) if timeout is not None: timer = api.timeout(timeout, *throw_args) timer.__enter__() if timeout==0: if timer.__exit__(None, None, None): return else: try: api.getcurrent().throw(*timer.throw_args) except: if not timer.__exit__(*sys.exc_info()): raise return EXC = True try: try: waiter = Waiter() self.link(waiter) try: return waiter.wait() finally: self.unlink(waiter) except: EXC = False if timeout is None or not timer.__exit__(*sys.exc_info()): raise finally: if timeout is not None and EXC: timer.__exit__(None, None, None)
def wait(self, timeout=None, *throw_args): """Wait until :meth:`send` or :meth:`send_exception` is called or *timeout* has expired. Return the argument of :meth:`send` or raise the argument of :meth:`send_exception`. If *timeout* has expired, ``None`` is returned. The arguments, when provided, specify how many seconds to wait and what to do when *timeout* has expired. They are treated the same way as :func:`~eventlet.api.timeout` treats them. """ if self.value is not _NOT_USED: if self._exc is None: return self.value else: api.getcurrent().throw(*self._exc) if timeout is not None: timer = api.timeout(timeout, *throw_args) timer.__enter__() if timeout == 0: if timer.__exit__(None, None, None): return else: try: api.getcurrent().throw(*timer.throw_args) except: if not timer.__exit__(*sys.exc_info()): raise return EXC = True try: try: waiter = Waiter() self.link(waiter) try: return waiter.wait() finally: self.unlink(waiter) except: EXC = False if timeout is None or not timer.__exit__(*sys.exc_info()): raise finally: if timeout is not None and EXC: timer.__exit__(None, None, None)
class Test(unittest.TestCase): def test_api(self): # Nothing happens if with-block finishes before the timeout expires with timeout(DELAY * 2): sleep(DELAY) sleep(DELAY * 2) # check if timer was actually cancelled # An exception will be raised if it's not try: with timeout(DELAY): sleep(DELAY * 2) except TimeoutError: pass else: raise AssertionError('must raise TimeoutError') # You can customize the exception raised: try: with timeout(DELAY, IOError("Operation takes way too long")): sleep(DELAY * 2) except IOError, ex: assert str(ex) == "Operation takes way too long", repr(ex) # Providing classes instead of values should be possible too: try: with timeout(DELAY, ValueError): sleep(DELAY * 2) except ValueError: pass # basically, anything that greenlet.throw accepts work: try: 1 / 0 except: try: with timeout(DELAY, *sys.exc_info()): sleep(DELAY * 2) raise AssertionError('should not get there') raise AssertionError('should not get there') except ZeroDivisionError: pass else: raise AssertionError('should not get there') # It's possible to cancel the timer inside the block: with timeout(DELAY) as timer: timer.cancel() sleep(DELAY * 2) # To silent the exception, pass None as second parameter. The with-block # will be interrupted with _SilentException, but it won't be propagated # outside. XDELAY = 0.1 start = time.time() with timeout(XDELAY, None): sleep(XDELAY * 2) delta = (time.time() - start) assert delta < XDELAY * 2, delta # passing None as seconds disables the timer with timeout(None): sleep(DELAY) sleep(DELAY)
def close(self): """Stop listening. Wait for the spawned greenlets to finish""" self.stopListening() with timeout(self.CLOSE_TIMEOUT, None): self.factory.waitall()
def timeout(cls, *throw_args): if not throw_args: throw_args = (cls, ) return timeout(cls.seconds, *throw_args)
def wait(self): with api.timeout(self.timeout): return event.wait(self)