litestar-org/polyfactory

Support for generating the models with alias

alazaralemayehu opened this issue · 8 comments

Hello, thank you for your support. Is there a way to generate the pydantic fake models that contains aliases field.
For example,
class Person(Model): userName: str = Field(alias='user_name')

the current factory generates only using fieldName (userName), is it possible to create the generate models using alias name?

thank you.

Yes, there is a class variable for this. Checkout the docs.

did you find what you needed or is there an issue?

Hi, I'm trying to look for this as well. The ones I see on the docs are:

    __model__ = Person
    __faker__ = my_faker
    __sync_persistence__ = SyncPersistenceHandler
    __async_persistence__ = AsyncPersistenceHandler
    __allow_none_optionals__ = False

They don't seem to be related? It looks like it's also missing docs for __random_seed__.

Hi,

So currently there is a method on the factory that determines per field whether to use alias:

    @classmethod
    def _should_use_alias_name(cls, model_field: "ModelField", model: Type[T]) -> bool:
        """Determines whether a given model field should be set by an alias.

        Args:
            model_field: A 'ModelField' instance.
            model: A model class.

        Returns:
            A boolean determining whether the field alias should be used.
        """
        return bool(model_field.alias) and not (
            issubclass(model, BaseModel) and model.__config__.allow_population_by_field_name
        )

What are you guys looking for to have?

I was trying to look at that, but (model, BaseModel) and model.__config__.allow_population_by_field_name is always true. I'm not sure if I'm missing any additional configs.

class Person(Model):
    user_name: str = Field(alias='username')

class PersonFactory(ModelFactory):
    __model__ = Person

x = PersonFactory.build() # I want it to be built with alias, so with `username` instead of `user_name`

Is that possible?

I was trying to look at that, but (model, BaseModel) and model.__config__.allow_population_by_field_name is always true. I'm not sure if I'm missing any additional configs.

class Person(Model):
    user_name: str = Field(alias='username')

class PersonFactory(ModelFactory):
    __model__ = Person

x = PersonFactory.build() # I want it to be built with alias, so with `username` instead of `user_name`

Is that possible?

You can pass a dict of values with username. I will have to look into the other part.

I am sorry for touching a closed issue, but @Goldziher you closed this issue while the problem is still here and I do not see that this is documented

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


class Person(BaseModel):
    id: int = Field(alias="_id")


class PersonFactory(ModelFactory[Person]):
    __model__ = Person


person_instance = PersonFactory.build()

Error:

E       pydantic_core._pydantic_core.ValidationError: 1 validation error for Person
E       _id
E         Field required [type=missing, input_value={}, input_type=dict]
E           For further information visit https://errors.pydantic.dev/2.1/v/missing

.venv/lib/python3.11/site-packages/polyfactory/factories/pydantic_factory.py:334: ValidationError

Should I create a new issue?


UPDATE

Solved by populate_by_name in the model itself. But this is a bad workaround because I need to modify the source code to make tests happy. Ugly workaround example:

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

# Application code
class Person(BaseModel):
    id: int = Field(alias="_id")

# Tests code
class PersonTest(Person):
    model_config = ConfigDict(populate_by_name=True)


class PersonFactory(ModelFactory[PersonTest]):
    __model__ = PersonTest

I am sorry for touching a closed issue, but @Goldziher you closed this issue while the problem is still here and I do not see that this is documented

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


class Person(BaseModel):
    id: int = Field(alias="_id")


class PersonFactory(ModelFactory[Person]):
    __model__ = Person


person_instance = PersonFactory.build()

Error:

E       pydantic_core._pydantic_core.ValidationError: 1 validation error for Person
E       _id
E         Field required [type=missing, input_value={}, input_type=dict]
E           For further information visit https://errors.pydantic.dev/2.1/v/missing

.venv/lib/python3.11/site-packages/polyfactory/factories/pydantic_factory.py:334: ValidationError

Should I create a new issue?


UPDATE

Solved by populate_by_name in the model itself. But this is a bad workaround because I need to modify the source code to make tests happy. Ugly workaround example:

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

# Application code
class Person(BaseModel):
    id: int = Field(alias="_id")

# Tests code
class PersonTest(Person):
    model_config = ConfigDict(populate_by_name=True)


class PersonFactory(ModelFactory[PersonTest]):
    __model__ = PersonTest

You're welcome to create a bug report with a reproduction