Source code for pymatgen.util.serialization

# coding: utf-8
# Copyright (c) Pymatgen Development Team.
# Distributed under the terms of the MIT License.

"""
Most features of this module has been moved to monty. Please refer to
monty.json and monty.serialization documentation.
"""

import json
import functools
import pickle

from pymatgen.core.periodic_table import Element


__author__ = "Shyue Ping Ong"
__copyright__ = "Copyright 2012, The Materials Project"
__version__ = "0.1"
__maintainer__ = "Shyue Ping Ong"
__email__ = "shyuep@gmail.com"
__date__ = "Apr 30, 2012"


[docs]def pmg_serialize(method): """ Decorator for methods that add MSON serializations keys to the dictionary. See documentation of MSON for more details """ @functools.wraps(method) def wrapper(*args, **kwargs): self = args[0] d = method(*args, **kwargs) # Add @module and @class d["@module"] = self.__class__.__module__ d["@class"] = self.__class__.__name__ return d return wrapper
[docs]def json_pretty_dump(obj, filename): """ Serialize obj as a JSON formatted stream to the given filename ( pretty printing version) """ with open(filename, "wt") as fh: json.dump(obj, fh, indent=4, sort_keys=4)
[docs]class PmgPickler(pickle.Pickler): """ Persistence of External Objects as described in section 12.1.5.1 of https://docs.python.org/3/library/pickle.html """
[docs] def persistent_id(self, obj): """Instead of pickling as a regular class instance, we emit a persistent ID.""" if isinstance(obj, Element): # Here, our persistent ID is simply a tuple, containing a tag and # a key return obj.__class__.__name__, obj.symbol else: # If obj does not have a persistent ID, return None. This means obj # needs to be pickled as usual. return None
[docs]class PmgUnpickler(pickle.Unpickler): """ Persistence of External Objects as described in section 12.1.5.1 of https://docs.python.org/3/library/pickle.html """
[docs] def persistent_load(self, pid): """ This method is invoked whenever a persistent ID is encountered. Here, pid is the tuple returned by PmgPickler. """ try: type_tag, key_id = pid except Exception: # Sometimes we get a string such as ('Element', u'C') instead # of a real tuple. Use ast to evalute the expression (much safer # than eval). import ast type_tag, key_id = ast.literal_eval(pid) if type_tag == "Element": return Element(key_id) else: # Always raises an error if you cannot return the correct object. # Otherwise, the unpickler will think None is the object referenced # by the persistent ID. raise pickle.UnpicklingError( "unsupported persistent object with pid %s" % pid)
[docs]def pmg_pickle_load(filobj, **kwargs): r""" Loads a pickle file and deserialize it with PmgUnpickler. Args: filobj: File-like object **kwargs: Any of the keyword arguments supported by PmgUnpickler Returns: Deserialized object. """ return PmgUnpickler(filobj, **kwargs).load()
[docs]def pmg_pickle_dump(obj, filobj, **kwargs): r""" Dump an object to a pickle file using PmgPickler. Args: obj : Object to dump. fileobj: File-like object **kwargs: Any of the keyword arguments supported by PmgPickler """ return PmgPickler(filobj, **kwargs).dump(obj)
[docs]class SlotPickleMixin: """ This mixin makes it possible to pickle/unpickle objects with __slots__ defined. """ def __getstate__(self): return dict( (slot, getattr(self, slot)) for slot in self.__slots__ if hasattr(self, slot) ) def __setstate__(self, state): for slot, value in state.items(): setattr(self, slot, value)