Fix PEP487 __set_name__ protocol in BaseModel (#4407)

* fix: fix __set_name__ protocol in BaseModel

* undo changes

* add comment

* fix lint

* fix lint

* add change file

* remove mock, move imports
This commit is contained in:
Talley Lambert
2022-08-21 09:53:26 -04:00
committed by GitHub
parent abcf81ec10
commit d501c39f2b
3 changed files with 27 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
Fix PEP487 protocol in `BaseModel`: call `__set_name__` on namespace values that implement the method.
+6
View File
@@ -286,6 +286,12 @@ class ModelMetaclass(ABCMeta):
if resolve_forward_refs:
cls.__try_update_forward_refs__()
# preserve `__set_name__` protocol defined in https://peps.python.org/pep-0487
for name, obj in namespace.items():
set_name = getattr(obj, '__set_name__', None)
if callable(set_name):
set_name(cls, name)
return cls
def __instancecheck__(self, instance: Any) -> bool:
+20
View File
@@ -3,6 +3,7 @@ from typing import Generic, TypeVar
import pytest
from pydantic import BaseModel, Extra, Field, ValidationError, create_model, errors, validator
from pydantic.fields import ModelPrivateAttr
from pydantic.generics import GenericModel
@@ -222,3 +223,22 @@ def test_generics_model():
result = AAModel[int](aa=1)
assert result.aa == 1
assert result.__config__.orm_mode is True
def test_set_name():
calls = []
class class_deco(ModelPrivateAttr):
def __init__(self, fn):
super().__init__()
self.fn = fn
def __set_name__(self, owner, name):
calls.append((owner, name))
class A(BaseModel):
@class_deco
def _some_func(self):
return self
assert calls == [(A, '_some_func')]