From fdc1b10b61e3b3880191e8d4b440a1b9fc035d78 Mon Sep 17 00:00:00 2001 From: Sadra Barikbin Date: Tue, 1 Aug 2023 21:24:10 +0330 Subject: [PATCH] Apply comments --- src/_pytest/fixtures.py | 36 ++++++++++++++++---------- testing/python/fixtures.py | 52 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 13 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index f98f774c7..8882486b0 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -241,14 +241,24 @@ def getfixturemarker(obj: object) -> Optional["FixtureFunctionMarker"]: @dataclasses.dataclass(frozen=True) -class FixtureArgKey: +class FixtureArgKeyByIndex: argname: str - param_index: Optional[int] - param_value: Optional[Hashable] + param_index: int scoped_item_path: Optional[Path] item_cls: Optional[type] +@dataclasses.dataclass(frozen=True) +class FixtureArgKeyByValue: + argname: str + param_value: Hashable + scoped_item_path: Optional[Path] + item_cls: Optional[type] + + +FixtureArgKey = Union[FixtureArgKeyByIndex, FixtureArgKeyByValue] + + def get_parametrized_fixture_keys( item: nodes.Item, scope: Scope ) -> Iterator[FixtureArgKey]: @@ -268,13 +278,6 @@ def get_parametrized_fixture_keys( if cs._arg2scope[argname] != scope: continue - param_index: Optional[int] = cs.indices[argname] - param_value = cs.params[argname] - if isinstance(cs.params[argname], Hashable): - param_index = None - else: - param_value = None - item_cls = None if scope is Scope.Session: scoped_item_path = None @@ -288,9 +291,16 @@ def get_parametrized_fixture_keys( else: assert_never(scope) - yield FixtureArgKey( - argname, param_index, param_value, scoped_item_path, item_cls - ) + param_index = cs.indices[argname] + param_value = cs.params[argname] + if isinstance(param_value, Hashable): + yield FixtureArgKeyByValue( + argname, param_value, scoped_item_path, item_cls + ) + else: + yield FixtureArgKeyByIndex( # type: ignore[unreachable] + argname, param_index, scoped_item_path, item_cls + ) # Algorithm for sorting on a per-parametrized resource setup basis. diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 8fa5a4303..1e05bf4c4 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -12,6 +12,7 @@ from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import get_public_names from _pytest.pytester import Pytester from _pytest.python import Function +from _pytest.scope import Scope def test_getfuncargnames_functions(): @@ -4683,3 +4684,54 @@ def test_reorder_with_high_scoped_direct_and_fixture_parametrization( r" ", ] ) + + +def test_get_parametrized_fixture_keys_with_unhashable_params( + pytester: Pytester, +) -> None: + module = pytester.makepyfile( + """ + import pytest + + @pytest.mark.parametrize("arg", [[1], [2]], scope='module') + def test(arg): + pass + """ + ) + test_0, test_1 = pytester.genitems((pytester.getmodulecol(module),)) + test_0_keys = list(fixtures.get_parametrized_fixture_keys(test_0, Scope.Module)) + test_1_keys = list(fixtures.get_parametrized_fixture_keys(test_1, Scope.Module)) + assert len(test_0_keys) == len(test_1_keys) == 1 + assert isinstance(test_0_keys[0], fixtures.FixtureArgKeyByIndex) + assert test_0_keys[0].param_index == 0 + assert isinstance(test_1_keys[0], fixtures.FixtureArgKeyByIndex) + assert test_1_keys[0].param_index == 1 + + +def test_reordering_with_unhashable_parametrize_args(pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + + @pytest.mark.parametrize("arg", [[1], [2]], scope='module') + def test_1(arg): + print(arg) + + def test_2(): + print("test_2") + + @pytest.mark.parametrize("arg", [[3], [4]], scope='module') + def test_3(arg): + print(arg) + """ + ) + result = pytester.runpytest("-s") + result.stdout.fnmatch_lines( + [ + r"*1*", + r"*3*", + r"*2*", + r"*4*", + r"*test_2*", + ] + )