jupyter-server/pytest-jupyter

pytest.skip causes tests to fail on cleanup

vidartf opened this issue · 1 comments

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

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.
welcome
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! 🎉