Skip to content

Flatten Enum members to bare values on the serialize path#800

Open
elinscott wants to merge 2 commits into
aiidateam:mainfrom
elinscott:serialize-enum-flatten
Open

Flatten Enum members to bare values on the serialize path#800
elinscott wants to merge 2 commits into
aiidateam:mainfrom
elinscott:serialize-enum-flatten

Conversation

@elinscott

@elinscott elinscott commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Problem

node_graph declares that an enum-typed socket's serialized form is the bare member value: socket_spec records structured_type extras precisely so coerce_inputs_from_spec can rebuild the Enum member before a task body runs.

The AiiDA serialization adapter never honoured that contract on the write path: a raw Enum instance (or a dict/list containing one, e.g. a parameters dict with an enum-valued entry) flows straight into serialize_ports, which hands it to aiida-pythonjob's general_serializer — which has no serializer for enums — and the whole submission fails at submit time with an opaque serialization error.

Change

A small _flatten_enums helper replaces Enum members with their .value, recursively through dicts (keys and values), lists and tuples, and is applied in both AiidaSerializationAdapter.serialize and AiidaSerializationAdapter.serialize_ports immediately after resolve_tagged_values. The isinstance(value, Enum) check also matches wrapt proxies (TaggedValue) wrapping enum members, so tagged graph inputs are handled by the same path.

Round-trip is preserved: the read side (coerce_inputs_from_spec in node-graph) rebuilds the member from the bare value using the recorded structured_type, so task bodies still receive the Enum they declared.

Testing

New unit tests in tests/test_serializer.py

Exercised end-to-end by the downstream Koopmans package, whose workgraphs pass enum-valued settings (e.g. functional and spin-treatment enums) through @task.graph inputs: before the change every such submission failed in general_serializer; after it, the graphs submit and the bodies receive rebuilt members.

elinscott and others added 2 commits July 8, 2026 13:46
node-graph's socket spec records structured_type extras for enum-typed
sockets so coerce_inputs_from_spec can rebuild the member before a task
body runs - the declared contract is that the serialized form is the
bare value. The AiiDA adapter never honoured it: raw Enum instances
reached aiida-pythonjob's general_serializer, which has no serializer
for them and failed the whole submission. Flatten enums (recursively,
including dict keys/values and list items) before serialize_ports.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
node-graph's socket spec records structured_type extras for enum-typed
sockets so coerce_inputs_from_spec can rebuild the member before a task
body runs - the declared contract is that the serialized form is the
bare value. The AiiDA adapter never honoured it: raw Enum instances
reached aiida-pythonjob's general_serializer, which has no serializer
for them and failed the whole submission. Flatten enums (recursively,
including dict keys/values and list items) before serialize_ports.

Add unit tests in tests/test_serializer.py covering _flatten_enums
(bare/IntEnum/str-Enum members, dict keys and values, list/tuple,
mixed nesting, enum-free passthrough, wrapt-proxied members) plus one
end-to-end serialize_ports check that an enum-valued entry serializes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@elinscott elinscott marked this pull request as ready for review July 8, 2026 12:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant