pytest.skip causes tests to fail on cleanup
vidartf opened this issue · 1 comments
vidartf commented
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
welcome commented
Thank you for opening your first issue in this project! Engagement like this is essential for open source projects!
If you haven't done so already, check out Jupyter's Code of Conduct. Also, please try to follow the issue template as it helps other other community members to contribute more effectively.
You can meet the other Jovyans by joining our Discourse forum. There is also an intro thread there where you can stop by and say Hi!
Welcome to the Jupyter community!