Code review changes · pydantic/pydantic@404b8b7 (original) (raw)

`@@ -86,10 +86,10 @@ def _model_field_setattr_handler(model: BaseModel, name: str, val: Any) -> None:

`

86

86

`model.pydantic_fields_set.add(name)

`

87

87

``

88

88

``

89

``

`-

SIMPLE_SETATTR_HANDLERS: Mapping[str, Callable[[BaseModel, str, Any], None]] = {

`

``

89

`+

_SIMPLE_SETATTR_HANDLERS: Mapping[str, Callable[[BaseModel, str, Any], None]] = {

`

90

90

`'model_field': _model_field_setattr_handler,

`

91

``

`-

'validate_assignment': lambda model, name, val: model.pydantic_validator.validate_assignment(model, name, val), # type: ignore

`

92

``

`-

'private': lambda model, name, val: model.pydantic_private.setitem(name, val), # type: ignore

`

``

91

`+

'validate_assignment': lambda model, name, val: model.pydantic_validator.validate_assignment(model, name, val), # pyright: ignore[reportAssignmentType]

`

``

92

`+

'private': lambda model, name, val: model.pydantic_private.setitem(name, val), # pyright: ignore[reportOptionalMemberAccess]

`

93

93

`'cached_property': lambda model, name, val: model.dict.setitem(name, val),

`

94

94

`'extra_known': lambda model, name, val: _object_setattr(model, name, val),

`

95

95

`}

`

`@@ -909,16 +909,18 @@ def getattr(self, item: str) -> Any:

`

909

909

`def setattr(self, name: str, value: Any) -> None:

`

910

910

`if (setattr_handler := self.pydantic_setattr_handlers.get(name)) is not None:

`

911

911

`setattr_handler(self, name, value)

`

``

912

`+

if None is returned from _setattr_handler, the attribute was set directly

`

912

913

`elif (setattr_handler := self._setattr_handler(name, value)) is not None:

`

913

914

`setattr_handler(self, name, value) # call here to not memo on possibly unknown fields

`

914

915

`self.pydantic_setattr_handlers[name] = setattr_handler # memoize the handler for faster access

`

915

916

``

916

``

`-

def _setattr_handler(self, name: str, value: Any) -> Callable[[BaseModel, Any, Any], None] | None:

`

``

917

`+

def _setattr_handler(self, name: str, value: Any) -> Callable[[BaseModel, str, Any], None] | None:

`

917

918

`"""Get a handler for setting an attribute on the model instance.

`

918

919

``

919

920

` Returns:

`

920

921

` A handler for setting an attribute on the model instance. Used for memoization of the handler.

`

921

``

`-

Gives None when memoization is not safe, then the attribute is set directly.

`

``

922

`` +

Memoizing the handlers leads to a dramatic performance improvement in __setattr__

``

``

923

`` +

Returns None when memoization is not safe, then the attribute is set directly.

``

922

924

` """

`

923

925

`cls = self.class

`

924

926

`if name in cls.class_vars:

`

`@@ -931,7 +933,7 @@ def _setattr_handler(self, name: str, value: Any) -> Callable[[BaseModel, Any, A

`

931

933

`if hasattr(attribute, 'set'):

`

932

934

`return lambda model, _name, val: attribute.set(model, val)

`

933

935

`else:

`

934

``

`-

return SIMPLE_SETATTR_HANDLERS['private']

`

``

936

`+

return _SIMPLE_SETATTR_HANDLERS['private']

`

935

937

`else:

`

936

938

`_object_setattr(self, name, value)

`

937

939

`return None # Can not return memoized handler with possibly freeform attr names

`

`@@ -946,9 +948,9 @@ def _setattr_handler(self, name: str, value: Any) -> Callable[[BaseModel, Any, A

`

946

948

`if isinstance(attr, property):

`

947

949

`return lambda model, _name, val: attr.set(model, val)

`

948

950

`elif isinstance(attr, cached_property):

`

949

``

`-

return SIMPLE_SETATTR_HANDLERS['cached_property']

`

``

951

`+

return _SIMPLE_SETATTR_HANDLERS['cached_property']

`

950

952

`elif cls.model_config.get('validate_assignment'):

`

951

``

`-

return SIMPLE_SETATTR_HANDLERS['validate_assignment']

`

``

953

`+

return _SIMPLE_SETATTR_HANDLERS['validate_assignment']

`

952

954

`elif name not in cls.pydantic_fields:

`

953

955

`if cls.model_config.get('extra') != 'allow':

`

954

956

`# TODO - matching error

`

`@@ -959,10 +961,9 @@ def _setattr_handler(self, name: str, value: Any) -> Callable[[BaseModel, Any, A

`

959

961

`return None # Can not return memoized handler with possibly freeform attr names

`

960

962

`else:

`

961

963

`# attribute does exist, and was not in extra, so update it

`

962

``

`-

return SIMPLE_SETATTR_HANDLERS['extra_known']

`

``

964

`+

return _SIMPLE_SETATTR_HANDLERS['extra_known']

`

963

965

`else:

`

964

``

`-

Normal model field

`

965

``

`-

return SIMPLE_SETATTR_HANDLERS['model_field']

`

``

966

`+

return _SIMPLE_SETATTR_HANDLERS['model_field']

`

966

967

``

967

968

`def delattr(self, item: str) -> Any:

`

968

969

`if item in self.private_attributes:

`