Background
I'm using dataclasses to create a nested data structure, that I use to represent a complex test output.
Previously I'd been creating a hierarchy by creating multiple top-level dataclasses and then using composition:
from dataclasses import dataclass
@dataclass
class Meta:
    color: str 
    size: float
@dataclass
class Point:
    x: float
    y: float
    stuff: Meta
point1 = Point(x=5, y=-5, stuff=Meta(color='blue', size=20))
Problem
I was wondering if there was a way of defining the classses in a self-contained way, rather than polluting my top-level with a bunch of lower-level classes.
So above, the definition of Point dataclass contains the definition of Meta, rather than the definition being at the top level.
Solution?
I wondered if it's possible to use inner (dataclass) classes with a dataclass and have things all work.
So I tried this:
rom dataclasses import dataclass
from typing import get_type_hints
@dataclass
class Point:
    @dataclass
    class Meta:
        color: str 
        size: float
    @dataclass
    class Misc:
        elemA: bool
        elemB: int 
    x: float
    y: float
    meta: Meta
    misc: Misc
point1 = Point(x=1, y=2,
               meta=Point.Meta(color='red', size=5.5),
               misc=Point.Misc(elemA=True, elemB=-100))
print("This is the point:", point1)
print(point1.x)
print(point1.y)
print(point1.meta)
print(point1.misc)
print(point1.meta.color)
print(point1.misc.elemB)
point1.misc.elemB = 99
print(point1)
print(point1.misc.elemB)
This all seems to work - the print outputs all work correctly, and the assignment to a (sub) member element works as well.
You can even support defaults for nested elements:
from dataclasses import dataclass
@dataclass
class Point:
    @dataclass
    class Meta:
        color: str = 'red'
        size: float = 10.0
    x: float
    y: float
    meta: Meta = Meta()
pt2 = Point(x=10, y=20)
print('pt2', pt2)
...prints out red and 10.0 defaults for pt2 correctly
Question
Is this a correct way to implement nested dataclasses?
(meaning it's just not lucky it works now, but would likely break in future? ...or it's just fugly and Not How You Do Things? ...or it's just Bad?)
...It's certainly a lot cleaner and a million times easier to understand and upport than a gazillion top-level 'mini' dataclasses being composed together.
...It's also a lot easier than trying to use marshmellow or jerry-rigging a json schema to class structure model.
...It also is very simple (which I like)
 
    