Closed
Description
Description
In a test that uses pytest-jupyter fixture, if I call pytest.skip()
, the test will fail during cleanup with a timeout error! See e.g. jupyterlab/jupyterlab_server#324
Context
___________ ERROR at teardown of test_contents_manager_preferred_dir ___________
io_loop = <tornado.platform.asyncio.AsyncIOMainLoop object at 0x7f7ad4b25c50>
http_server_port = (<socket.socket [closed] fd=-1, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6>, 36149)
jp_web_app = <jupyter_server.serverapp.ServerWebApplication object at 0x7f7ad3ea1a50>
@pytest.fixture
def http_server(io_loop, http_server_port, jp_web_app):
"""Start a tornado HTTP server that listens on all available interfaces."""
async def get_server():
server = tornado.httpserver.HTTPServer(jp_web_app)
server.add_socket(http_server_port[0])
return server
server = io_loop.run_sync(get_server)
yield server
server.stop()
if hasattr(server, "close_all_connections"):
> io_loop.run_sync(server.close_all_connections)
../../../.local/share/hatch/env/virtual/jupyterlab-server/DCUu2YYM/cov/lib/python3.7/site-packages/pytest_jupyter/jupyter_server.py:70:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <tornado.platform.asyncio.AsyncIOMainLoop object at 0x7f7ad4b25c50>
func = <bound method HTTPServer.close_all_connections of <tornado.httpserver.HTTPServer object at 0x7f7ad3eaedd0>>
timeout = None
def run_sync(self, func: Callable, timeout: Optional[float] = None) -> Any:
"""Starts the `IOLoop`, runs the given function, and stops the loop.
The function must return either an awaitable object or
``None``. If the function returns an awaitable object, the
`IOLoop` will run until the awaitable is resolved (and
`run_sync()` will return the awaitable's result). If it raises
an exception, the `IOLoop` will stop and the exception will be
re-raised to the caller.
The keyword-only argument ``timeout`` may be used to set
a maximum duration for the function. If the timeout expires,
a `asyncio.TimeoutError` is raised.
This method is useful to allow asynchronous calls in a
``main()`` function::
async def main():
# do stuff...
if __name__ == '__main__':
IOLoop.current().run_sync(main)
.. versionchanged:: 4.3
Returning a non-``None``, non-awaitable value is now an error.
.. versionchanged:: 5.0
If a timeout occurs, the ``func`` coroutine will be cancelled.
.. versionchanged:: 6.2
``tornado.util.TimeoutError`` is now an alias to ``asyncio.TimeoutError``.
"""
future_cell = [None] # type: List[Optional[Future]]
def run() -> None:
try:
result = func()
if result is not None:
from tornado.gen import convert_yielded
result = convert_yielded(result)
except Exception:
fut = Future() # type: Future[Any]
future_cell[0] = fut
future_set_exc_info(fut, sys.exc_info())
else:
if is_future(result):
future_cell[0] = result
else:
fut = Future()
future_cell[0] = fut
fut.set_result(result)
assert future_cell[0] is not None
self.add_future(future_cell[0], lambda future: self.stop())
self.add_callback(run)
if timeout is not None:
def timeout_callback() -> None:
# If we can cancel the future, do so and wait on it. If not,
# Just stop the loop and return with the task still pending.
# (If we neither cancel nor wait for the task, a warning
# will be logged).
assert future_cell[0] is not None
if not future_cell[0].cancel():
self.stop()
timeout_handle = self.add_timeout(self.time() + timeout, timeout_callback)
self.start()
if timeout is not None:
self.remove_timeout(timeout_handle)
assert future_cell[0] is not None
if future_cell[0].cancelled() or not future_cell[0].done():
> raise TimeoutError("Operation timed out after %s seconds" % timeout)
E concurrent.futures._base.TimeoutError: Operation timed out after None seconds
../../../.local/share/hatch/env/virtual/jupyterlab-server/DCUu2YYM/cov/lib/python3.7/site-packages/tornado/ioloop.py:528: TimeoutError