jupyter_client icon indicating copy to clipboard operation
jupyter_client copied to clipboard

Test TestAsyncKernelClient::test_input_request failed on riscv64

Open kxxt opened this issue 1 year ago • 0 comments

Hi,

I am trying to build jupyter_client on riscv64 linux. I have noticed that there is a failing test.

Failing test: TestAsyncKernelClient.test_input_request
=================================== FAILURES ===================================
___________________ TestAsyncKernelClient.test_input_request ___________________

self = <tests.test_client.TestAsyncKernelClient object at 0x40067310f0>
kc = <jupyter_client.asynchronous.client.AsyncKernelClient object at 0x400677cd00>

    @pytest.mark.skipif(
        sys.platform != 'linux' or platform.python_implementation().lower() == 'pypy',
        reason='only works with cpython on ubuntu in ci',
    )
    async def test_input_request(self, kc):
        with mock.patch('builtins.input', return_value='test\n'):
>           reply = await kc.execute_interactive("a = input()", timeout=TIMEOUT)

tests/test_client.py:132: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <jupyter_client.asynchronous.client.AsyncKernelClient object at 0x400677cd00>
code = 'a = input()', silent = False, store_history = True
user_expressions = None, allow_stdin = True, stop_on_error = True
timeout = 29.978911502999836
output_hook = <bound method KernelClient._output_hook_default of <jupyter_client.asynchronous.client.AsyncKernelClient object at 0x400677cd00>>
stdin_hook = <bound method KernelClient._stdin_hook_default of <jupyter_client.asynchronous.client.AsyncKernelClient object at 0x400677cd00>>

    async def _async_execute_interactive(
        self,
        code: str,
        silent: bool = False,
        store_history: bool = True,
        user_expressions: t.Optional[t.Dict[str, t.Any]] = None,
        allow_stdin: t.Optional[bool] = None,
        stop_on_error: bool = True,
        timeout: t.Optional[float] = None,
        output_hook: t.Optional[t.Callable] = None,
        stdin_hook: t.Optional[t.Callable] = None,
    ) -> t.Dict[str, t.Any]:
        """Execute code in the kernel interactively
    
        Output will be redisplayed, and stdin prompts will be relayed as well.
        If an IPython kernel is detected, rich output will be displayed.
    
        You can pass a custom output_hook callable that will be called
        with every IOPub message that is produced instead of the default redisplay.
    
        .. versionadded:: 5.0
    
        Parameters
        ----------
        code : str
            A string of code in the kernel's language.
    
        silent : bool, optional (default False)
            If set, the kernel will execute the code as quietly possible, and
            will force store_history to be False.
    
        store_history : bool, optional (default True)
            If set, the kernel will store command history.  This is forced
            to be False if silent is True.
    
        user_expressions : dict, optional
            A dict mapping names to expressions to be evaluated in the user's
            dict. The expression values are returned as strings formatted using
            :func:`repr`.
    
        allow_stdin : bool, optional (default self.allow_stdin)
            Flag for whether the kernel can send stdin requests to frontends.
    
            Some frontends (e.g. the Notebook) do not support stdin requests.
            If raw_input is called from code executed from such a frontend, a
            StdinNotImplementedError will be raised.
    
        stop_on_error: bool, optional (default True)
            Flag whether to abort the execution queue, if an exception is encountered.
    
        timeout: float or None (default: None)
            Timeout to use when waiting for a reply
    
        output_hook: callable(msg)
            Function to be called with output messages.
            If not specified, output will be redisplayed.
    
        stdin_hook: callable(msg)
            Function or awaitable to be called with stdin_request messages.
            If not specified, input/getpass will be called.
    
        Returns
        -------
        reply: dict
            The reply message for this request
        """
        if not self.iopub_channel.is_alive():
            emsg = "IOPub channel must be running to receive output"
            raise RuntimeError(emsg)
        if allow_stdin is None:
            allow_stdin = self.allow_stdin
        if allow_stdin and not self.stdin_channel.is_alive():
            emsg = "stdin channel must be running to allow input"
            raise RuntimeError(emsg)
        msg_id = await ensure_async(
            self.execute(
                code,
                silent=silent,
                store_history=store_history,
                user_expressions=user_expressions,
                allow_stdin=allow_stdin,
                stop_on_error=stop_on_error,
            )
        )
        if stdin_hook is None:
            stdin_hook = self._stdin_hook_default
        # detect IPython kernel
        if output_hook is None and "IPython" in sys.modules:
            from IPython import get_ipython
    
            ip = get_ipython()
            in_kernel = getattr(ip, "kernel", False)
            if in_kernel:
                output_hook = partial(
                    self._output_hook_kernel,
                    ip.display_pub.session,
                    ip.display_pub.pub_socket,
                    ip.display_pub.parent_header,
                )
        if output_hook is None:
            # default: redisplay plain-text outputs
            output_hook = self._output_hook_default
    
        # set deadline based on timeout
        if timeout is not None:
            deadline = time.monotonic() + timeout
        else:
            timeout_ms = None
    
        poller = zmq.Poller()
        iopub_socket = self.iopub_channel.socket
        poller.register(iopub_socket, zmq.POLLIN)
        if allow_stdin:
            stdin_socket = self.stdin_channel.socket
            poller.register(stdin_socket, zmq.POLLIN)
        else:
            stdin_socket = None
    
        # wait for output and redisplay it
        while True:
            if timeout is not None:
                timeout = max(0, deadline - time.monotonic())
                timeout_ms = int(1000 * timeout)
            events = dict(poller.poll(timeout_ms))
            if not events:
                emsg = "Timeout waiting for output"
>               raise TimeoutError(emsg)
E               TimeoutError: Timeout waiting for output

jupyter_client/client.py:536: TimeoutError
----------------------------- Captured stdout call -----------------------------
a = input()

It still times out if I modify the TIMEOUT variable in tests/test_client.py.

It seems it is deadlocked. Do you have any idea why that test is failing?

This test is marked as only works with cpython on ubuntu in ci. Is there any reason for that? Maybe the test is failing for the same reason here on linux riscv64.

Any help is greatly appreciated.

kxxt avatar Apr 15 '23 11:04 kxxt