Repository: pytest-dev/pytest
File: src/_pytest/fixtures.py (Python)

Code before:
    return fixturefunc


def pytest_fixture_setup(
    fixturedef: FixtureDef[FixtureValue], request: SubRequest
) -> FixtureValue:
    """Execution of fixture setup."""
    kwargs = {}
    for argname in fixturedef.argnames:
        kwargs[argname] = request.getfixturevalue(argname)

    fixturefunc = resolve_fixture_function(fixturedef, request)
    my_cache_key = fixturedef.cache_key(request)

    if inspect.isasyncgenfunction(fixturefunc) or inspect.iscoroutinefunction(
        fixturefunc
    ):
        auto_str = " with autouse=True" if fixturedef._autouse else ""

        warnings.warn(
            PytestRemovedIn9Warning(
                f"{request.node.name!r} requested an async fixture "
                f"{request.fixturename!r}{auto_str}, with no plugin or hook that "
                "handled it. This is usually an error, as pytest does not natively "
                "support it. If this is intentional, consider making the fixture "
                "sync and return a coroutine/asyncgen. "
                "This will turn into an error in pytest 9."
            ),
            # no stacklevel will point at users code, so we just point here
            stacklevel=1,
        )

    try:
        result = call_fixture_func(fixturefunc, request, kwargs)
    except TEST_OUTCOME as e:
        if isinstance(e, skip.Exception):
            # The test requested a fixture which caused a skip.
            # Don't show the fixture as the skip location, as then the user
            # wouldn't know which test skipped.
            e._use_item_location = True
        fixturedef.cached_result = (None, my_cache_key, (e, e.__traceback__))
        raise
    fixturedef.cached_result = (result, my_cache_key, None)
    return result


def wrap_function_to_error_out_if_called_directly(
    function: FixtureFunction,
    fixture_marker: FixtureFunctionMarker,
) -> FixtureFunction:
    """Wrap the given fixture function so we can raise an error about it being called directly,

Review comment (bug):
Hmmm I think the use case of returning an actual async object and expecting to use that in the test is rare (but really is just my gut feeling and I could be wrong!). If you agree, I think we should remove this suggestion from here, as the usual "fix" is to install an async plugin, and not change the fixture definition.

```suggestion
                "support it. "
```

With my suggestion of linking to the docs below, the user can find the suggestion with a more complete explanation in there, which I think is better.

Code after:
    return fixturefunc


def pytest_fixture_setup(
    fixturedef: FixtureDef[FixtureValue], request: SubRequest
) -> FixtureValue:
    """Execution of fixture setup."""
    kwargs = {}
    for argname in fixturedef.argnames:
        kwargs[argname] = request.getfixturevalue(argname)

    fixturefunc = resolve_fixture_function(fixturedef, request)
    my_cache_key = fixturedef.cache_key(request)

    if inspect.isasyncgenfunction(fixturefunc) or inspect.iscoroutinefunction(
        fixturefunc
    ):
        auto_str = " with autouse=True" if fixturedef._autouse else ""

        warnings.warn(
            PytestRemovedIn9Warning(
                f"{request.node.name!r} requested an async fixture "
                f"{request.fixturename!r}{auto_str}, with no plugin or hook that "
                "handled it. This is usually an error, as pytest does not natively "
                "support it. "
                "This will turn into an error in pytest 9.\n"
                "See: https://docs.pytest.org/en/stable/deprecations.html#sync-test-depending-on-async-fixture"
            ),
            # no stacklevel will point at users code, so we just point here
            stacklevel=1,
        )

    try:
        result = call_fixture_func(fixturefunc, request, kwargs)
    except TEST_OUTCOME as e:
        if isinstance(e, skip.Exception):
            # The test requested a fixture which caused a skip.
            # Don't show the fixture as the skip location, as then the user
            # wouldn't know which test skipped.
            e._use_item_location = True
        fixturedef.cached_result = (None, my_cache_key, (e, e.__traceback__))
        raise
    fixturedef.cached_result = (result, my_cache_key, None)
    return result


def wrap_function_to_error_out_if_called_directly(
    function: FixtureFunction,
    fixture_marker: FixtureFunctionMarker,
) -> FixtureFunction:
    """Wrap the given fixture function so we can raise an error about it being called directly,