litestar-org/polyfactory

Bug: Custom Random instance passed to __random__ does not get passed to list/set fields

TheGrandmother opened this issue · 1 comments

Description

I ham having issues running polyfactory with the property based testing library hypothesis.
Hypothesis will get angry and throw warnings if one calls the random module from within a test or strategy as this breaks some aspect of hypothesis.

But hypothesis provides a method for getting an instance of the Random and just supplying that to the __random__ field on a polyfactory class solves the issue.

But, lo and behold, out of somewhere the warning started popping up again. After some dissection i found that it showed up in models that had fields with collections like list or set. It appears that the instance of Random is not propagated to the factory for the "inner type"/argument for the collection.

URL to code causing the issue

No response

MCVE

class A(BaseModel):
    x: str


class B(BaseModel):
    x: list[A]


class C(BaseModel):
    x: A


@st.composite
def factory_strat(draw):
    class Factory(ModelFactory[B]):
        __random__ = draw(st.randoms()) # Returns a nice instance of Random

    return Factory.build()


@given(factory_strat())
def test_something(f):
    pass

Steps to reproduce

When ran in pytest with hypothesis warnings will be emitted that the random module is being used.

If I let the factory extend A or C instead the warning does not get emitted as polyfactory appears to be using the special Random instance generated by st.randoms.

Screenshots

No response

Logs

No response

Release Version

2.16.0

Platform

  • Linux
  • Mac
  • Windows
  • Other (Please specify in the description above)

Note

While we are open for sponsoring on GitHub Sponsors and
OpenCollective, we also utilize Polar.sh to engage in pledge-based sponsorship.

Check out all issues funded or available for funding on our Polar.sh dashboard

  • If you would like to see an issue prioritized, make a pledge towards it!
  • We receive the pledge once the issue is completed & verified
  • This, along with engagement in the community, helps us know which features are a priority to our users.
Fund with Polar

Thanks for the detailed report! Really helpful. I'm able to reproduce with

from hypothesis import given
from hypothesis import strategies as st
from pydantic import BaseModel

from polyfactory.factories.pydantic_factory import ModelFactory


class A(BaseModel):
    x: str


class B(BaseModel):
    x: list[A]


class C(BaseModel):
    x: A


@st.composite
def factory_strat(draw):
    class Factory(ModelFactory[B]):
        __random__ = draw(st.randoms())  # Returns a nice instance of Random

    return Factory.build()


@given(factory_strat())
def test_something(f: B):
    pass

PRs welcome to fix.