Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error when using marshmallow_dataclass with attr.s #236

Open
csghone opened this issue Mar 24, 2023 · 1 comment
Open

Error when using marshmallow_dataclass with attr.s #236

csghone opened this issue Mar 24, 2023 · 1 comment

Comments

@csghone
Copy link

csghone commented Mar 24, 2023

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.

  • Scenario1 : ENABLE_DC = True, ENABLE_ATTRS = False
    • Works as expected. Validator is inactive
  • Scenario2 : ENABLE_DC = True, ENABLE_ATTRS = True
    • Works as expected. Validator also works.
  • Scenario3 : ENABLE_DC = False, ENABLE_ATTRS = True
    • Crashes.
    • Fails in B = ClsB.Schema().load({'a': 123, 'b': 'bb', 'c': 4, 'd': "123"})
      • Error: marshmallow.exceptions.ValidationError: {'a': ['Unknown field.'], 'b': ['Unknown field.']}

Questions:

  • Is it possible to fix Scenario 3 ?
  • Scenario 2 seems to be ok for my requirements. But I am not sure what weird stuff might happen by enabling both dataclasses and attrs together. If you are aware of possible problems I might get into, please let me know.

I have raised this query with attrs as well.
python-attrs/attrs#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
Copy link
Author

csghone commented Apr 5, 2023

Response from attrs team:
python-attrs/attrs#1114 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant