From 2b09cf48c4737898679b62cfbd004d9d1083877a Mon Sep 17 00:00:00 2001 From: Sydney Runkle <54324534+sydney-runkle@users.noreply.github.com> Date: Tue, 9 Jan 2024 10:11:48 -0600 Subject: [PATCH] Add more support for private attributes in `model_construct` call (#8525) --- pydantic/main.py | 6 ++++++ tests/test_construction.py | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/pydantic/main.py b/pydantic/main.py index 1dbf607c3f..9df8f8797c 100644 --- a/pydantic/main.py +++ b/pydantic/main.py @@ -237,6 +237,12 @@ def model_construct(cls: type[Model], _fields_set: set[str] | None = None, **val if cls.__pydantic_post_init__: m.model_post_init(None) + # update private attributes with values set + if hasattr(m, '__pydantic_private__') and m.__pydantic_private__ is not None: + for k, v in values.items(): + if k in m.__private_attributes__: + m.__pydantic_private__[k] = v + elif not cls.__pydantic_root_model__: # Note: if there are any private attributes, cls.__pydantic_post_init__ would exist # Since it doesn't, that means that `__pydantic_private__` should be set to None diff --git a/tests/test_construction.py b/tests/test_construction.py index a3d13b817c..75998bf474 100644 --- a/tests/test_construction.py +++ b/tests/test_construction.py @@ -519,3 +519,13 @@ class MyModel(BaseModel): m = MyModel.model_construct(b='b') assert m.model_dump_json() == '{"a":"a","b":"b"}' + + +def test_initialize_with_private_attr(): + class MyModel(BaseModel): + _a: str + + m = MyModel.model_construct(_a='a') + + assert m._a == 'a' + assert '_a' in m.__pydantic_private__