Skip to content

de-emphasize request.addfinalizer Fixes #5587 #5589

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 16, 2019

Conversation

graingert
Copy link
Member

@graingert graingert commented Jul 10, 2019

  • Target the master branch for bug fixes, documentation updates and trivial changes.
  • Target the features branch for new features and removals/deprecations.
  • Include documentation when adding new features.
  • Include new tests or update existing tests when applicable.

Unless your change is trivial or a small documentation fix (e.g., a typo or reword of a small section) please:

  • Create a new changelog file in the changelog folder, with a name like <ISSUE NUMBER>.<TYPE>.rst. See changelog/README.rst for details.
  • Add yourself to AUTHORS in alphabetical order;

Fixes #5587

@graingert graingert force-pushed the fixture-yield-exit-stack branch from ee65393 to 27516bd Compare July 10, 2019 13:50
@codecov
Copy link

codecov bot commented Jul 10, 2019

Codecov Report

Merging #5589 into master will decrease coverage by <.01%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #5589      +/-   ##
==========================================
- Coverage   96.12%   96.11%   -0.01%     
==========================================
  Files         117      117              
  Lines       25733    25775      +42     
  Branches     2493     2495       +2     
==========================================
+ Hits        24735    24773      +38     
- Misses        695      697       +2     
- Partials      303      305       +2
Impacted Files Coverage Δ
src/_pytest/pathlib.py 87.89% <0%> (-1.19%) ⬇️
testing/test_tmpdir.py 98.52% <0%> (+0.21%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2c402f4...a96710d. Read the comment docs.

@graingert graingert force-pushed the fixture-yield-exit-stack branch from 27516bd to c224c4f Compare July 10, 2019 13:52
@graingert graingert changed the title de-emphasize request.addfinalizer de-emphasize request.addfinalizer Fixes #5587 Jul 10, 2019
@graingert
Copy link
Member Author

I'm not keen on deprecating/removing addfinalizer though. Are there usecases for addfinalizer that ExitStack cannot provide?

@RonnyPfannschmidt
Copy link
Member

addfinalizer can be implemented in terms of adding a callback to a stack

it would be interesting if there was a per usage scope fixture for eexit stacks,

then each fixture could get a very own exit stack in a well expressed manner (and if each fixture had one, it wouldnt be as bad to expose it)



@pytest.fixture
def equipments():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is worth adding at all, request.addfinalizer is actually more concise:

    @pytest.fixture
    def equipments(request):        
        r = []
        for port in ("C1", "C3", "C28"):
            equip = connect(port)
            request.addfinalizer(equip.disconnect)
            r.append(equip)
        yield r

Given that we definitely won't deprecate request.addfinalizer, I don't see much value in adding this particular example TBH. 🤔

Copy link
Member Author

@graingert graingert Jul 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's more concise in this particular case but it doesn't let you use layered resources or mix contexts and callbacks.

ExitStack would be more concise considering realistically connect will return a context manager

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ExitStack would be more concise considering realistically connect will return a context manager

Can you update the example to make use of this then? I believe it would then make more sense.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Member

@nicoddemus nicoddemus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update the example so it uses with statement for the connections too; this way the example will make more sense as an alternative to addfinalizer. 👍

Thanks!

request.addfinalizer(equip.disconnect)
cm = connect(port)
equip = cm.__enter__()
request.addfinalizer(functools.partial(cm.__exit__, None, None, None))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤢 now this is why ExitStack is so great

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah, for context managers then ExitStack is definitely the superior alternative. Do you think it is worth it thought to add this example like this? I'm afraid users might get confused by it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm tempted to remove docs for addfinalizer entirely

Copy link
Member Author

@graingert graingert Jul 15, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a go at removing all pytest's own calls to .addfinalizer and replacing them with plain yield fixtures, and replacing it with either layered resource acquisition or an ExitStack. And it looks much nicer.

It's quite a big change, doesn't really gain anything, and I got bored half way and gave up - but it just demonstrates the superiority of the yield fixture + ExitStack approach.

If we actually want to go ahead and deprecate addfinalizer then it would obviously be worth removing our own uses of it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree, it is part of the official API and should be in the docs, even if it is not the best alternative for all cases. People might be maintaining old test suites which use addfinalizer, and they might need the docs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW request.addfinalizer is also still (AFAIK) the only way to do cleanups from inside a test (rather than a fixture).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

def test_something():
    with contextlib.ExitStack as stack:
        setup_something()
        stack.callback(cleanup_something)
        assert sut()

@graingert
Copy link
Member Author

@nicoddemus should I hit "Merge pull request" ? :shipit:

@nicoddemus
Copy link
Member

Sure, go ahead! 👍

@graingert graingert merged commit 7440cec into pytest-dev:master Jul 16, 2019
@graingert graingert deleted the fixture-yield-exit-stack branch July 16, 2019 17:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

De-emphaze addfinalizer in favour of ExitStack
4 participants