dataclass-wizard icon indicating copy to clipboard operation
dataclass-wizard copied to clipboard

Fix Failure in rendering `str()` for Exceptions (values are not JSON serializable)

Open rnag opened this issue 2 years ago • 0 comments
trafficstars

  • Dataclass Wizard version: 0.22.2
  • Python version: 3.10.4
  • Operating System: Mac OS X (M1)

Description

I have noticed in certain cases -- such as using the YAMLWizard with the PyYAML library, which inherently loads YAML data as complex Python types, such as datetime for instance -- that exceptions which call json.dumps on the input argument to fromdict, will fail rendering the str() method, mainly because values are not common types and are instead complex types such as datetime which the json module does not support for (de)serialization OOTB.

What I Did

The following code works when publisher is uncommented out in the YAML, but crashes with a vague/unclear error when run as it currently is:

import dataclasses
from datetime import datetime

from dataclass_wizard import YAMLWizard
from yaml import safe_load

yaml_data = """
kind: Book
title: Someone's life

# publisher: someone
published_at: 2023-02-24T09:31:00Z
"""


@dataclasses.dataclass
class Book(YAMLWizard):
    title: str
    publisher:  str
    published_at: datetime


print('yaml.safe_load():  ', safe_load(yaml_data))
print(repr(Book.from_yaml(yaml_data)))

The current error trace:

yaml.safe_load():   {'kind': 'Book', 'title': "Someone's life", 'published_at': datetime.datetime(2023, 2, 24, 9, 31, tzinfo=datetime.timezone.utc)}
Traceback (most recent call last):
  File "/path/to/script.py", line 25, in <module>
    print(repr(Book.from_yaml(yaml_data)))
  File "/path/to/venv/lib/python3.10/site-packages/dataclass_wizard/wizard_mixins.py", line 136, in from_yaml
    return fromdict(cls, o) if isinstance(o, dict) else fromlist(cls, o)
  File "/path/to/venv/lib/python3.10/site-packages/dataclass_wizard/loaders.py", line 536, in fromdict
    return load(d)
  File "/path/to/venv/lib/python3.10/site-packages/dataclass_wizard/loaders.py", line 662, in cls_fromdict
    raise MissingFields(
dataclass_wizard.errors.MissingFields: <exception str() failed>

The desired or expected error message:

dataclass_wizard.errors.MissingFields: Failure calling constructor method of class `Book`. Missing values for required dataclass fields.
  have fields: ['title', 'published_at']
  missing fields: ['publisher']
  input JSON object: {"kind": "Book", "title": "Someone's life", "published_at": "2023-02-24 09:31:00+00:00"}
  error: Book.__init__() missing 1 required positional argument: 'publisher'

rnag avatar Mar 30 '23 15:03 rnag