Skip to content

Commit

Permalink
Keep values of private attributes set within model_post_init in sub…
Browse files Browse the repository at this point in the history
…classes (#7775)
  • Loading branch information
alexmojaki committed Oct 11, 2023
1 parent 5c21e7c commit 218b5ad
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 6 deletions.
13 changes: 7 additions & 6 deletions pydantic/_internal/_model_construction.py
Expand Up @@ -259,12 +259,13 @@ def init_private_attributes(self: BaseModel, __context: Any) -> None:
self: The BaseModel instance.
__context: The context.
"""
pydantic_private = {}
for name, private_attr in self.__private_attributes__.items():
default = private_attr.get_default()
if default is not PydanticUndefined:
pydantic_private[name] = default
object_setattr(self, '__pydantic_private__', pydantic_private)
if getattr(self, '__pydantic_private__', None) is None:
pydantic_private = {}
for name, private_attr in self.__private_attributes__.items():
default = private_attr.get_default()
if default is not PydanticUndefined:
pydantic_private[name] = default
object_setattr(self, '__pydantic_private__', pydantic_private)


def get_model_post_init(namespace: dict[str, Any], bases: tuple[type[Any], ...]) -> Callable[..., Any] | None:
Expand Down
32 changes: 32 additions & 0 deletions tests/test_main.py
Expand Up @@ -2021,6 +2021,38 @@ class C(B):
assert calls == ['C.model_post_init']


def test_model_post_init_subclass_setting_private_attrs():
"""https://github.com/pydantic/pydantic/issues/7091"""

class Model(BaseModel):
_priv1: int = PrivateAttr(91)
_priv2: int = PrivateAttr(92)

def model_post_init(self, __context) -> None:
self._priv1 = 100

class SubModel(Model):
_priv3: int = PrivateAttr(93)
_priv4: int = PrivateAttr(94)
_priv5: int = PrivateAttr()
_priv6: int = PrivateAttr()

def model_post_init(self, __context) -> None:
self._priv3 = 200
self._priv5 = 300
super().model_post_init(__context)

m = SubModel()

assert m._priv1 == 100
assert m._priv2 == 92
assert m._priv3 == 200
assert m._priv4 == 94
assert m._priv5 == 300
with pytest.raises(AttributeError):
assert m._priv6 == 94


def test_model_post_init_correct_mro():
"""https://github.com/pydantic/pydantic/issues/7293"""
calls = []
Expand Down

0 comments on commit 218b5ad

Please sign in to comment.