123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- """
- Contains the :class:`base class <tinydb.storages.Storage>` for storages and
- implementations.
- """
- from abc import ABCMeta, abstractmethod
- import os
- from .utils import with_metaclass
- try:
- import ujson as json
- except ImportError:
- import json
- def touch(fname, create_dirs):
- if create_dirs:
- base_dir = os.path.dirname(fname)
- if not os.path.exists(base_dir):
- os.makedirs(base_dir)
- with open(fname, 'a'):
- os.utime(fname, None)
- class Storage(with_metaclass(ABCMeta, object)):
- """
- The abstract base class for all Storages.
- A Storage (de)serializes the current state of the database and stores it in
- some place (memory, file on disk, ...).
- """
- # Using ABCMeta as metaclass allows instantiating only storages that have
- # implemented read and write
- @abstractmethod
- def read(self):
- """
- Read the last stored state.
- Any kind of deserialization should go here.
- Return ``None`` here to indicate that the storage is empty.
- :rtype: dict
- """
- raise NotImplementedError('To be overridden!')
- @abstractmethod
- def write(self, data):
- """
- Write the current state of the database to the storage.
- Any kind of serialization should go here.
- :param data: The current state of the database.
- :type data: dict
- """
- raise NotImplementedError('To be overridden!')
- def close(self):
- """
- Optional: Close open file handles, etc.
- """
- pass
- class JSONStorage(Storage):
- """
- Store the data in a JSON file.
- """
- def __init__(self, path, create_dirs=False, **kwargs):
- """
- Create a new instance.
- Also creates the storage file, if it doesn't exist.
- :param path: Where to store the JSON data.
- :type path: str
- """
- super(JSONStorage, self).__init__()
- touch(path, create_dirs=create_dirs) # Create file if not exists
- self.kwargs = kwargs
- self._handle = open(path, 'r+')
- def close(self):
- self._handle.close()
- def read(self):
- # Get the file size
- self._handle.seek(0, os.SEEK_END)
- size = self._handle.tell()
- if not size:
- # File is empty
- return None
- else:
- self._handle.seek(0)
- return json.load(self._handle)
- def write(self, data):
- self._handle.seek(0)
- serialized = json.dumps(data, **self.kwargs)
- self._handle.write(serialized)
- self._handle.flush()
- os.fsync(self._handle.fileno())
- self._handle.truncate()
- class MemoryStorage(Storage):
- """
- Store the data as JSON in memory.
- """
- def __init__(self):
- """
- Create a new instance.
- """
- super(MemoryStorage, self).__init__()
- self.memory = None
- def read(self):
- return self.memory
- def write(self, data):
- self.memory = data
|