简体   繁体   中英

SQLModel: Forbid mutation

from sqlmodel import SQLModel


class Foo(SQLModel):
    bar: str
        
    class Config:
        """
        Forbid mutation in order to freeze the inheriting classes
        """
        allow_mutation = False


foo = Foo(bar='bar')

Produces

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/tmp/ipykernel_3092/4259691966.py in <module>
----> 1 foo = Foo(bar='bar')

/usr/local/lib/python3.8/site-packages/sqlmodel/main.py in __init__(__pydantic_self__, **data)
    512         object.__setattr__(__pydantic_self__, "__fields_set__", fields_set)
    513         for key, value in values.items():
--> 514             setattr(__pydantic_self__, key, value)
    515         non_pydantic_keys = data.keys() - values.keys()
    516         for key in non_pydantic_keys:

/usr/local/lib/python3.8/site-packages/sqlmodel/main.py in __setattr__(self, name, value)
    530             # non relationship values
    531             if name not in self.__sqlmodel_relationships__:
--> 532                 super().__setattr__(name, value)
    533 
    534     @classmethod

/usr/local/lib/python3.8/site-packages/pydantic/main.cpython-38-x86_64-linux-gnu.so in pydantic.main.BaseModel.__setattr__()

TypeError: "Foo" is immutable and does not support item assignment

Question : Is it possible to forbid mutation for a SQLModel class?

Context: I have a code base with all data model classes built upon frozen Pydantic classes and want to migrate from BaseModel to SQLModel in order to store inheriting table classes.

Of course allow_mutation=True works like a charm.

This is arguably a bug in the current (0.0.8) implementation of SQLModel.__init__ .

It calls its own __setattr__ , which in turn calls the BaseModel.__setattr__ . Since mutation is forbidden, you get the error. This has been mentioned here already. I did not see a PR for fixing it yet, so it may take a while.

EDIT:

The code below is not a usable workaround . BaseModel.__config__ is a class variable, which means that with this code you effectively still set allow_mutation=False after the first initialization. Maybe someone can come up with an idea for how to work around this issue for now.

Original section:

In the meantime, here is a possible workaround:

from sqlmodel import SQLModel


class ImmutableSQLModel(SQLModel):
    def __init__(self, **data: object) -> None:
        super().__init__(**data)
        self.__config__.allow_mutation = False


class Foo(ImmutableSQLModel):
    bar: str


if __name__ == "__main__":
    foo = Foo(bar="bar")
    print(foo)
    try:
        foo.bar = "baz"
    except Exception as e:
        print(repr(e))

Output:

bar='bar'
TypeError('"Foo" is immutable and does not support item assignment')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM