'pyyaml support for default list in dataclass?
Below is a minimal example that demonstrates the issue.
First, imports:
from dataclasses import dataclass, field
from typing import List
import yaml
Next, define a class that derives from yaml.YAMLObject:
@dataclass
class Yaz(yaml.YAMLObject):
name: str
items: List[str] = field(default_factory=lambda: ['a', 'b', 'c'])
yaml_tag: str = u'!Yaz'
Demonstrate usage:
Yaz(name='Yazzzy') # >>> Yaz(name='Yazzzy', items=['a', 'b', 'c'], yaml_tag='!Yaz')
Yaz(name='Yazzzy', items=[]) # >>> Yaz(name='Yazzzy', items=[], yaml_tag='!Yaz')
But sometimes I'd like to instantiate an instance from a YAML file. Mock a YAML file:
yaml_str = """---
!Yaz
name: Yazzzy
"""
Load the YAML file into an instance:
yaml.load(yaml_str, Loader=yaml.Loader) # ERROR!
The last line yields the following error:
AttributeError: 'Yaz' object has no attribute 'items'
Is there some sort of hook I'm missing?
Thanks in advance!
Note: I am using Python 3.8 with pyyaml 6.0.
Solution 1:[1]
I would humbly suggest using the dataclass-wizard for this task. It comes with a helper Mixin class called the YAMLWizard, which you can use along with pyyaml 6.0. To clarify it does use pyyaml for working with YAML data.
Here's a working example below. Note that I went ahead and removed the yaml.YAMLObject and the associated tags in the YAML object, since this is not needed anymore.
I haven't shown this in the example, but it's also possible to load a nested dataclass model from YAML using this same approach. You can check out an example of a nested model here.
from __future__ import annotations # can be removed in Python 3.9+
from dataclasses import dataclass, field
from dataclass_wizard import YAMLWizard
@dataclass
class Yaz(YAMLWizard):
name: str
items: list[str] = field(default_factory=lambda: ['a', 'b', 'c'])
Yaz(name='Yazzzy') # >>> Yaz(name='Yazzzy', items=['a', 'b', 'c'])
Yaz(name='Yazzzy', items=[]) # >>> Yaz(name='Yazzzy', items=[])
yaml_str = """---
name: Yazzzy
"""
yaz_object = Yaz.from_yaml(yaml_str)
print(yaz_object)
Output:
Yaz(name='Yazzzy', items=['a', 'b', 'c'])
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
