lovasoa / marshmallow_dataclass

Automatic generation of marshmallow schemas from dataclasses.
https://lovasoa.github.io/marshmallow_dataclass/html/marshmallow_dataclass.html
MIT License
456 stars 78 forks source link

Error when using marshmallow_dataclass with attr.s #236

Open csghone opened 1 year ago

csghone commented 1 year ago

I am able to use marshmallow_dataclass perfectly when using with dataclasses.dataclass

However, I want to use it with attrs module instead - use the converters/validators functionalities. It works well most of the time. However, I am facing problems when I use marshmallow_dataclass + attrs with inheritance.

Sample code is given below.

Questions:

I have raised this query with attrs as well. https://github.com/python-attrs/attrs/issues/1114

I hope the first question is answered by marshmallow_dataclass team and second by the attrs team.

import dataclasses
import marshmallow
from marshmallow import Schema
import marshmallow_dataclass
from marshmallow_dataclass import class_schema
import attr
from typing import ClassVar, Type

ENABLE_DC    = True
ENABLE_ATTRS = True

# Conditional decorator
def conditionally(dec, cond):
    def resdec(f):
        if not cond:
            return f
        return dec(f)
    return resdec

@marshmallow_dataclass.add_schema
@conditionally(dataclasses.dataclass, ENABLE_DC)
@conditionally(attr.s(auto_attribs=True), ENABLE_ATTRS)
class ClsA:
    a: int
    b: str
    Schema : ClassVar[Type[Schema]] = Schema

@marshmallow_dataclass.add_schema
@conditionally(dataclasses.dataclass, ENABLE_DC)
@conditionally(attr.s(auto_attribs=True), ENABLE_ATTRS)
class ClsB(ClsA):
    if ENABLE_ATTRS:
        c: float = attr.ib(validator=attr.validators.lt(5))
    else:
        c: float
    d: str
    Schema : ClassVar[Type[Schema]] = Schema

B = ClsB.Schema().load({'a': 123, 'b': 'bb', 'c': 4, 'd': "123"})
print(B)
# ClsB(a=123, b='bb', c=4.0, d='123')

B = ClsB.Schema().load({'a': 123, 'b': 'bb', 'c': "3", 'd': 'dd'})
print(B)
# ClsB(a=123, b='bb', c=3.0, d='dd')

try:
    B = ClsB.Schema().load({'a': "asdad", 'b': 'bb', 'c': 2, 'd': 'dd'})
    print(B)
except Exception as e:
    print(e)
# {'a': ['Not a valid integer.']}

try:
    B = ClsB.Schema().load({'a': 123, 'b': 'bb', 'c': '123123asd', 'd': 'dd'})
    print(B)
except Exception as e:
    print(e)
# {'c': ['Not a valid number.']}

try:
    B = ClsB.Schema().load({'a': 123, 'b': 'bb', 'c': '123123', 'd': 'dd'})
    print(B)
except Exception as e:
    print(e)
# "ClsB(a=123, b='bb', c=123123.0, d='dd')" if not ENABLE_ATTRS else "'c' must be < 5: 123123.0"
csghone commented 1 year ago

Response from attrs team: https://github.com/python-attrs/attrs/issues/1114#issuecomment-1495488349