Python attrs nested objects convertes

375 Views Asked by At

I'm using attrs lib to parse my configuration file, and I'm looking for a better way to parse nested data objects.

Example :

from attrs import define, field, validators
from typing import Dict

class HoconParser:
    @classmethod
    def from_hocon(cls, file_path):
        from pyhocon import ConfigFactory

        return cls(
            **ConfigFactory.parse_file(file_path)
        )
    
    @classmethod
    def from_dictstrobj(cls, dictstrobj):
        
        if dictstrobj:
            return {
                key: cls(**value) for key, value in dictstrobj.items()
            }
        return {}
@define
class ClassOne(HoconParser):
    id: str = field(validator=validators.instance_of(str))
    name: str = field(validator=validators.instance_of(str))
    
@define
class ClassTwo(HoconParser):
    id: str = field(validator=validators.instance_of(str))
    name: str = field(validator=validators.instance_of(str))
    test: Dict[str, ClassOne] = field(
        converter=ClassOne.from_dictstrobj,
        validator=validators.deep_mapping(
            key_validator=validators.instance_of(str),
            value_validator=validators.instance_of(ClassOne)
        )
    )
    
a = ClassTwo.from_hocon("test.conf")

Basically, ClassTwo has an attribute which is a Dict[str, ClassOne].

In order to make this work, I had to make a specific function named from_dictstrobj and use it as a converter for test attribute.

Is there any better way to do this ?

1

There are 1 best solutions below

2
Tin Tvrtković On BEST ANSWER

I'm a major contributor to attrs and the author of cattrs.

You might want to use the cattrs library here. I'm assuming ConfigFactory.parse_file(file_path) produces a dictionary?

cattrs can recursively transform this dictionary into a graph of objects.

Here's the modified code:

from cattrs import structure

class HoconParser:
    @classmethod
    def from_hocon(cls, file_path):
        from pyhocon import ConfigFactory

        return structure(ConfigFactory.parse_file(file_path), cls)

Hope this helps!