Skip to content
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

Bug: Support custom types providers for which there already exists a registered base factory #607

Open
1 of 4 tasks
mjmaurer opened this issue Nov 22, 2024 · 2 comments
Open
1 of 4 tasks
Labels
bug Something isn't working

Comments

@mjmaurer
Copy link

mjmaurer commented Nov 22, 2024

Description

It seems like defining a type in get_provider_map(cls) wouldn't work if that type is already handled by an existing base_factory (such as dataclass, Pydantic model, etc).

It's possible this is intended, as the Handling Custom Types docs only specifies a plain-old Python class CustomSecret.

Please see the MCVE below for what my desired behavior would be. Is this currently possible? I've tried playing around with __base_factory_overrides__ but didn't have any luck.

URL to code causing the issue

No response

MCVE

from pydantic import BaseModel, ConfigDict
from polyfactory.factories.pydantic_factory import ModelFactory

class CustomSecretPydantic(BaseModel):
    value: str


class CustomSecretPlain:
    def __init__(self, value: str) -> None:
        self.value = value

    def __repr__(self) -> str:
        return self.value

    def __str__(self) -> str:
        return self.value


class MyModel(BaseModel):
    model_config = ConfigDict(arbitrary_types_allowed=True)

    id: int
    secret: CustomSecretPydantic


class MyFactory(ModelFactory[MyModel]):

    @classmethod
    def get_provider_map(cls) -> dict[type, Any]:
        providers_map = super().get_provider_map()

        return {
            **providers_map,
            CustomSecretPydantic: lambda: CustomSecretPydantic.model_validate({"value": "asdf"}),
            CustomSecretPlain: lambda: CustomSecretPlain(value="asdf"),
        }


if __name__ == "__main__":

    print(MyFactory.build())

Steps to reproduce

1. Run code
2. Observe that "asdf" is NOT generated

I'd expect that it would be.

Screenshots

"In the format of: ![SCREENSHOT_DESCRIPTION](SCREENSHOT_LINK.png)"

Logs

No response

Release Version

2.17.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
@mjmaurer mjmaurer added the bug Something isn't working label Nov 22, 2024
@adhtruong
Copy link
Collaborator

Hi @mjmaurer ,

Looks like this currently isn't possible but PRs welcome to fix.

Couple of potential workarounds

  • Set this at the field level.
  • Create a separate factory that targets this model only and register as default type, e.g. something like
class CustomSecretPydantic(ModelFactory[CustomSecretPydantic]):
      __set_as_default_factory_for_type__ = True

     @classmethod
     def process_kwargs(cls, **kwargs: Any) -> dict[str, Any]:
           return {"value": "asdf"}

@mjmaurer
Copy link
Author

Thanks, the latter option worked perfectly!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants