Skip to content

Commit

Permalink
fix: always treat param fixtures as new
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey committed Sep 26, 2024
1 parent f2c8708 commit 518d04b
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 64 deletions.
54 changes: 3 additions & 51 deletions src/ape/pytest/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from dataclasses import dataclass, field
from fnmatch import fnmatch
from functools import cached_property, singledispatchmethod
from typing import Optional, ClassVar
from typing import ClassVar, Optional

import pytest
from eth_utils import to_hex
Expand All @@ -25,11 +25,11 @@ class FixtureManager:
_builtin_fixtures: ClassVar[list] = []
_nodeid_to_fixture_map: dict[str, "FixtureMap"] = {}

def _get_builtin_fixtures(self, item) -> list[str]:
def get_builtin_fixtures(self, item) -> list[str]:
if self._builtin_fixtures:
return self._builtin_fixtures

self._builtin_fixtures = [
FixtureManager._builtin_fixtures = [
fixture_name
for fixture_name, defs in item.session._fixturemanager._arg2fixturedefs.items()
if any("pytest" in fixture.func.__module__ for fixture in defs)
Expand All @@ -44,54 +44,6 @@ def get_fixtures(self, item):
self._nodeid_to_fixture_map[item.nodeid] = item
return fixture_map

def is_last_fixture_iteration(self, item) -> bool:
"""
``True`` when is the last from all the parametrized fixtures.
"""
fixtures = self.get_fixtures(item)
parametrized_fixtures = fixtures.parametrized
if not parametrized_fixtures:
# When not using parametrized fixtures, it's always the last.
return True

return all(_get_last_fixture_iteration())
for name, info_ls in parametrized_fixtures.items():
for info in info_ls:


#
# """
# for name, info_ls in self.parametrized.items():
# for info in info_ls:
# if (
# info.cached_result is None
# or len(info.cached_result) < 2
# or info.cached_result[1] != info.params[-1]
# ):
# return False
#
# # All parametrized fixtures used are on their last iteration for this item.
# return True


def _is_last_iteration(fixture_info) -> bool:
"""
Returns True when is the last iteration of this fixture.
"""
return _get_previous_iteration(fixture_info) == len(fixture_info.params)


def _get_previous_iteration(fixture_info) -> int:
"""
The last iteration of the fixture. Assume we know it's a parametrized
fixture.
"""
cached_result = fixture_info.cached_result
if cached_result is None:
return -1 # Hasn't happened yet.

return cached_result[1]


class FixtureMap(dict[Scope, list[str]]):
def __init__(self, item):
Expand Down
18 changes: 6 additions & 12 deletions src/ape/pytest/runners.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from ape.logging import LogLevel
from ape.pytest.config import ConfigWrapper
from ape.pytest.coverage import CoverageTracker
from ape.pytest.fixtures import IsolationManager, PytestApeFixtures, ReceiptCapture, FixtureManager
from ape.pytest.fixtures import FixtureManager, IsolationManager, PytestApeFixtures, ReceiptCapture
from ape.pytest.gas import GasTracker
from ape.pytest.utils import Scope
from ape.types.coverage import CoverageReport
Expand Down Expand Up @@ -160,35 +160,29 @@ def pytest_runtest_setup(self, item):
return

fixtures = self.fixture_manager.get_fixtures(item)
builtins = self.fixture_manager.get_builtin_fixtures(item)
for scope in (Scope.SESSION, Scope.PACKAGE, Scope.MODULE, Scope.CLASS):
custom_fixtures = [
f
for f in fixtures[scope]
if f not in self._ape_fixtures and f not in fixtures.builtins
f for f in fixtures[scope] if f not in self._ape_fixtures and f not in builtins
]
if not custom_fixtures:
# Intermediate scope isolations aren't filled in, or only using
# built-in Ape fixtures.
continue

snapshot = self.isolation_manager.get_snapshot(scope)
is_last_iteration = fixtures.is_last_iteration

# Gather new fixtures. Also, be mindful of parametrized fixtures
# which strangely have the same name.
new_fixtures = []
for custom_fixture in custom_fixtures:
# Parametrized fixtures must always be considered new
# because of severe complications of using them.
is_parametrized = custom_fixture in fixtures.parametrized
if not is_parametrized and custom_fixture not in snapshot.fixtures:
# Is simply a new a fixture.
if custom_fixture not in snapshot.fixtures or is_parametrized:
new_fixtures.append(custom_fixture)
continue

elif is_parametrized and is_last_iteration:
pass
# elif not is_last_iteration and custom_fixture in fixtures.parametrized:
# new_fixtures.append(custom_fixture)

# Check for fixtures that are now invalid. For example, imagine a session
# fixture comes into play after the module snapshot has been set.
# Once we restore the module's state and move to the next module,
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/cli/test_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ def test_test(setup_pytester, integ_project, pytester, eth_tester_provider):
if integ_project.name == "test":
# Correct tests being added from parametrized fixtures
# TODO: Find better way to do this.
passed += 10
passed += 12

from ape.logging import logger

Expand Down

0 comments on commit 518d04b

Please sign in to comment.