fixtures: remove dirty optimization for request.getfixturevalue()#14290
fixtures: remove dirty optimization for request.getfixturevalue()#14290
request.getfixturevalue()#14290Conversation
|
Fixtures are cached per-test in |
|
@Anton3 Good point, so the perf con is actually not the case. I will amend the commit message. Aside on `_fixture_defs`
Speaking of import pytest
@pytest.fixture(scope='module')
def fix(): return "module"
@pytest.fixture() # scope='module' should also work
def modfix(fix): return fix
class TestIt:
@pytest.fixture
def fix(self): return "function"
def test_it(self, modfix):
assert modfix == "module"Currently it has |
Currently for each `Function` we copy the `FunctionDefinition`'s `_arg2fixturedefs`. This is done due to an ineffective optimization for a dynamic `request.getfixturevalue()` when the fixture name wasn't statically requested. In this case, we would save the dynamically-found `FixtureDef` in `_arg2fixturedef`, such that if it is requested again in the same item, it is returned immediately instead of doing a `_matchfactories` check again. But this case is already covered by the `_fixture_defs` optimization. I've always disliked this copy and mutation. The `_arg2fixturedefs` shenanigans performed during collection are hard enough to follow, and this only adds to the complexity, due to the mutability and having multiple different `_arg2fixturedefs` with different contents. So summing up: Pros: faster repeated `request.getfixturevalue()` in same test (ineffective) Cons: complexity (reasoning about mutability), extra copy Even without the `_fixture_defs` optimization, since `request.getfixturevalue()` is mostly a last-resort thing, so shouldn't be too common, and *repeated* calls to it in the same test should be even less common, and if so `_matchfactories` shouldn't be *that* slow, it should be fine to remove it.
d068e14 to
af80fa5
Compare
That's probably due to faulty logic in |
#14104 doesn't touch the Just as an experiment, I did try now to comment out the (Note: I just noticed that even with commenting out |
Currently for each
Functionwe copy theFunctionDefinition's_arg2fixturedefs. This is done due to an ineffective optimization fora dynamic
request.getfixturevalue()when the fixture name wasn'tstatically requested. In this case, we would save the dynamically-found
FixtureDefin_arg2fixturedef, such that if it is requested again inthe same item, it is returned immediately instead of doing a
_matchfactoriescheck again. But this case is already covered by the_fixture_defsoptimization.I've always disliked this copy and mutation. The
_arg2fixturedefsshenanigans performed during collection are hard enough to follow, and
this only adds to the complexity, due to the mutability and having
multiple different
_arg2fixturedefswith different contents.So summing up:
Pros: faster repeated
request.getfixturevalue()in same test (ineffective)Cons: complexity (reasoning about mutability), extra copy
Even without the
_fixture_defsoptimization, sincerequest.getfixturevalue()is mostly a last-resort thing, so shouldn'tbe too common, and repeated calls to it in the same test should be
even less common, and if so
_matchfactoriesshouldn't be that slow,it should be fine to remove it.