Fix infinite recursion when writing pyc files: if an import happens to be triggered when writing the pyc file, this would cause another call to the hook, which would trigger another pyc writing, which could trigger another import, and so on. (#3506)
(
pytester: Pytester, pytestconfig, monkeypatch
)
| 1874 | |
| 1875 | |
| 1876 | def test_rewrite_infinite_recursion( |
| 1877 | pytester: Pytester, pytestconfig, monkeypatch |
| 1878 | ) -> None: |
| 1879 | """Fix infinite recursion when writing pyc files: if an import happens to be triggered when writing the pyc |
| 1880 | file, this would cause another call to the hook, which would trigger another pyc writing, which could |
| 1881 | trigger another import, and so on. (#3506)""" |
| 1882 | from _pytest.assertion import rewrite as rewritemod |
| 1883 | |
| 1884 | pytester.syspathinsert() |
| 1885 | pytester.makepyfile(test_foo="def test_foo(): pass") |
| 1886 | pytester.makepyfile(test_bar="def test_bar(): pass") |
| 1887 | |
| 1888 | original_write_pyc = rewritemod._write_pyc |
| 1889 | |
| 1890 | write_pyc_called = [] |
| 1891 | |
| 1892 | def spy_write_pyc(*args, **kwargs): |
| 1893 | # make a note that we have called _write_pyc |
| 1894 | write_pyc_called.append(True) |
| 1895 | # try to import a module at this point: we should not try to rewrite this module |
| 1896 | assert hook.find_spec("test_bar") is None |
| 1897 | return original_write_pyc(*args, **kwargs) |
| 1898 | |
| 1899 | monkeypatch.setattr(rewritemod, "_write_pyc", spy_write_pyc) |
| 1900 | monkeypatch.setattr(sys, "dont_write_bytecode", False) |
| 1901 | |
| 1902 | hook = AssertionRewritingHook(pytestconfig) |
| 1903 | spec = hook.find_spec("test_foo") |
| 1904 | assert spec is not None |
| 1905 | module = importlib.util.module_from_spec(spec) |
| 1906 | hook.exec_module(module) |
| 1907 | assert len(write_pyc_called) == 1 |
| 1908 | |
| 1909 | |
| 1910 | class TestEarlyRewriteBailout: |
nothing calls this directly
no test coverage detected