python-desert / desert

Deserialize to objects while staying DRY
https://desert.readthedocs.io
MIT License
158 stars 10 forks source link

Support for SQLAlchemy 2.0's new declarative method of class definitions with dataclass integration. #268

Open xlorepdarkhelm opened 1 year ago

xlorepdarkhelm commented 1 year ago

SQLAlchemy 2.0 has a new method for making an ORM table model using "dataclasses". I put it in quotes because there are limitations. The dataclasses are made either by subclassing the MappedAsDataclass class, or by using the reg.mapped_as_dataclass() decorator.

Fields are defined using a type of Mapped[], and then optionally using mapped_column() to specify additional details as necessary. This is all fine and good except: desert won't recognize Mapped[str] as a string, and it fails in making a Schema. It suggests setting the metadata attribute for dataclasses.field() to specifically state which marshmallow type to use. HOWEVER, SQLAlchemy will not allow the use of the dataclasses.field() function for setting up the field. To make matters worse, their mapped_column() function doesn't have a metadata parameter to do that with.

However, the resulting class that is defined after this is all said and done, has 2 dunder attributes that are quite helpful: __dataclass_fields__ and __dataclass_params__. The first of which lists the underlying dataclass fields, with the correct Python types, and even has the dataclasses.field() settings in it as well. The last one specifies all the dataclass decorator parameters that are set. Together, you have the actual underlying dataclass definition. So, in theory, it should be possible for desert to identify these attributes and look up the correct types without needing the extra metadata being set.

I have a request in on the SQLAlchemy team to find out a best practice for needing to set metadata in their structure. However I think it might also be good for desert to be able to support this structure type, as SQLAlchemy is a very popular database ORM that is used in Python.