Repository navigation
Open
Description
Describe the bug
The default parsing logic seems to want to call asdict on a dataclass field even if it has a registered decoding function:
To Reproduce
def test_parse_helper_uses_custom_decoding_fn():
@dataclasses.dataclass
class Id:
value: str
register_decoding_fn(Id, (lambda x, drop_extra_fields: Id(value=x)))
@dataclasses.dataclass
class Person:
name: str
id: Id
config_str = """
name: bob
id: hi
"""
@dataclasses.dataclass
class StrIdPerson:
name: str
id: str
# ok
assert get_decoding_fn(Person)({"name": "bob", "id": "hi"}) == Person("bob", Id("hi")) # type: ignore
with tempfile.NamedTemporaryFile("w", suffix=".yaml") as f:
f.write(config_str)
f.flush()
# ok
assert simple_parsing.parse(StrIdPerson, f.name, args=[]) == StrIdPerson("bob", "hi")
# boom
assert simple_parsing.parse(Person, f.name, args=[]) == Person("bob", Id("hi"))
Expected behavior
Test should pass.
Actual behavior
Last assertion fails:
simple_parsing/parsing.py:1021: in parse
parsed_args = parser.parse_args(args)
argparse.py:1826: in parse_args
args, argv = self.parse_known_args(args, namespace)
simple_parsing/parsing.py:298: in parse_known_args
self.set_defaults(config_file)
simple_parsing/parsing.py:405: in set_defaults
wrapper.set_default(default_for_dataclass)
simple_parsing/wrappers/dataclass_wrapper.py:308: in set_default
nested_dataclass_wrapper.set_default(field_default_value)
simple_parsing/wrappers/dataclass_wrapper.py:292: in set_default
field_default_values = dataclasses.asdict(value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
obj = 'hi'
def asdict(obj, *, dict_factory=dict):
"""Return the fields of a dataclass instance as a new dictionary mapping
field names to field values.
Example usage:
@dataclass
class C:
x: int
y: int
c = C(1, 2)
assert asdict(c) == {'x': 1, 'y': 2}
If given, 'dict_factory' will be used instead of built-in dict.
The function applies recursively to field values that are
dataclass instances. This will also look into built-in containers:
tuples, lists, and dicts.
"""
if not _is_dataclass_instance(obj):
> raise TypeError("asdict() should be called on dataclass instances")
E TypeError: asdict() should be called on dataclass instances
Desktop (please complete the following information):
- Version 0.1.3
- Python version: 3.10
Additional context
Metadata
Metadata
Assignees
Labels
No labels
Activity
don't treat dataclasses with decoding fns as dataclasses, fixes lebri…
lebrice commentedon Jun 22, 2023
Hey @dlwh , encoding = dc->dict (via the
encodefunction) and decoding = dict->dcTherefore asdict is more about encoding, and therefore I dont understand why calling asdict on the dataclass would be wrong if it has a custom decoding function registered.
lebrice commentedon Jun 22, 2023
I dont completely understand the test in the issue atm. I'll take a better look a bit later today.
lebrice commentedon Jun 22, 2023
When parsing with a config file, the custom decoding function isnt being used?
lebrice commentedon Jun 29, 2023
Would you mind helping me out @dlwh ? I'm still having trouble understanding what the issue is here.
dlwh commentedon Jun 29, 2023
Yes, dataclasses that have custom decode functions (like
Idin the example) don't use that custom decode function when parsing from a "json dict", or when using argparse. I had a mostly complete fix in #267.(FWIW, I ended up forking Pyrallis so I'm going it alone, so happy to just close this.)