-
-
Notifications
You must be signed in to change notification settings - Fork 81
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
fix: properly resolve dataclass forward references #383
Conversation
Kudos, SonarCloud Quality Gate passed! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should #347 be re-opened?
Yeah I think so. For fixing these kinds of issues, I was thinking maybe we could have a |
I have to admit I'm not very familiar with polyfactory, so overall I'm inclined to follow your lead. I did take a quick look though and one thing that stands out is that each of the fields_meta.append(
FieldMeta.from_type(
annotation=annotation,
name=field.name,
default=default_value,
random=cls.__random__,
randomize_collection_length=cls.__randomize_collection_length__,
min_collection_length=cls.__min_collection_length__,
max_collection_length=cls.__max_collection_length__,
)
) Perhaps you could consider adding a class BaseFactory:
...
@classmethod
def create_field_meta(
cls,
annotation,
name,
default,
random=None,
randomize_collection_length=None,
min_collection_length=None,
max_collection_length=None,
) -> FieldMeta:
return FieldMeta.from_type(
annotation=annotation,
name=name,
default=default_value,
random=random or cls.__random__,
randomize_collection_length=randomize_collection_length or cls.__randomize_collection_length__,
min_collection_length=min_collection_length or cls.__min_collection_length__,
max_collection_length=max_collection_length or cls.__max_collection_length__,
) This would clean up the repetition of passing fields_meta.append(
cls.create_field_meta(
annotation=annotation,
name=field.name,
default=default_value,
)
) And would also provide a convenient place for sub-classes to intercept the annotation: class SQLAlchemyDCFactory(DataclassFactory):
@classmethod
def create_field_meta(cls, annotation, *args, **kwargs) -> FieldMeta:
annotation = unwrap_mapped_annotation(annotation)
return super().create_field_meta(annotation, *args, **kwargs) WDYT? |
I'm really like the idea of allowing the users to override the creation of the |
I'm going to merge this now and reopen that issue. I think we can move the discussion into there. |
There's a argument to do both, even if random=random or cls.__random__,
randomize_collection_length=randomize_collection_length or cls.__randomize_collection_length__,
min_collection_length=min_collection_length or cls.__min_collection_length__,
max_collection_length=max_collection_length or cls.__max_collection_length__, So it would be: class BaseFactory:
...
@classmethod
def _create_field_meta(
cls,
annotation,
name,
default,
random=None,
randomize_collection_length=None,
min_collection_length=None,
max_collection_length=None,
) -> FieldMeta:
return cls.__field_meta_cls__.from_type(
annotation=annotation,
name=name,
default=default_value,
random=random or cls.__random__,
randomize_collection_length=randomize_collection_length or cls.__randomize_collection_length__,
min_collection_length=min_collection_length or cls.__min_collection_length__,
max_collection_length=max_collection_length or cls.__max_collection_length__,
) However we are getting into the realms of personal preference now, so I'll back your decision from here 👍 |
Hm...I do understand your point about the reducing the duplication of passing the arguments to the field type, but I don't feel like it provides enough of an advantage that it warrants another layer of indirection/abstraction. However, I definitely liked your idea of allowing users to capture the annotation and override it in some if they wanted to. I think we should go ahead with the |
Pull Request Checklist
Description
This PR reverts #371 because the dataclasses
fields
API does not properly resolve the forward annotations as explained in this issue. For getting the resolved types, we have to useget_type_hints
though that doesn't work well with models likeMappedAsDataclass
ofsqlalchemy
. For those cases, it's probably better for users to subclass the currentDataclassFactory
implementation and handle them accordingly.Close Issue(s)
DataclassFactory
#382