We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
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
ModelSQLAlchemyFactory.build() fails on SQLAlchemy models with a constrained, optional field, e.g., mapped_column(String(10), nullable=True).
ModelSQLAlchemyFactory.build()
mapped_column(String(10), nullable=True)
With nullable=False, no exception is raised.
nullable=False
The bug may have been introduced by #594 that has just been released (2024.11.06 - v2.18.0).
No response
from polyfactory.factories.sqlalchemy_factory import SQLAlchemyFactory from sqlalchemy import Integer, String from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column class Base(DeclarativeBase): pass class MyModel(Base): __tablename__ = "my_model" id: Mapped[int] = mapped_column(Integer, primary_key=True) name: Mapped[str | None] = mapped_column(String(10), nullable=True) class MyModelFactory(SQLAlchemyFactory[MyModel]): __model__ = MyModel MyModelFactory.build()
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[5], line 20 16 class MyModelFactory(SQLAlchemyFactory[MyModel]): 17 __model__ = MyModel ---> 20 MyModelFactory.build() File ~/toy-project/.venv/lib/python3.12/site-packages/polyfactory/factories/base.py:1080, in BaseFactory.build(cls, **kwargs) 1071 @classmethod 1072 def build(cls, **kwargs: Any) -> T: 1073 """Build an instance of the factory's __model__ 1074 1075 :param kwargs: Any kwargs. If field names are set in kwargs, their values will be used. (...) 1078 1079 """ -> 1080 return cast("T", cls.__model__(**cls.process_kwargs(**kwargs))) File ~/toy-project/.venv/lib/python3.12/site-packages/polyfactory/factories/base.py:980, in BaseFactory.process_kwargs(cls, **kwargs) 977 result: dict[str, Any] = {**kwargs} 978 generate_post: dict[str, PostGenerated] = {} --> 980 for field_meta in cls.get_model_fields(): 981 field_build_parameters = cls.extract_field_build_parameters(field_meta=field_meta, build_args=kwargs) 982 if cls.should_set_field_value(field_meta, **kwargs) and not cls.should_use_default_value(field_meta): File ~/toy-project/.venv/lib/python3.12/site-packages/polyfactory/factories/sqlalchemy_factory.py:196, in SQLAlchemyFactory.get_model_fields(cls) 193 fields_meta: list[FieldMeta] = [] 195 table: Mapper = inspect(cls.__model__) # type: ignore[assignment] --> 196 fields_meta.extend( 197 FieldMeta.from_type( 198 annotation=cls.get_type_from_column(column), 199 name=name, 200 random=cls.__random__, 201 ) 202 for name, column in table.columns.items() 203 if cls.should_column_be_set(column) 204 ) 205 if cls.__set_relationships__: 206 for name, relationship in table.relationships.items(): File ~/toy-project/.venv/lib/python3.12/site-packages/polyfactory/factories/sqlalchemy_factory.py:197, in <genexpr>(.0) 193 fields_meta: list[FieldMeta] = [] 195 table: Mapper = inspect(cls.__model__) # type: ignore[assignment] 196 fields_meta.extend( --> 197 FieldMeta.from_type( 198 annotation=cls.get_type_from_column(column), 199 name=name, 200 random=cls.__random__, 201 ) 202 for name, column in table.columns.items() 203 if cls.should_column_be_set(column) 204 ) 205 if cls.__set_relationships__: 206 for name, relationship in table.relationships.items(): File ~/toy-project/.venv/lib/python3.12/site-packages/polyfactory/field_meta.py:153, in FieldMeta.from_type(cls, annotation, random, name, default, constraints, randomize_collection_length, min_collection_length, max_collection_length, children) 142 annotation = container[get_args(annotation)] # type: ignore[index] 144 field = cls( 145 annotation=annotation, 146 random=random, (...) 150 constraints=constraints, 151 ) --> 153 if field.type_args and not field.children: 154 field.children = [ 155 cls.from_type( 156 annotation=unwrap_new_type(arg), (...) 160 if arg is not NoneType 161 ] 162 return field File ~/toy-project/.venv/lib/python3.12/site-packages/polyfactory/field_meta.py:96, in FieldMeta.type_args(self) 90 @property 91 def type_args(self) -> tuple[Any, ...]: 92 """Return the normalized type args of the annotation, if any. 93 94 :returns: a tuple of types. 95 """ ---> 96 return tuple(TYPE_MAPPING.get(arg, arg) for arg in get_args(self.annotation)) File ~/toy-project/.venv/lib/python3.12/site-packages/polyfactory/field_meta.py:96, in <genexpr>(.0) 90 @property 91 def type_args(self) -> tuple[Any, ...]: 92 """Return the normalized type args of the annotation, if any. 93 94 :returns: a tuple of types. 95 """ ---> 96 return tuple(TYPE_MAPPING.get(arg, arg) for arg in get_args(self.annotation)) File /usr/lib/python3.12/typing.py:2023, in _AnnotatedAlias.__hash__(self) 2022 def __hash__(self): -> 2023 return hash((self.__origin__, self.__metadata__)) TypeError: unhashable type: 'dict'
v2.18.0
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
The text was updated successfully, but these errors were encountered:
Successfully merging a pull request may close this issue.
Description
ModelSQLAlchemyFactory.build()
fails on SQLAlchemy models with a constrained, optional field, e.g.,mapped_column(String(10), nullable=True)
.With
nullable=False
, no exception is raised.The bug may have been introduced by #594 that has just been released (2024.11.06 - v2.18.0).
URL to code causing the issue
No response
MCVE
Steps to reproduce
No response
Screenshots
No response
Logs
Release Version
v2.18.0
Platform
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
The text was updated successfully, but these errors were encountered: