"OSError: could not get source code" Came Up When "pytest_fixture_setup()" Executed
Every initial test case will fail when pytest_fixture_setup is executed. I have compared pytest==8.1.1 and pytest==8.2.0. The 8.1.1 has no error, and the 8.2.0 has an error.
My conftest.py:
import asyncio
from asyncio import AbstractEventLoop
import pytest
import pytest_asyncio
from tests.containers.test_container import TestContainer
@pytest_asyncio.fixture(scope="session")
def event_loop():
loop: AbstractEventLoop = asyncio.get_event_loop()
yield loop
loop.close()
@pytest_asyncio.fixture(scope="function")
async def main_context(request: pytest.FixtureRequest):
test_container: TestContainer = TestContainer()
main_context = test_container.main_context()
await main_context.all_seeder.up()
yield main_context
await main_context.all_seeder.down()
Comparison:
- 8.1.1
============================= test session starts ==============================
platform linux -- Python 3.10.12, pytest-8.1.1, pluggy-1.5.0
rootdir: /app
plugins: cov-5.0.0, asyncio-0.23.6, xdist-3.6.1, anyio-4.3.0
asyncio: mode=strict
1 worker [43 items]
........................................... [100%]
- 8.2.0
============================================================================================================== test session starts ===============================================================================================================
platform linux -- Python 3.10.12, pytest-8.2.0, pluggy-1.5.0
rootdir: /app
plugins: cov-5.0.0, asyncio-0.23.6, xdist-3.6.1, anyio-4.3.0
asyncio: mode=strict
1 worker [5 items]
E.... [100%]
===================================================================================================================== ERRORS =====================================================================================================================
_______________________________________________________________________________________ ERROR at setup of test__find_many_with_pagination__should__succeed _______________________________________________________________________________________
[gw0] linux -- Python 3.10.12 /usr/bin/python3
fixturedef = <FixtureDef argname='event_loop' scope='session' baseid='tests'>
@pytest.hookimpl(hookwrapper=True)
def pytest_fixture_setup(
fixturedef: FixtureDef,
) -> Generator[None, Any, None]:
"""Adjust the event loop policy when an event loop is produced."""
if fixturedef.argname == "event_loop":
# The use of a fixture finalizer is preferred over the
# pytest_fixture_post_finalizer hook. The fixture finalizer is invoked once
# for each fixture, whereas the hook may be invoked multiple times for
# any specific fixture.
# see https://github.com/pytest-dev/pytest/issues/5848
_add_finalizers(
fixturedef,
_close_event_loop,
_restore_event_loop_policy(asyncio.get_event_loop_policy()),
_provide_clean_event_loop,
)
outcome = yield
loop: asyncio.AbstractEventLoop = outcome.get_result()
# Weird behavior was observed when checking for an attribute of FixtureDef.func
# Instead, we now check for a special attribute of the returned event loop
fixture_filename = inspect.getsourcefile(fixturedef.func)
if not getattr(loop, "__original_fixture_loop", False):
> _, fixture_line_number = inspect.getsourcelines(fixturedef.func)
/usr/local/lib/python3.10/dist-packages/pytest_asyncio/plugin.py:758:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3.10/inspect.py:1121: in getsourcelines
lines, lnum = findsource(object)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
object = <function event_loop at 0x7f7f854153f0>
def findsource(object):
"""Return the entire source file and starting line number for an object.
The argument may be a module, class, method, function, traceback, frame,
or code object. The source code is returned as a list of all the lines
in the file and the line number indexes a line in that list. An OSError
is raised if the source code cannot be retrieved."""
file = getsourcefile(object)
if file:
# Invalidate cache if needed.
linecache.checkcache(file)
else:
file = getfile(object)
# Allow filenames in form of "<something>" to pass through.
# `doctest` monkeypatches `linecache` module to enable
# inspection, so let `linecache.getlines` to be called.
if not (file.startswith('<') and file.endswith('>')):
raise OSError('source code not available')
module = getmodule(object, file)
if module:
lines = linecache.getlines(file, module.__dict__)
else:
lines = linecache.getlines(file)
if not lines:
> raise OSError('could not get source code')
E OSError: could not get source code
/usr/lib/python3.10/inspect.py:958: OSError
The same error here, pytest 7.4.4 and pytest-asyncio 0.23.4. It was harassing me for hours yesterday and then suddenly gone (just as suddenly, as it started).
pytest-asyncio 0.23.6 and pytest 8.2.0 same
gone with pytest==8.1.1
Thanks for reporting this. The pytest-asyncio tests don't seem to be affected, so it's hard to find the cause of the error.
@muazhari @Klavionik @halvomez: Can any one provide a minimal code example that reproduces the issue?
Fixed in pytest==8.2.1. However, I can't reproduce the error with minimal codes with pytest==8.2.0 and the same environment. I don't know why.
============================= test session starts ==============================
platform linux -- Python 3.10.12, pytest-8.2.1, pluggy-1.5.0
rootdir: /app
plugins: cov-5.0.0, asyncio-0.23.6, xdist-3.6.1, anyio-4.3.0
asyncio: mode=strict
1 worker [6 items]
......
Since this issue seems to be fixed with more recent versions of pytest and I cannot reproduce it, I'll close the ticket until further evidence arrives.
Also encountered this on the latest pytest (8.3.2). Causes the first test in the session to fail, but then all the subsequent ones succeed. Reverting to 0.21.2 resolves this 🤔
platform linux -- Python 3.9.6, pytest-8.3.2, pluggy-1.5.0
plugins: asyncio-0.23.8
asyncio: mode=auto
@mike-oakley Any chance you can cook up a reproducer so we can get to the bottom of this?
The same problem:
`$ poetry show pytest
name : pytest
version : 8.3.2
description : pytest: simple powerful testing with Python `
and
`$ poetry show pytest-asyncio
name : pytest-asyncio
version : 0.23.8
description : Pytest support for asyncio `
There's really not much I can do to help, unless someone can provide a minimal reproducer.
There's really not much I can do to help, unless someone can provide a minimal reproducer.
Here is example fixture "event_loop" which we have a problem with
@pytest.fixture(scope='session')
def event_loop():
try:
loop = asyncio.get_running_loop()
except RuntimeError:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
yield loop
loop.close()
Try to run any tests, you might get error always in first test, because problem in moment initialization.
pytest==8.1.1 work good, 8.2.1 sometimes work, 8.2.2 doesn't work
You can try this and reproduce: conftest.py
import asyncio
from httpx import AsyncClient
@pytest.fixture(scope='session')
def event_loop():
try:
loop = asyncio.get_running_loop()
except RuntimeError:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
yield loop
loop.close()
@pytest.fixture(scope='session')
async def http_client():
async with AsyncClient(app=app, base_url='https://test.io/') as client:
yield client
test_ping.py
from httpx import AsyncClient
async def test__ping(http_client: AsyncClient):
response = await http_client.get('/ping')
assert response.status_code == 200
assert response.json() == {'msg': 'pong'}
Even this tiny test return this error
@devTarik Thanks for backing this issue up with some more code. However, when I try to run your example, I get the following error:
@pytest.fixture(scope='session')
async def http_client():
> async with AsyncClient(app=app, base_url='https://test.io/') as client:
E NameError: name 'app' is not defined
conftest.py:18: NameError
Is there a minimal implementation of app you can share?