Source code for pymatgen.util.serialization

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

from __future__ import unicode_literals, division, print_function

import json
import functools
import pickle

from pymatgen.core.periodic_table import Element

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

__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 as exc: # 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): """ 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): """ Dump an object to a pickle file using PmgPickler. Args: obj (object): 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(object): """ 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)