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

fix: Allow inheriting dataclasses with defaults #7184

Merged
merged 4 commits into from Aug 25, 2023

Conversation

tobni
Copy link
Contributor

@tobni tobni commented Aug 20, 2023

Change Summary

This patch allows for a pydantic.Basemodel class to inherit a "pure" stdlib dataclass, even when the attribute name is set on the class instance, as is the case with dataclasses.field and default assignments.

Related issue number

fix #6984

Checklist

  • The pull request title is a good summary of the changes - it will be used in the changelog
  • Unit tests for the changes exist
  • Tests pass on CI
  • Documentation reflects the changes where applicable
  • My PR is ready to review, please add a comment including the phrase "please review" to assign reviewers

Selected Reviewer: @hramezani

@tobni
Copy link
Contributor Author

tobni commented Aug 20, 2023

please review

@tobni
Copy link
Contributor Author

tobni commented Aug 22, 2023

Looks like #7193 addressed the immediate issue. I am however keen on letting the test and extra logic be reviewed and if ok to merge to avoid the warning and ensure compat.

Comment on lines +2503 to +2536
def test_can_inherit_stdlib_dataclasses_with_dataclass_fields():
@dataclasses.dataclass
class Base:
a: int = dataclasses.field(default=5)

class Model(BaseModel, Base):
pass

assert Model().a == 5
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also add a test for default_factory? I'm assuming it doesn't work?

Copy link
Contributor Author

@tobni tobni Aug 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adriangb I added a test that xfails. The internals of stdlib dataclasses does not assign default factory attributes to the class instance (meaning the warning isnt triggered in this case). It also means that you are right, the default factory is not propagated to the resulting FieldInfo instance (because the dataclass.Field isnt assigned to Base but rather Base.__dataclass_fields__.

@dataclasses.dataclass
class Base:
    a: int = dataclasses.field(default_factory=lambda: 5)

assert hasattr(Base, 'a')  # this fails

Copy link
Contributor Author

@tobni tobni Aug 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inheritance works fine if you provide a value, so for my usecase this isn't an important feature to support. I added a test for what we need to work, though.

@tobni tobni force-pushed the allow-dataclass-inheritance branch from 5135319 to 8056cc6 Compare August 25, 2023 09:51
Comment on lines 2516 to 2527
@pytest.mark.xfail(raises=ValidationError, require=True)
def test_can_inherit_stdlib_dataclasses_default_factories_and_use_them():
"""This test documents that default factories are not supported"""

@dataclasses.dataclass
class Base:
a: str = dataclasses.field(default_factory=lambda: 'TEST')

class Model(BaseModel, Base):
pass

assert Model().a == 'TEST'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather see with pytest.raises(...) since that's what we use elsewhere

@tobni
Copy link
Contributor Author

tobni commented Aug 25, 2023

@adriangb Done!

@tobni tobni requested a review from adriangb August 25, 2023 14:19
@tobni
Copy link
Contributor Author

tobni commented Aug 25, 2023

please review

@adriangb adriangb enabled auto-merge (squash) August 25, 2023 14:27
@adriangb adriangb merged commit ce51f5e into pydantic:main Aug 25, 2023
47 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow inheriting dataclasses.dataclass with defaults
4 participants