def io_loop(event_loop, request): """Same as pytest-tornado.io_loop, but runs with pytest-asyncio""" io_loop = AsyncIOMainLoop() io_loop.make_current() assert io_loop.asyncio_loop is event_loop def _close(): io_loop.clear_current() io_loop.close(all_fds=True) request.addfinalizer(_close) return io_loop
def io_loop(event_loop, request): """Same as pytest-tornado.io_loop, but re-scoped to module-level""" ioloop.IOLoop.configure(AsyncIOMainLoop) io_loop = AsyncIOMainLoop() io_loop.make_current() assert asyncio.get_event_loop() is event_loop assert io_loop.asyncio_loop is event_loop def _close(): io_loop.clear_current() io_loop.close(all_fds=True) request.addfinalizer(_close) return io_loop
def io_loop(event_loop, request): """Make sure tornado io_loop is run on asyncio""" ioloop.IOLoop.configure(AsyncIOMainLoop) io_loop = AsyncIOMainLoop() io_loop.make_current() assert asyncio.get_event_loop() is event_loop assert io_loop.asyncio_loop is event_loop def _close(): io_loop.clear_current() io_loop.close(all_fds=True) request.addfinalizer(_close) return io_loop
class TornadoServer(AbstractServer): """ Flexx Server implemented in Tornado. """ def __init__(self, *args, **kwargs): self._app = None self._server = None super().__init__(*args, **kwargs) def _open(self, host, port, **kwargs): # Note: does not get called if host is False. That way we can # run Flexx in e.g. JLab's application. # Hook Tornado up with asyncio. Flexx' BaseServer makes sure # that the correct asyncio event loop is current (for this thread). # http://www.tornadoweb.org/en/stable/asyncio.html # todo: Since Tornado v5.0 asyncio is autom used, deprecating AsyncIOMainLoop self._io_loop = AsyncIOMainLoop() # I am sorry for this hack, but Tornado wont work otherwise :( # I wonder how long it will take before this will bite me back. I guess # we will be alright as long as there is no other Tornado stuff going on. IOLoop._current.instance = None self._io_loop.make_current() # handle ssl, wether from configuration or given args if config.ssl_certfile: if 'ssl_options' not in kwargs: kwargs['ssl_options'] = {} if 'certfile' not in kwargs['ssl_options']: kwargs['ssl_options']['certfile'] = config.ssl_certfile if config.ssl_keyfile: if 'ssl_options' not in kwargs: kwargs['ssl_options'] = {} if 'keyfile' not in kwargs['ssl_options']: kwargs['ssl_options']['keyfile'] = config.ssl_keyfile if config.tornado_debug: app_kwargs = dict(debug=True) else: app_kwargs = dict() # Create tornado application self._app = Application([ (r"/flexx/ws/(.*)", WSHandler), (r"/flexx/(.*)", MainHandler), (r"/(.*)", AppHandler), ], **app_kwargs) self._app._io_loop = self._io_loop # Create tornado server, bound to our own ioloop if tornado.version_info < (5, ): kwargs['io_loop'] = self._io_loop self._server = HTTPServer(self._app, **kwargs) # Start server (find free port number if port not given) if port: # Turn port into int, use hashed port number if a string was given try: port = int(port) except ValueError: port = port_hash(port) self._server.listen(port, host) else: # Try N ports in a repeatable range (easier, browser history, etc.) prefered_port = port_hash('Flexx') for i in range(8): port = prefered_port + i try: self._server.listen(port, host) break except (OSError, IOError): pass # address already in use else: # Ok, let Tornado figure out a port [sock] = netutil.bind_sockets(None, host, family=socket.AF_INET) self._server.add_sockets([sock]) port = sock.getsockname()[1] # Notify address, so its easy to e.g. copy and paste in the browser self._serving = self._app._flexx_serving = host, port proto = 'http' if 'ssl_options' in kwargs: proto = 'https' logger.info('Serving apps at %s://%s:%i/' % (proto, host, port)) def _close(self): self._server.stop() @property def app(self): """ The Tornado Application object being used.""" return self._app @property def server(self): """ The Tornado HttpServer object being used.""" return self._server @property def protocol(self): """ Get a string representing served protocol.""" if self._server.ssl_options is not None: return 'https' return 'http'
class TornadoServer(AbstractServer): """ Flexx Server implemented in Tornado. """ def __init__(self, *args, **kwargs): self._app = None self._server = None super().__init__(*args, **kwargs) def _open(self, host, port, **kwargs): # Note: does not get called if host is False. That way we can # run Flexx in e.g. JLab's application. # Hook Tornado up with asyncio. Flexx' BaseServer makes sure # that the correct asyncio event loop is current (for this thread). # http://www.tornadoweb.org/en/stable/asyncio.html # todo: Since Tornado v5.0 asyncio is autom used, deprecating AsyncIOMainLoop self._io_loop = AsyncIOMainLoop() # I am sorry for this hack, but Tornado wont work otherwise :( # I wonder how long it will take before this will bite me back. I guess # we will be alright as long as there is no other Tornado stuff going on. if hasattr(IOLoop, "_current"): IOLoop._current.instance = None else: IOLoop.current().instance = None self._io_loop.make_current() # handle ssl, wether from configuration or given args if config.ssl_certfile: if 'ssl_options' not in kwargs: kwargs['ssl_options'] = {} if 'certfile' not in kwargs['ssl_options']: kwargs['ssl_options']['certfile'] = config.ssl_certfile if config.ssl_keyfile: if 'ssl_options' not in kwargs: kwargs['ssl_options'] = {} if 'keyfile' not in kwargs['ssl_options']: kwargs['ssl_options']['keyfile'] = config.ssl_keyfile if config.tornado_debug: app_kwargs = dict(debug=True) else: app_kwargs = dict() # Create tornado application self._app = Application([(r"/flexx/ws/(.*)", WSHandler), (r"/flexx/(.*)", MainHandler), (r"/(.*)", AppHandler), ], **app_kwargs) self._app._io_loop = self._io_loop # Create tornado server, bound to our own ioloop if tornado.version_info < (5, ): kwargs['io_loop'] = self._io_loop self._server = HTTPServer(self._app, **kwargs) # Start server (find free port number if port not given) if port: # Turn port into int, use hashed port number if a string was given try: port = int(port) except ValueError: port = port_hash(port) self._server.listen(port, host) else: # Try N ports in a repeatable range (easier, browser history, etc.) prefered_port = port_hash('Flexx') for i in range(8): port = prefered_port + i try: self._server.listen(port, host) break except (OSError, IOError): pass # address already in use else: # Ok, let Tornado figure out a port [sock] = netutil.bind_sockets(None, host, family=socket.AF_INET) self._server.add_sockets([sock]) port = sock.getsockname()[1] # Notify address, so its easy to e.g. copy and paste in the browser self._serving = self._app._flexx_serving = host, port proto = 'http' if 'ssl_options' in kwargs: proto = 'https' # This string 'Serving apps at' is our 'ready' signal and is tested for. logger.info('Serving apps at %s://%s:%i/' % (proto, host, port)) def _close(self): self._server.stop() @property def app(self): """ The Tornado Application object being used.""" return self._app @property def server(self): """ The Tornado HttpServer object being used.""" return self._server @property def protocol(self): """ Get a string representing served protocol.""" if self._server.ssl_options is not None: return 'https' return 'http'