Skip to content

Commit a193944

Browse files
authored
Update call_fixture() to work with pytest 8.4. (#166)
Internally the unit tests for pytester access pytest fixtures directly. This has been [deprecated since 4.x](https://docs.pytest.org/en/stable/deprecations.html#calling-fixtures-directly), but the project currently contains some workarounds (in `call_fixture()`) to do this anyway. In pytest 8.4, the internals changed which breaks the way `call_fixture()` accesses the underlying fixture. This PR: - Updates `call_fixture()` minimally so that it also works with 8.4+. - Adds a marker that we should fix this properly. - Notes a promising direction for doing what we want in a supported manner. Resolves #165.
1 parent 4ae6499 commit a193944

File tree

1 file changed

+23
-7
lines changed
  • src/databricks/labs/pytester/fixtures

1 file changed

+23
-7
lines changed

src/databricks/labs/pytester/fixtures/unwrap.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
from typing import TypeVar
66
from unittest.mock import MagicMock, create_autospec
77

8+
import pytest
9+
810
from databricks.labs.lsql.backends import MockBackend
911
from databricks.sdk import WorkspaceClient
1012
from databricks.sdk.service import iam
@@ -14,13 +16,27 @@
1416
T = TypeVar('T')
1517

1618

17-
def call_fixture(fixture_fn: Callable[..., T], *args, **kwargs) -> T:
18-
if not hasattr(fixture_fn, '__pytest_wrapped__'):
19-
raise ValueError(f'{fixture_fn} is not a pytest fixture')
20-
wrapped = getattr(fixture_fn, '__pytest_wrapped__')
21-
if not hasattr(wrapped, 'obj'):
22-
raise ValueError(f'{fixture_fn} is not a pytest fixture')
23-
return wrapped.obj(*args, **kwargs)
19+
# Pytest fixtures are not supposed to be called directly, but historically we hack through the countermeasures.
20+
# TODO: Investigate and fix this if possible, to avoid breakage in future pytest versions.
21+
# Potential solution: use `pytest.FixtureRequest` & `request.getfixturevalue()` to access fixtures.
22+
if pytest.version_tuple >= (8, 4):
23+
24+
def call_fixture(fixture_fn: Callable[..., T], *args, **kwargs) -> T:
25+
if not hasattr(fixture_fn, "_get_wrapped_function"):
26+
raise ValueError(f'{fixture_fn} is not a pytest fixture')
27+
accessor = getattr(fixture_fn, "_get_wrapped_function")
28+
wrapped = accessor()
29+
return wrapped(*args, **kwargs)
30+
31+
else:
32+
# Older versions of pytest use a different mechanism to wrap fixtures.
33+
def call_fixture(fixture_fn: Callable[..., T], *args, **kwargs) -> T:
34+
if not hasattr(fixture_fn, '__pytest_wrapped__'):
35+
raise ValueError(f'{fixture_fn} is not a pytest fixture')
36+
wrapped = getattr(fixture_fn, '__pytest_wrapped__')
37+
if not hasattr(wrapped, 'obj'):
38+
raise ValueError(f'{fixture_fn} is not a pytest fixture')
39+
return wrapped.obj(*args, **kwargs)
2440

2541

2642
class CallContext:

0 commit comments

Comments
 (0)