pyiron / pyiron_workflow

Graph-and-node based workflows
BSD 3-Clause "New" or "Revised" License
10 stars 1 forks source link

:bug: Dataclass nodes made from a decorator are not pickleable #319

Open liamhuber opened 1 month ago

liamhuber commented 1 month ago

The easy bit is that when coming from a decorator, they need the same flag as the macro and function nodes from a decorator _class_returns_from_decorated_function (although it's a class in this case, not a function, so I guess the flag needs a better name). Adding cls._class_returns_from_decorated_function = dataclass to as_dataclass_node is sufficient to resolve this, __reduce__ then returns factory._instantiate_from_decorated and the problem is resolved in exactly the same manner as functions and macros.

The outstanding problem is that the underlying dataclass also gets used by the output signal, and there it's an instance property rather than a class property, so pickle tries to deal with it in the __getstate__ of the output channel and throws a it's not the same object as error.

I did a brute-force check and just setting {dataclass node}.outputs.dataclass.type_hint = None resolves this, so that really is the issue. In principle one could do this in the get- and set-state of dataclass nodes... but that's not a pattern I'm thrilled with.

Dataclass nodes instantiated separately from their dataclass instance pickle fine, of course. Maybe this is the better way to go anyhow, so that if/when you want to make new dataclasses by composition you don't wind up with something ugly like

@as_dataclass_node
@dataclass
class CompositeData(Parent.dataclass, Parent2.dataclass):
    pass