def testIsGeneratorOrComposed(self): def f(): yield self.assertTrue(is_generator(f())) self.assertTrue(is_generator(compose(f()))) self.assertFalse(is_generator(lambda: None)) self.assertFalse(is_generator(None))
def _callonce(self, observers, args, kwargs, seen): for observer in (o for o in observers if o not in seen): seen.add(observer) try: method = getattr(observer, self._message) except AttributeError: pass else: try: try: self.called.add(observer) _ = methodResult = method(*args, **kwargs) except (StopIteration, GeneratorExit): c, v, t = exc_info() handleNonGeneratorGeneratorExceptions(method, c, v, t.tb_next) if is_generator(methodResult): _ = yield methodResult except: c, v, t = exc_info(); raise c, v, t.tb_next assert _ is None, "%s returned '%s'" % (methodOrMethodPartialStr(method), _) if isinstance(observer, Observable): try: _ = yield self._callonce(observer._observers, args, kwargs, seen) except: c, v, t = exc_info(); raise c, v, t.tb_next assert _ is None, "OnceMessage of %s returned '%s', but must always be None" % (self._observable, _)
def _callonce(self, observers, args, kwargs, done): for observer in (o for o in observers if o not in done): done.add(observer) try: method = getattr(observer, self._message) except AttributeError: pass else: try: try: _ = methodResult = method(*args, **kwargs) except (StopIteration, GeneratorExit): c, v, t = exc_info() handleNonGeneratorGeneratorExceptions( method, c, v, t.tb_next) if is_generator(methodResult): _ = yield methodResult except: c, v, t = exc_info() raise c, v, t.tb_next assert _ is None, "%s returned '%s'" % ( methodOrMethodPartialStr(method), _) if isinstance(observer, Observable): try: _ = yield self._callonce(observer._observers, args, kwargs, done) except: c, v, t = exc_info() raise c, v, t.tb_next assert _ is None, "OnceMessage of %s returned '%s', but must always be None" % ( self._observable, _)
def _asProcess(g): if not is_generator(g): raise TypeError("asProcess() expects a generator, got %s" % repr(g)) reactor = Reactor() # Between creating and reactor.loop() there should be no statements that can raise exceptions (otherwise (epoll) fd-leaking occurs). wrapper(g, reactor) try: reactor.loop() except StopIteration, e: if e.args: return e.args[0]
def verifyMethodResult(self, method, result): assert is_generator(result), "%s should have resulted in a generator." % methodOrMethodPartialStr(method)
def verifyMethodResult(self, method, result): assert is_generator( result ), "%s should have resulted in a generator." % methodOrMethodPartialStr( method)
def _compose(initial, stepping): """ The method compose() allows program (de)composition with generators. It enables calls like: retvat = yield otherGenerator(args) The otherGenerator may return values by: raise StopIteration(retvat, remaining data) Remaining data might be present if the otherGenerator consumes less than it get gets. It must make this remaining data available to the calling generator by yielding it as shown. Most notably, compose enables catching exceptions: try: retvat = yield otherGenerator(args) except Exception: pass This will work as expected: it catches an exception thrown by otherGenerator. """ generators = [initial] __callstack__ = generators # make these visible to 'local()' messages = [None] exception = None while generators: generator = generators[-1] try: if exception: if exception[0] == GeneratorExit: generator.close() raise exception response = generator.throw(*exception) exception = None else: message = messages.pop(0) response = generator.send(message) if is_generator(response): generators.append(response) frame = response.gi_frame if cpython: assert frame, 'Generator is exhausted.' if cpython: assert frame.f_lineno == frame.f_code.co_firstlineno, 'Generator already used.' try: if stepping: _ = yield Yield except BaseException: exType, exValue, exTraceback = exc_info() exception = (exType, exValue, exTraceback.tb_next) continue if stepping: assert _ is None, 'Cannot accept data when stepping. First send None.' messages.insert(0, None) elif (response is not None) or not messages: try: message = yield response assert message is None or response is None, 'Cannot accept data. First send None.' messages.insert(0, message) except BaseException: exType, exValue, exTraceback = exc_info() exception = (exType, exValue, exTraceback.tb_next) except StopIteration, returnValue: exception = None generators.pop() retvals = returnValue.args if retvals: if retvals == ('', ): #jython retvals = (None, ) messages[0:0] = retvals else: generators and messages.insert(0, None) except BaseException: generators.pop() exType, exValue, exTraceback = exc_info() exception = (exType, exValue, exTraceback.tb_next)
def compose(initial, stepping=False): if not is_generator(initial): raise TypeError("compose() expects generator") return _compose(initial, stepping)
def _compose(initial, stepping): """ The method compose() allows program (de)composition with generators. It enables calls like: retvat = yield otherGenerator(args) The otherGenerator may return values by: raise StopIteration(retvat, remaining data) Remaining data might be present if the otherGenerator consumes less than it get gets. It must make this remaining data available to the calling generator by yielding it as shown. Most notably, compose enables catching exceptions: try: retvat = yield otherGenerator(args) except Exception: pass This will work as expected: it catches an exception thrown by otherGenerator. """ generators = [initial] __callstack__ = generators # make these visible to 'local()' messages = [None] exception = None while generators: generator = generators[-1] try: if exception: if exception[0] == GeneratorExit: generator.close() raise exception response = generator.throw(*exception) exception = None else: message = messages.pop(0) response = generator.send(message) if is_generator(response): generators.append(response) frame = response.gi_frame if cpython: assert frame, 'Generator is exhausted.' if cpython: assert frame.f_lineno == frame.f_code.co_firstlineno, 'Generator already used.' try: if stepping: _ = yield Yield except BaseException: exType, exValue, exTraceback = exc_info() exception = (exType, exValue, exTraceback.tb_next) continue if stepping: assert _ is None, 'Cannot accept data when stepping. First send None.' messages.insert(0, None) elif (response is not None) or not messages: try: message = yield response assert message is None or response is None, 'Cannot accept data. First send None.' messages.insert(0, message) except BaseException: exType, exValue, exTraceback = exc_info() exception = (exType, exValue, exTraceback.tb_next) except StopIteration, returnValue: exception = None generators.pop() retvals = returnValue.args if retvals: if retvals == ('',): #jython retvals = (None,) messages[0:0] = retvals else: generators and messages.insert(0, None) except BaseException: generators.pop() exType, exValue, exTraceback = exc_info() exception = (exType, exValue, exTraceback.tb_next)