# -*- coding: utf-8 -*- """ The postman project - storage.py This file is released under the BSD license, see LICENSE for more information. Francisco de Borja Lopez Rio - Soluciones Informaticas Codigo23 S.L.U. - http://codigo23.net """ import os, errno, json class JsonStorage(): """ Json-based storage. """ def __init__(self, path='storage.json'): if os.path.isdir(path): raise IOError(path, ' is a directory, exiting') self.path = path def exists(self): return os.path.exists(self.path) def create(self): """ Ensure all the subdirectories in the path to the storage file exist """ try: os.makedirs(os.path.dirname(self.path)) except OSError, e: # If the dir already exists do not complain, if it is # any other error, raise the exception if e.errno != errno.EEXIST: raise def jsonize(self, obj): """ Convert objects to a dictionary of their representation Based on the exmplaes from Doyg Hellmann: http://www.doughellmann.com/PyMOTW/json/#working-with-your-own-types """ jobj = { '__class__':obj.__class__.__name__, '__module__':obj.__module__, } jobj.update(obj.__dict__) return jobj def dejsonize(self, jobj): """ Convert some data that has been "jsonized" to the original python object. Again, based on the examples from Doug Hellmann """ if '__class__' in jobj: class_name = jobj.pop('__class__') module_name = jobj.pop('__module__') module = __import__(module_name) class_ = getattr(module, class_name) args = dict((key.encode('ascii'), value) \ for key, value in jobj.items()) return class_(**args) return jobj def write(self, data): if not self.exists(): # ensure the path to the storage file exists self.create() with open(self.path, 'w') as storage: json.dump(data, storage, sort_keys=True, indent=4, default=self.jsonize) return True return False def read(self): with open(self.path, 'r') as storage: try: data = json.load(storage,object_hook=self.dejsonize) except ValueError: # if no json data could be imported, the file could be # damaged or perhaps it does not containg json-encoded # data, simply return an empty string # # FIXME: we should notify the user about the problem return '' return data def delete(self): """ Remove the storage file """ if self.exists(): os.remove(self.path) return True return False