@@ -99,10 +99,20 @@ def _model_field_setattr_handler(model: BaseModel, name: str, val: Any) -> None:
99
99
model .__pydantic_fields_set__ .add (name )
100
100
101
101
102
+ def _private_setattr_handler (model : BaseModel , name : str , val : Any ) -> None :
103
+ if getattr (model , '__pydantic_private__' , None ) is None :
104
+ # While the attribute should be present at this point, this may not be the case if
105
+ # users do unusual stuff with `model_post_init()` (which is where the `__pydantic_private__`
106
+ # is initialized, by wrapping the user-defined `model_post_init()`), e.g. if they mock
107
+ # the `model_post_init()` call. Ideally we should find a better way to init private attrs.
108
+ object .__setattr__ (model , '__pydantic_private__' , {})
109
+ model .__pydanti
10000
c_private__ [name ] = val # pyright: ignore[reportOptionalSubscript]
110
+
111
+
102
112
_SIMPLE_SETATTR_HANDLERS : Mapping [str , Callable [[BaseModel , str , Any ], None ]] = {
103
113
'model_field' : _model_field_setattr_handler ,
104
114
'validate_assignment' : lambda model , name , val : model .__pydantic_validator__ .validate_assignment (model , name , val ), # pyright: ignore[reportAssignmentType]
105
- 'private' : lambda model , name , val : model . __pydantic_private__ . __setitem__ ( name , val ), # pyright: ignore[reportOptionalMemberAccess]
115
+ 'private' : _private_setattr_handler ,
106
116
'cached_property' : lambda model , name , val : model .__dict__ .__setitem__ (name , val ),
107
117
'extra_known' : lambda model , name , val : _object_setattr (model , name , val ),
108
118
}
0 commit comments