Skip to content

Earlier and More Helpful Type Errors  #325

@MatrixManAtYrService

Description

@MatrixManAtYrService

First of all, thanks for dataclasses-json. It's useful.

Here are some dataclasses:

# issue.py
from dataclasses import dataclass
from dataclasses_json import dataclass_json
from typing import List, Dict

@dataclass_json
@dataclass(frozen=True)
class InnerThing:
    innest_things: List[str]

@dataclass_json
@dataclass(frozen=True)
class Thing:
    things: Dict[str, InnerThing]

foo = InnerThing(
    innest_things=["hydrogen", "oxygen", "carbon"],
)

bar = Thing(
    things={"wakka" : foo}
)

baz = Thing(
    things={"wakka" : foo.innest_things}
)

# a hacky way to check for errors
Thing.from_dict(bar.to_dict()) # no error
Thing.from_dict(baz.to_dict()) # see below

And here is an error:

❯ python issue.py
Traceback (most recent call last):
  File "/Users/matt/src/qa-outer-dags/venv/lib/python3.9/site-packages/dataclasses_json/core.py", line 263, in _decode_generic
    res = _get_type_cons(type_)(xs)
  File "/Users/matt/src/qa-outer-dags/venv/lib/python3.9/site-packages/dataclasses_json/core.py", line 317, in <genexpr>
    items = (_decode_dataclass(type_arg, x, infer_missing)
  File "/Users/matt/src/qa-outer-dags/venv/lib/python3.9/site-packages/dataclasses_json/core.py", line 137, in _decode_dataclass
    kvs = {decode_names.get(k, k): v for k, v in kvs.items()}
AttributeError: 'list' object has no attribute 'items'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/matt/src/qa-outer-dags/issue.py", line 32, in <module>
    Thing.from_dict(baz.to_dict()) # error
  File "/Users/matt/src/qa-outer-dags/venv/lib/python3.9/site-packages/dataclasses_json/api.py", line 83, in from_dict
    return _decode_dataclass(cls, kvs, infer_missing)
  File "/Users/matt/src/qa-outer-dags/venv/lib/python3.9/site-packages/dataclasses_json/core.py", line 201, in _decode_dataclass
    init_kwargs[field.name] = _decode_generic(field_type,
  File "/Users/matt/src/qa-outer-dags/venv/lib/python3.9/site-packages/dataclasses_json/core.py", line 265, in _decode_generic
    res = type_(xs)
  File "/usr/local/Cellar/[email protected]/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/typing.py", line 680, in __call__
    raise TypeError(f"Type {self._name} cannot be instantiated; "
TypeError: Type Dict cannot be instantiated; use dict() instead

It's appropriate that there would be an error: baz initializes Thing with the wrong type. I'm filing an issue because I wanted to point out two things:

Field names in error messages

It would be very nice if the error showed the name of the field with the problem. If it's convenient, would you consider making that error prettier?

Forcing errors to surface earlier

My hack to check for type errors Thing.from_dict(foo.to_dict()) is ugly. Is there a better way to programmatically check for errors? Perhaps something like baz.check()?

I considered trying to use mypy for the job, but I get the feeling that it might not be the right tool (based on this)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions