Calysto / metakernel

Jupyter/IPython Kernel Tools
BSD 3-Clause "New" or "Revised" License
344 stars 84 forks source link

Test failures with Python 3.13 #279

Open ellert opened 3 months ago

ellert commented 3 months ago

Two tests fail when using Python 3.13:

=================================== FAILURES ===================================
________________________________ test_get_help _________________________________

    def test_get_help():
        kernel = get_kernel()
        d = Dummy(kernel)

        dummy_help = d.get_help('line', 'dummy', 0)
        assert dummy_help.startswith("%dummy")
>       assert "    This is additional information on dummy" in d.line_dummy.__doc__, "Checking indents"
E       AssertionError: Checking indents
E       assert '    This is additional information on dummy' in '\n%dummy [options] foo - Perform dummy operation on foo\n\nThis is additional information on dummy.\n\n\nOptions:\n-------\n-s --size      Pixel size of plots, "width,height"'
E        +  where '\n%dummy [options] foo - Perform dummy operation on foo\n\nThis is additional information on dummy.\n\n\nOptions:\n-------\n-s --size      Pixel size of plots, "width,height"' = <bound method Dummy.line_dummy of <metakernel.tests.test_magic.Dummy object at 0x7fb288225810>>.__doc__
E        +    where <bound method Dummy.line_dummy of <metakernel.tests.test_magic.Dummy object at 0x7fb288225810>> = <metakernel.tests.test_magic.Dummy object at 0x7fb288225810>.line_dummy

/builddir/build/BUILD/python-metakernel-0.30.2-build/metakernel-0.30.2/metakernel/tests/test_magic.py:51: AssertionError
_________________________ REPLWrapTestCase.test_python _________________________

self = <metakernel.tests.test_replwrap.REPLWrapTestCase testMethod=test_python>

    def test_python(self):
        if platform.python_implementation() == 'PyPy':
            raise unittest.SkipTest("This test fails on PyPy because of REPL differences")

        if platform.system() == 'Darwin':
            raise unittest.SkipTest("This test fails on macOS because of REPL differences")

>       p = replwrap.python(sys.executable)

/builddir/build/BUILD/python-metakernel-0.30.2-build/metakernel-0.30.2/metakernel/tests/test_replwrap.py:82: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/builddir/build/BUILD/python-metakernel-0.30.2-build/metakernel-0.30.2/metakernel/replwrap.py:288: in python
    return REPLWrapper(command, u(">>> "),
/builddir/build/BUILD/python-metakernel-0.30.2-build/metakernel-0.30.2/metakernel/replwrap.py:99: in __init__
    self._expect_prompt()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <metakernel.replwrap.REPLWrapper object at 0x7fb28698b490>
timeout = None

    def _expect_prompt(self, timeout=None):
        """Expect a prompt from the child.
        """
        expects = [self.prompt_regex, self.continuation_prompt_regex,
                   self.stdin_prompt_regex]
        if self.prompt_emit_cmd:
            self.sendline(self.prompt_emit_cmd)

        if self._stream_handler:
            return self._expect_prompt_stream(expects, timeout)

        if self._line_handler:
            expects += [u(self.child.crlf)]

        while True:
            pos = self.child.expect(expects, timeout=timeout)
            # got a full prompt or continuation prompt.
            if pos in [0, 1]:
                return pos
            # got a stdin prompt
            if pos == 2:
                if not self._stdin_handler:
>                   raise ValueError('Stdin Requested but not stdin handler available')
E                   ValueError: Stdin Requested but not stdin handler available

/builddir/build/BUILD/python-metakernel-0.30.2-build/metakernel-0.30.2/metakernel/replwrap.py:138: ValueError

The list of changes in Python 3.13 are described here: https://docs.python.org/3.13/whatsnew/3.13.html

The first failure is related to the following change: https://docs.python.org/3.13/whatsnew/3.13.html#other-language-changes

"Compiler now strip indents from docstrings. This will reduce the size of bytecode cache (e.g. .pyc file). For example, cache file size for sqlalchemy.orm.session in SQLAlchemy 2.0 is reduced by about 5%. This change will affect tools using docstrings, like doctest.Compiler now strip indents from docstrings. This will reduce the size of bytecode cache (e.g. .pyc file). For example, cache file size for sqlalchemy.orm.session in SQLAlchemy 2.0 is reduced by about 5%. This change will affect tools using docstrings, like doctest."

If the four spaces at the beginning of the string ar removed, the tast passes, e.g.:

assert "    This is additional information on dummy" in d.line_dummy.__doc__, "Checking indents"

is changed to:

assert "This is additional information on dummy" in d.line_dummy.__doc__, "Checking indents"

For the second failure, I have no proposed fix.

ellert commented 3 months ago

Regarding the second failure:

With Python 3.12 pos is 0 and the return statement is executed. With Python 3.13 pos is 2 and the exception is raised.

        if pos in [0, 1]:
            return pos
        # got a stdin prompt
        if pos == 2:
            if not self._stdin_handler:
                raise ValueError('Stdin Requested but not stdin handler available')

This test is skipped if PyPy is used. It is alos skipped on macos. In both cases "because of REPL differences". I have no better suggestion than to skip the test for Python >= 3.13 for the same reason.