Skip to content

Expose FixtureFunctionDefinition as part of the public API #14853

Description

@adamtheturtle

There doesn’t appear to be a public type that can be used to annotate the result of pytest.fixture.

For example, consider a factory which creates fixtures:

from _pytest.fixtures import FixtureFunctionDefinition

def make_fixture(value: str) -> FixtureFunctionDefinition:
    @pytest.fixture
    def fixture() -> str:
        return value
    return fixture

Activity

  1. teddygood commented on Aug 11, 2026

    @teddygood

    I'd like to work on this. Could you assign it to me?

  2. Gugilla-Aakash commented on Aug 19, 2026

    @Gugilla-Aakash

    Hi! I’d be interested in working on this issue. My initial thought is to expose FixtureFunctionDefinition through a supported public API (possibly from pytest), along with the necessary typing/tests, rather than requiring users to import it from the private _pytest.fixtures module.

    I noticed it’s currently assigned to @teddygood, so I wanted to check whether they’re actively working on it. If not, I’d be happy to take this on and submit a PR.

  3. siddy-stack commented on Aug 19, 2026

    @siddy-stack

    Is this issue being worked upon? If so not, Please assign

  4. Pierre-Sassoulas commented on Aug 19, 2026

    @Pierre-Sassoulas
    Member

    There's an open PR by @teddygood from last week (you could check yourself on the side instead of asking).

    Image
  5. teddygood commented on Aug 19, 2026

    @teddygood

    @Gugilla-Aakash @siddy-stack Thanks for your interest. But I’m currently working on this, and there’s already an open PR for it.

  6. bluetech commented on Aug 20, 2026

    @bluetech
    Member

    Exposing this type has downsides: it locks an implementation detail, and increases the API surface. So my first inclination is to see how we can avoid exposing this.

    @adamtheturtle use case seems valid, though I'd be interesting in a bit more details, I'm assuming the example given is not the real one.

    But either case, the reason @adamtheturtle needs FixtureFunctionDefinition is because pytest.fixture returns it. But pytest core itself doesn't need this return type, it of course has no access to @pytest.fixture return value directly, it only sees it later during collection where of course it relies on the runtime type, not the static type.

    So perhaps we can undo the part of ecde993 that changes the return type of pytest.fixture. It doesn't matter to pytest core (as explained above), nor to users (since FixtureFunctionDefinition is private anyway, and they just need the type to be correct). In order for the types to match with the wrapper, we would need to revive the ParamSpec part from #13036.

  7. RonnyPfannschmidt commented on Aug 20, 2026

    @RonnyPfannschmidt
    Member

    I think i want to introduce a opaque protocol for this

  8. adamtheturtle commented on Aug 20, 2026

    @adamtheturtle
    Author

    @bluetech I am the maintainer of vws-python-mock. It has a test suite where a bunch of tests are written once and run against a real web service, as well as a mock, and another mock. Each of these "backends" has its own setup and teardown, so I use fixtures. https://github.com/VWS-Python/vws-python-mock/blob/7ca1c36f03f38784389b4a02628cb095016ec25a/tests/backend_harness.py#L116-L159 is the function which wants this exposed.

  9. bluetech commented on Aug 20, 2026

    @bluetech
    Member

    @adamtheturtle Thanks, yeah that's perfectly reasonable.

  10. bluetech commented on Aug 20, 2026

    @bluetech
    Member

    I think i want to introduce a opaque protocol for this

    Is there a benefit for this over returning the type of the input function with a generic? (To be clear, everything with FixtureFunctionDefinition will remain the same, I'm talking only about pytest.fixture static type)

  11. RonnyPfannschmidt commented on Aug 20, 2026

    @RonnyPfannschmidt
    Member

    The exposure we started with the _ispytest types locks concrete types in a lot of places

    When i started to experiment with the ensemble apis I got a more concrete need to replace objects and being locked in

  12. bluetech commented on Aug 20, 2026

    @bluetech
    Member

    How does _ispytest lock a concrete type? The intention (along with @final) was the opposite, to prevent constructing such that among other things it can be replaced entirely (including with a protocol if needed, though TBH I don't see a benefit for a protocol in such cases).

  13. RonnyPfannschmidt commented on Aug 20, 2026

    @RonnyPfannschmidt
    Member

    the exported name is in type annotations and its a concrete type instead of a shape

    makes creating fakes/stand-ins and/or wrappers a mess

  14. bluetech commented on Aug 20, 2026

    @bluetech
    Member

    Premature abstraction is the root of all evil :) Though there is nothing precluding replacing protected concrete types with ABCs or protocols.

    But how does this apply to this case? The purpose of FixtureFunctionDefinition is to mark a function as a fixture definition for collection, and we use isinstance(obj, FixtureFunctionDefinition) for this. What would a protocol replacement look like?

  15. bobbapranay2006 commented on Sep 22, 2026

    @bobbapranay2006

    Hi! I'd like to work on this issue as my first contribution to pytest.

  16. Pierre-Sassoulas commented on Sep 22, 2026

    @Pierre-Sassoulas
  17. DevarthRaj commented on Sep 27, 2026

    @DevarthRaj

    Is this issue being fixed? If not , please assign this to me

  18. Pierre-Sassoulas commented on Sep 27, 2026

    @Pierre-Sassoulas
    Member

    You can see if there's open PR for it in the "Developement" part of the right status bar : Image (there are 3 duplicate already)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

good first issueeasy issue that is friendly to new contributortopic: fixturesanything involving fixtures directly or indirectly

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions