From 3b816f803e98c3db9993ee7dfbd65cc121d4aae2 2021-12-05 18:30:29 From: Nikita Kniazev Date: 2021-12-05 18:30:29 Subject: [PATCH] Tweak tests for PyPy and add CI runner * `autoreload` tests are skipped on PyPy because `gc.get_referrers` is unusably slow here * `doctest_refs` does not seem to test anything and was removed * pexpect timeouts were adjusted because subprocess communication is 3-4 times slower on PyPy * few other tweaks --- diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 898dfe5..5cb06d9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -33,6 +33,16 @@ jobs: - os: ubuntu-latest python-version: "3.11-dev" deps: test + # Installing optional dependencies stuff takes ages on PyPy + - os: ubuntu-latest + python-version: "pypy-3.8" + deps: test + - os: windows-latest + python-version: "pypy-3.8" + deps: test + - os: macos-latest + python-version: "pypy-3.8" + deps: test steps: - uses: actions/checkout@v2 diff --git a/IPython/core/tests/test_async_helpers.py b/IPython/core/tests/test_async_helpers.py index 9ca67f4..40a840c 100644 --- a/IPython/core/tests/test_async_helpers.py +++ b/IPython/core/tests/test_async_helpers.py @@ -3,6 +3,7 @@ Test for async helpers. Should only trigger on python 3.5+ or will have syntax errors. """ +import platform from itertools import chain, repeat from textwrap import dedent, indent from unittest import TestCase @@ -275,7 +276,7 @@ class AsyncTest(TestCase): """ ) - if sys.version_info < (3,9): + if sys.version_info < (3, 9) and platform.python_implementation() != "PyPy": # new pgen parser in 3.9 does not raise MemoryError on too many nested # parens anymore def test_memory_error(self): diff --git a/IPython/core/tests/test_debugger.py b/IPython/core/tests/test_debugger.py index 65bcb5e..75ce9fd 100644 --- a/IPython/core/tests/test_debugger.py +++ b/IPython/core/tests/test_debugger.py @@ -371,11 +371,13 @@ def _decorator_skip_setup(): child = pexpect.spawn( sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env ) - child.timeout = 5 * IPYTHON_TESTING_TIMEOUT_SCALE + child.timeout = 15 * IPYTHON_TESTING_TIMEOUT_SCALE child.expect("IPython") child.expect("\n") + child.timeout = 5 * IPYTHON_TESTING_TIMEOUT_SCALE + dedented_blocks = [dedent(b).strip() for b in skip_decorators_blocks] in_prompt_number = 1 for cblock in dedented_blocks: @@ -448,11 +450,13 @@ def test_decorator_skip_with_breakpoint(): child = pexpect.spawn( sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env ) - child.timeout = 5 * IPYTHON_TESTING_TIMEOUT_SCALE + child.timeout = 15 * IPYTHON_TESTING_TIMEOUT_SCALE child.expect("IPython") child.expect("\n") + child.timeout = 5 * IPYTHON_TESTING_TIMEOUT_SCALE + ### we need a filename, so we need to exec the full block with a filename with NamedTemporaryFile(suffix=".py", dir=".", delete=True) as tf: diff --git a/IPython/core/tests/test_magic.py b/IPython/core/tests/test_magic.py index 428d711..aa006f6 100644 --- a/IPython/core/tests/test_magic.py +++ b/IPython/core/tests/test_magic.py @@ -2,6 +2,7 @@ """Tests for various magic functions.""" import asyncio +import gc import io import os import re @@ -576,6 +577,7 @@ class TestXdel(tt.TempFileMixin): _ip.magic("xdel a") # Check that a's __del__ method has been called. + gc.collect(0) assert monitor == [1] def doctest_who(): diff --git a/IPython/core/tests/test_run.py b/IPython/core/tests/test_run.py index a872f5a..0f73a78 100644 --- a/IPython/core/tests/test_run.py +++ b/IPython/core/tests/test_run.py @@ -18,6 +18,7 @@ as otherwise it may influence later tests. import functools import os +import platform from os.path import join as pjoin import random import string @@ -158,7 +159,7 @@ def doctest_reset_del(): In [3]: a = A() - In [4]: get_ipython().reset() + In [4]: get_ipython().reset(); import gc; x = gc.collect(0) Hi In [5]: 1+1 @@ -241,6 +242,10 @@ class TestMagicRunSimple(tt.TempFileMixin): _ip.run_cell("t = isinstance(f(), foo)") assert _ip.user_ns["t"] is True + @pytest.mark.xfail( + platform.python_implementation() == "PyPy", + reason="expecting __del__ call on exit is unreliable and doesn't happen on PyPy", + ) def test_obj_del(self): """Test that object's __del__ methods are called on exit.""" src = ("class A(object):\n" @@ -286,14 +291,20 @@ class TestMagicRunSimple(tt.TempFileMixin): _ip.magic("run %s" % empty.fname) assert _ip.user_ns["afunc"]() == 1 - @dec.skip_win32 def test_tclass(self): mydir = os.path.dirname(__file__) - tc = os.path.join(mydir, 'tclass') - src = ("%%run '%s' C-first\n" - "%%run '%s' C-second\n" - "%%run '%s' C-third\n") % (tc, tc, tc) - self.mktmp(src, '.ipy') + tc = os.path.join(mydir, "tclass") + src = f"""\ +import gc +%run "{tc}" C-first +gc.collect(0) +%run "{tc}" C-second +gc.collect(0) +%run "{tc}" C-third +gc.collect(0) +%reset -f +""" + self.mktmp(src, ".ipy") out = """\ ARGV 1-: ['C-first'] ARGV 1-: ['C-second'] diff --git a/IPython/core/tests/test_ultratb.py b/IPython/core/tests/test_ultratb.py index d0f13df..66a7a95 100644 --- a/IPython/core/tests/test_ultratb.py +++ b/IPython/core/tests/test_ultratb.py @@ -3,6 +3,7 @@ """ import io import logging +import platform import re import sys import os.path @@ -248,7 +249,8 @@ bar() ip.showsyntaxerror() import sys -if sys.version_info < (3,9): + +if sys.version_info < (3, 9) and platform.python_implementation() != "PyPy": """ New 3.9 Pgen Parser does not raise Memory error, except on failed malloc. """ @@ -359,7 +361,7 @@ def r3o2(): ): ip.run_cell("r1()") - @recursionlimit(200) + @recursionlimit(160) def test_recursion_three_frames(self): with tt.AssertPrints("[... skipping similar frames: "), \ tt.AssertPrints(re.compile(r"r3a at line 8 \(\d{2} times\)"), suppress=False), \ diff --git a/IPython/extensions/tests/test_autoreload.py b/IPython/extensions/tests/test_autoreload.py index e03a08e..8cc55e7 100644 --- a/IPython/extensions/tests/test_autoreload.py +++ b/IPython/extensions/tests/test_autoreload.py @@ -13,6 +13,8 @@ # ----------------------------------------------------------------------------- import os +import platform +import pytest import sys import tempfile import textwrap @@ -28,6 +30,12 @@ from unittest import TestCase from IPython.extensions.autoreload import AutoreloadMagics from IPython.core.events import EventManager, pre_run_cell +if platform.python_implementation() == "PyPy": + pytest.skip( + "Current autoreload implementation is extremly slow on PyPy", + allow_module_level=True, + ) + # ----------------------------------------------------------------------------- # Test fixture # ----------------------------------------------------------------------------- diff --git a/IPython/terminal/tests/test_debug_magic.py b/IPython/terminal/tests/test_debug_magic.py index d19f827..faa3b7c 100644 --- a/IPython/terminal/tests/test_debug_magic.py +++ b/IPython/terminal/tests/test_debug_magic.py @@ -51,6 +51,8 @@ def test_debug_magic_passes_through_generators(): child.sendline(" pass") child.sendline("") + child.timeout = 10 * IPYTHON_TESTING_TIMEOUT_SCALE + child.expect('Exception:') child.expect(in_prompt) diff --git a/IPython/terminal/tests/test_embed.py b/IPython/terminal/tests/test_embed.py index ac4c942..3f0885e 100644 --- a/IPython/terminal/tests/test_embed.py +++ b/IPython/terminal/tests/test_embed.py @@ -74,8 +74,9 @@ def test_nest_embed(): child = pexpect.spawn(sys.executable, ['-m', 'IPython', '--colors=nocolor'], env=env) - child.timeout = 5 * IPYTHON_TESTING_TIMEOUT_SCALE + child.timeout = 15 * IPYTHON_TESTING_TIMEOUT_SCALE child.expect(ipy_prompt) + child.timeout = 5 * IPYTHON_TESTING_TIMEOUT_SCALE child.sendline("import IPython") child.expect(ipy_prompt) child.sendline("ip0 = get_ipython()") diff --git a/IPython/testing/plugin/show_refs.py b/IPython/testing/plugin/show_refs.py deleted file mode 100644 index b2c70ad..0000000 --- a/IPython/testing/plugin/show_refs.py +++ /dev/null @@ -1,19 +0,0 @@ -"""Simple script to show reference holding behavior. - -This is used by a companion test case. -""" - -import gc - -class C(object): - def __del__(self): - pass - #print 'deleting object...' # dbg - -if __name__ == '__main__': - c = C() - - c_refs = gc.get_referrers(c) - ref_ids = list(map(id,c_refs)) - - print('c referrers:',list(map(type,c_refs))) diff --git a/IPython/testing/plugin/test_refs.py b/IPython/testing/plugin/test_refs.py index bd7ad8f..b92448b 100644 --- a/IPython/testing/plugin/test_refs.py +++ b/IPython/testing/plugin/test_refs.py @@ -37,10 +37,3 @@ def doctest_ivars(): In [6]: zz Out[6]: 1 """ - -def doctest_refs(): - """DocTest reference holding issues when running scripts. - - In [32]: run show_refs.py - c referrers: [<... 'dict'>] - """ diff --git a/IPython/utils/ipstruct.py b/IPython/utils/ipstruct.py index d71a75e..ed11210 100644 --- a/IPython/utils/ipstruct.py +++ b/IPython/utils/ipstruct.py @@ -131,7 +131,7 @@ class Struct(dict): >>> s.a 10 >>> type(s.get) - <... 'builtin_function_or_method'> + <...method'> >>> try: ... s.b ... except AttributeError: