maggma icon indicating copy to clipboard operation
maggma copied to clipboard

JSON representation for `MontyStore` cannot be decoded with `monty.json.MontyDecoder`

Open Andrew-S-Rosen opened this issue 2 years ago • 3 comments

Overview

Given a Store.to_json() representation, one would ideally be able to use MontyDecoder to regenerate the Store object. This works for MemoryStore, MongoStore, etc. but does not work for MontyStore for reasons I have not yet understood.

Sidenote: very confusing here that MontyStore refers to MontyDB but MontyDecoder is the monty package 😅

Example

from maggma.stores import MontyStore
from monty.json import MontyDecoder
store = MontyStore("test")
store_json = store.to_json()
store_remade = MontyDecoder().decode(store_json)
      3 store = MontyStore("test")
      4 store_json = store.to_json()
----> 5 store_remade = MontyDecoder().decode(store_json)

File ~/software/miniconda/envs/quacc/lib/python3.10/site-packages/monty/json.py:497, in
 MontyDecoder.decode(self, s)
    495 else:
    496     d = json.loads(s)
--> 497 return self.process_decoded(d)

File ~/software/miniconda/envs/quacc/lib/python3.10/site-packages/monty/json.py:444, in
 MontyDecoder.process_decoded(self, d)
    442 if hasattr(cls_, "from_dict"):
    443     return cls_.from_dict(data)
--> 444 if pydantic is not None and issubclass(cls_, pydantic.BaseModel):  # pylint: disable=E1101
    445     return cls_(**data)
    446 if (
    447     dataclasses is not None
    448     and (not issubclass(cls_, MSONable))
    449     and dataclasses.is_dataclass(cls_)
    450 ):

File ~/software/miniconda/envs/quacc/lib/python3.10/abc.py:123, in ABCMeta.__subclasscheck__(cls, subclass)
    121 def __subclasscheck__(cls, subclass):
    122     """Override for issubclass(subclass, cls)."""
--> 123     return _abc_subclasscheck(cls, subclass)

TypeError: issubclass() arg 1 must be a class

Alternatives

I also tried MontyDecoder().process_decoded(store.as_dict()), but that led to the same error.

Andrew-S-Rosen avatar Jul 15 '23 16:07 Andrew-S-Rosen

@arosen93 is this still an issue? I see it was closed and then re-opened (and also note the discussion in #825 )

If you think there's some use case for a as_dict / from_dict method for StoreI'd be happy to discuss

rkingsbury avatar Jul 21 '23 17:07 rkingsbury

This is indeed still an issue! I closed it by mistake, and this was after trying @mkhorton's recommendation, which works for most stores except MontyStore in particular.

Unfortunately, I haven't had time to dig into why. This isn't a dealbreaker for me or anything, but I wanted to report it nonetheless since it's unexpected behavior.

Andrew-S-Rosen avatar Jul 21 '23 17:07 Andrew-S-Rosen

The underlying reason is because MontyStore is a function, not a class. It only becomes a class when instantiated. This causes some issues with (de)serialization.

from maggma.stores import MontyStore

print(MontyStore) # function
print(MontyStore('test')) # class

Andrew-S-Rosen avatar Feb 10 '24 01:02 Andrew-S-Rosen