Fixed PrivateAttr defaults ignored on database-loaded instances#1818
Fixed PrivateAttr defaults ignored on database-loaded instances#1818xr843 wants to merge 3 commits intofastapi:mainfrom
Conversation
When SQLAlchemy reconstructs a model instance from a database query (bypassing __init__), it goes through __new__ which calls init_pydantic_private_attrs(). That function was setting __pydantic_private__ = None instead of initializing it with the private attribute defaults. This caused AttributeError when accessing PrivateAttr fields on database-loaded instances. The fix introspects the class's __private_attributes__ dict and calls get_default() on each entry, mirroring what Pydantic's own __init__ does. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@xr843, please, review and test changes before opening PR for review |
- Used getattr() instead of direct attribute access to satisfy mypy's union-attr check on InstanceOrType. - Added regression tests verifying PrivateAttr with default and default_factory work correctly on database-loaded instances. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Thank you for the feedback @YuriiMotov. I've addressed the issues:
Both tests confirm the fix resolves the Ready for re-review when you have a chance. |
Please review the CI errors as well. |
Pydantic 2.x's ModelPrivateAttr.get_default() takes no arguments and handles both default and default_factory internally. Removed the call_default_factory=True kwarg that caused TypeError on Pydantic >=2.11. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@svlandeg Thank you for the reminder. I've reviewed the CI errors. All code quality checks are passing: tests (all matrix combinations), pre-commit, coverage (99%), and docs. The only failing check is |
Summary
Fixes #149
__init__), it calls__new__which invokesinit_pydantic_private_attrs(). That function was setting__pydantic_private__ = Noneinstead of initializing it with the private attribute defaults.AttributeErrorwhen accessingPrivateAttrfields on database-loaded instances.__private_attributes__dict and callsget_default()on each entry to properly initialize__pydantic_private__, mirroring what Pydantic's ownBaseModel.__init__does.Test plan
PrivateAttr(default=...)fieldsAttributeError🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com