odmantic icon indicating copy to clipboard operation
odmantic copied to clipboard

AttributeError: 'Person' object has no attribute '__fields_modified__'

Open d3cryptofc opened this issue 1 year ago • 0 comments

Bug

The bug happens using pydantic's model_validator, when trying to modify one of the model's attributes, but works normally with pydantic's BaseModel.

AttributeError: 'Person' object has no attribute '__fields_modified__'

Current Behavior

It's just a random example, I know it's not the case for model_validator but field_validator, but it's just to demonstrate the bug.

from odmantic import Model
from pydantic import model_validator

class Person(Model):
  name: str

  @model_validator(mode='after')
  @classmethod
  def strip_name(cls, instance):
    n = instance.name
    if n.strip() != n:
      instance.name = n.strip()
    return instance
>>> Person(name=' John ')
----> 1 Person(name=' John ')

File .venv/lib/python3.12/site-packages/odmantic/model.py:542, in _BaseODMModel.__init__(self, **data)
    541 def __init__(self, **data: Any):
--> 542     super().__init__(**data)
    543     object.__setattr__(self, "__fields_modified__", set(self.__odm_fields__.keys()))

    [... skipping hidden 1 frame]

Cell In[3], line 12, in Person.strip_name(cls, instance)
     10 n = instance.name
     11 if n.strip() != n:
---> 12   instance.name = n.strip()
     13 return instance

File .venv/lib/python3.12/site-packages/odmantic/model.py:960, in Model.__setattr__(self, name, value)
    955 if name == self.__primary_field__:
    956     # TODO implement
    957     raise NotImplementedError(
    958         "Reassigning a new primary key is not supported yet"
    959     )
--> 960 super().__setattr__(name, value)

File .venv/lib/python3.12/site-packages/odmantic/model.py:707, in _BaseODMModel.__setattr__(self, name, value)
    705 def __setattr__(self, name: str, value: Any) -> None:
    706     super().__setattr__(name, value)
--> 707     self.__fields_modified__.add(name)

File .venv/lib/python3.12/site-packages/pydantic/main.py:853, in BaseModel.__getattr__(self, item)
    851 else:
    852     if hasattr(self.__class__, item):
--> 853         return super().__getattribute__(item)  # Raises AttributeError if appropriate
    854     else:
    855         # this is the current error
    856         raise AttributeError(f'{type(self).__name__!r} object has no attribute {item!r}')

AttributeError: 'Person' object has no attribute '__fields_modified__'

Expected behavior

>>> Person(name=' John ')
Person(name='John')

Environment

  • ODMantic version: 1.0.2
  • Pydantic infos (output of python -c "import pydantic.utils; print(pydantic.utils.version_info())):
             pydantic version: 2.9.2
        pydantic-core version: 2.23.4
          pydantic-core build: profile=release pgo=false
                 install path: /home/lelzin/Projects/tests/python/personal-data-miner/.venv/lib/python3.12/site-packages/pydantic
               python version: 3.12.7 (main, Oct  1 2024, 11:15:50) [GCC 14.2.1 20240910]
                     platform: Linux-6.6.50-2-lts-x86_64-with-glibc2.40
             related packages: typing_extensions-4.12.2
                       commit: unknown

d3cryptofc avatar Oct 29 '24 18:10 d3cryptofc