Describe the bug
JsonableData._get_object() calls .pop('@class') and .pop('@module') on the attributes dictionary before passing it to cls.from_dict(). This mutates the dict and strips both keys before deserialization. MSONable's contract (used by pymatgen and other materials science libraries) requires @module and @class to be present in the dict passed to from_dict() — the same dict that as_dict() produced. Stripping them silently breaks round-trip deserialization.
Steps to reproduce
from aiida.orm import JsonableData, load_node
class MyMSONable:
def __init__(self, value):
self.value = value
def as_dict(self):
return {
'@module': self.__class__.__module__,
'@class': self.__class__.__name__,
'value': self.value,
}
@classmethod
def from_dict(cls, d):
# MSONable contract: @module and @class must be present
if '@module' not in d or '@class' not in d:
raise KeyError('`@module` and `@class` must be present')
return cls(d['value'])
obj = MyMSONable(42)
node = JsonableData(obj)
node.store()
loaded = load_node(node.pk)
print(loaded.obj.value) # Raises KeyError: @module and @class stripped
Expected behavior
loaded.obj.value should return 42. @module and @class should be preserved in the dict passed to cls.from_dict().
Your environment
- Operating system: Linux
- Python version: 3.11
- aiida-core version: 2.8.0 (main branch)
Additional context
File: src/aiida/orm/nodes/data/jsonable.py
The fix is to use non-destructive key access (attributes['@class']) instead of .pop(), so the full dict including @module and @class reaches from_dict(). A PR with the fix and a regression test is ready.
Describe the bug
JsonableData._get_object()calls.pop('@class')and.pop('@module')on the attributes dictionary before passing it tocls.from_dict(). This mutates the dict and strips both keys before deserialization. MSONable's contract (used by pymatgen and other materials science libraries) requires@moduleand@classto be present in the dict passed tofrom_dict()— the same dict thatas_dict()produced. Stripping them silently breaks round-trip deserialization.Steps to reproduce
Expected behavior
loaded.obj.valueshould return42.@moduleand@classshould be preserved in the dict passed tocls.from_dict().Your environment
Additional context
File:
src/aiida/orm/nodes/data/jsonable.pyThe fix is to use non-destructive key access (
attributes['@class']) instead of.pop(), so the full dict including@moduleand@classreachesfrom_dict(). A PR with the fix and a regression test is ready.