Using a PyodideHandle in a fixture with the playwright runner, I am seeing a warning about an ignored exception when cleaning up the test.
Test case:
# tomtests/test_handle_bug.py
import pytest
from pytest_pyodide import run_in_pyodide
@pytest.fixture
@run_in_pyodide
def macguffin(selenium):
from pytest_pyodide.decorator import PyodideHandle
s = {"a": 1}
return PyodideHandle(s)
@run_in_pyodide
def test_macguffin(selenium, macguffin):
assert macguffin["a"] == 1
# uv sync --all-extras
# uv run pytest --runner playwright --rt chrome tomtests/
Also pushed here: tomjakubowski@23cd219
Error message:
Exception ignored in: <function PyodideHandle.__del__ at 0x101ffa3e0>
Traceback (most recent call last):
File "/Users/tom/github.com/pyodide/pytest-pyodide/pytest_pyodide/decorator.py", line 88, in __del__
self.selenium.run_js(
File "/Users/tom/github.com/pyodide/pytest-pyodide/pytest_pyodide/runner.py", line 262, in run_js
return self.run_js_inner(code, check_code)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/pytest_pyodide/runner.py", line 415, in run_js_inner
retval = self.driver.evaluate(wrapper % (code, check_code))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/playwright/sync_api/_generated.py", line 8530, in evaluate
self._sync(
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/playwright/_impl/_sync_base.py", line 104, in _sync
raise Error("Event loop is closed! Is Playwright already stopped?")
playwright._impl._errors.Error: Event loop is closed! Is Playwright already stopped?
Note that this doesn't cause the test to fail, and the exit code is 0.
I see a similar error message when running with --runner selenium:
Exception ignored in: <function PyodideHandle.__del__ at 0x1032263e0>
Traceback (most recent call last):
File "/Users/tom/github.com/pyodide/pytest-pyodide/pytest_pyodide/decorator.py", line 88, in __del__
self.selenium.run_js(
File "/Users/tom/github.com/pyodide/pytest-pyodide/pytest_pyodide/runner.py", line 262, in run_js
return self.run_js_inner(code, check_code)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/pytest_pyodide/runner.py", line 362, in run_js_inner
retval = self.driver.execute_async_script(wrapper % (code, check_code))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/selenium/webdriver/remote/webdriver.py", line 550, in execute_async_script
return self.execute(command, {"script": script, "args": converted_args})["value"]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/selenium/webdriver/remote/webdriver.py", line 427, in execute
response = self.command_executor.execute(driver_command, params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/selenium/webdriver/remote/remote_connection.py", line 404, in execute
return self._request(command_info[0], url, body=data)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/selenium/webdriver/remote/remote_connection.py", line 428, in _request
response = self._conn.request(method, url, body=body, headers=headers, timeout=self._client_config.timeout)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/urllib3/_request_methods.py", line 143, in request
return self.request_encode_body(
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/urllib3/_request_methods.py", line 278, in request_encode_body
return self.urlopen(method, url, **extra_kw)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/urllib3/poolmanager.py", line 443, in urlopen
response = conn.urlopen(method, u.request_uri, **kw)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/urllib3/connectionpool.py", line 871, in urlopen
return self.urlopen(
^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/urllib3/connectionpool.py", line 871, in urlopen
return self.urlopen(
^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/urllib3/connectionpool.py", line 871, in urlopen
return self.urlopen(
^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/urllib3/connectionpool.py", line 841, in urlopen
retries = retries.increment(
^^^^^^^^^^^^^^^^^^
File "/Users/tom/github.com/pyodide/pytest-pyodide/.venv/lib/python3.12/site-packages/urllib3/util/retry.py", line 519, in increment
raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=60847): Max retries exceeded with url: /session/d6624be6a6c2269e04186b871e101b60/execute/async (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x1034bb7a0>: Failed to establish a new connection: [Errno 61] Connection refused'))
I think that the handle's finalizer is being called after the event loop is closed, and the call to eval the reference count decrement is what's throwing.
Using a PyodideHandle in a fixture with the playwright runner, I am seeing a warning about an ignored exception when cleaning up the test.
Test case:
Also pushed here: tomjakubowski@23cd219
Error message:
Note that this doesn't cause the test to fail, and the exit code is 0.
I see a similar error message when running with
--runner selenium:I think that the handle's finalizer is being called after the event loop is closed, and the call to eval the reference count decrement is what's throwing.