diff --git a/changes/4081-samuelcolvin.md b/changes/4081-samuelcolvin.md new file mode 100644 index 00000000000..53fd4f52a89 --- /dev/null +++ b/changes/4081-samuelcolvin.md @@ -0,0 +1 @@ +Speedup `__isinstancecheck__` on pydantic models when the type is not a model, may also avoid memory "leaks". diff --git a/pydantic/main.py b/pydantic/main.py index 7afcafc4978..0c20d9e69d5 100644 --- a/pydantic/main.py +++ b/pydantic/main.py @@ -295,6 +295,14 @@ def is_untouched(v: Any) -> bool: return cls + def __instancecheck__(self, instance: Any) -> bool: + """ + Avoid calling ABC _abc_subclasscheck unless we're pretty sure. + + See #3829 and python/cpython#92810 + """ + return hasattr(instance, '__fields__') and super().__instancecheck__(instance) + object_setattr = object.__setattr__ diff --git a/tests/test_edge_cases.py b/tests/test_edge_cases.py index 5da62257040..b7083d05846 100644 --- a/tests/test_edge_cases.py +++ b/tests/test_edge_cases.py @@ -1932,3 +1932,17 @@ def __new__(cls, data: int): m = MyModel(my_int=IntSubclass(123)) assert m.my_int.__class__ == IntSubclass + + +def test_model_issubclass(): + assert not issubclass(int, BaseModel) + + class MyModel(BaseModel): + x: int + + assert issubclass(MyModel, BaseModel) + + class Custom: + __fields__ = True + + assert not issubclass(Custom, BaseModel)