deadsimplekv
module
+DeadSimpleKv. An extremely simple key-value storage system with cache +Copyright (C) 2019 Kevin Froman
+This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version.
+This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the +GNU General Public License for more details.
+You should have received a copy of the GNU General Public License +along with this program. +If not, see https://www.gnu.org/licenses/.
+Source code
+'''
+ DeadSimpleKv. An extremely simple key-value storage system with cache
+ Copyright (C) 2019 Kevin Froman
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+'''
+import json, time, math, os
+
+def _is_serializable(data):
+ try:
+ json.dumps(data)
+ return True
+ except TypeError:
+ return False
+
+class DeadSimpleKV:
+ def __init__(self, file_path=None, refresh_seconds=0, flush_seconds=0):
+ '''
+ Accepts a file path and refresh.
+ If file_path is not set, no data will be written to disk.
+ Refresh is an integer specifying how many seconds should pass before data is re-read from disk.
+ If refresh_seconds or flush_seconds are set to None they will not be done automatically
+ '''
+ temp_time = DeadSimpleKV._get_epoch() # Initialization time
+ self.file_path = file_path # The file path where we write our data in JSON format
+ self.refresh_seconds = refresh_seconds # How often to refresh the
+ self.flush_seconds = flush_seconds # How often to flush out when setting
+ self._data = {} # The key store (in memory)
+ self._last_refresh = temp_time # time last refreshed from disk
+ self._last_flush = temp_time # time last flushed to disk
+
+ try:
+ if os.path.exists(file_path):
+ self.refresh()
+ except TypeError:
+ pass
+
+ def get(self, key):
+ self._do_auto_refresh()
+ try:
+ return self._data[key]
+ except KeyError:
+ return None
+
+ def put(self, key, value):
+ '''Value setter. Will automatically flush if auto_flush is True and file_path is not None
+ Will return value error if either key or value are not JSON serializable
+ '''
+ self._data[key] = value # Set the key
+
+ # Check if key and value can be put in JSON
+ if not _is_serializable(key):
+ raise ValueError('%s is not JSON serializable' % (key,))
+ if not _is_serializable(value):
+ raise ValueError('%s is not JSON serializable' % (value,))
+ self._do_auto_flush()
+ return (key, value)
+
+ def delete(self, key):
+ '''Deletes value. Will automatically flush if auto_flush is True and file_path is not None'''
+ del self._data[key]
+ self._do_auto_flush()
+
+ def refresh(self):
+ '''Refresh data and then mark time read. Can be manually called'''
+ try:
+ self._data = json.loads(DeadSimpleKV._read_in(self.file_path))
+ except FileNotFoundError:
+ pass
+ self._last_refresh = DeadSimpleKV._get_epoch()
+
+ def flush(self):
+ '''Write out then mark time flushed. Can be manually called'''
+ DeadSimpleKV._write_out(self.file_path, json.dumps(self._data))
+ self._last_flush = DeadSimpleKV._get_epoch()
+
+ def _do_auto_flush(self):
+ if self.flush_seconds is not None and self.file_path is not None:
+ # flush if automatic and it is time to do so
+ if DeadSimpleKV._get_epoch() - self._last_flush >= self.flush_seconds:
+ self.flush()
+
+ def _do_auto_refresh(self):
+ if self.refresh_seconds is not None and self.file_path is not None:
+ # refresh if automatic and time to do so
+ if DeadSimpleKV._get_epoch() - self._last_refresh >= self.refresh_seconds:
+ self.refresh()
+
+ @staticmethod
+ def _get_epoch():
+ return math.floor(time.time())
+
+ @staticmethod
+ def _write_out(file_path, data):
+ '''Write out the raw data'''
+ with open(file_path, 'w') as write_file:
+ write_file.write(data)
+
+ @staticmethod
+ def _read_in(file_path):
+ '''Read in raw data'''
+ with open(file_path, 'r') as read_file:
+ return read_file.read()
+Classes
+-
+
+class DeadSimpleKV +
+-
+
+++
Source code
+
+class DeadSimpleKV: + def __init__(self, file_path=None, refresh_seconds=0, flush_seconds=0): + ''' + Accepts a file path and refresh. + If file_path is not set, no data will be written to disk. + Refresh is an integer specifying how many seconds should pass before data is re-read from disk. + If refresh_seconds or flush_seconds are set to None they will not be done automatically + ''' + temp_time = DeadSimpleKV._get_epoch() # Initialization time + self.file_path = file_path # The file path where we write our data in JSON format + self.refresh_seconds = refresh_seconds # How often to refresh the + self.flush_seconds = flush_seconds # How often to flush out when setting + self._data = {} # The key store (in memory) + self._last_refresh = temp_time # time last refreshed from disk + self._last_flush = temp_time # time last flushed to disk + + try: + if os.path.exists(file_path): + self.refresh() + except TypeError: + pass + + def get(self, key): + self._do_auto_refresh() + try: + return self._data[key] + except KeyError: + return None + + def put(self, key, value): + '''Value setter. Will automatically flush if auto_flush is True and file_path is not None + Will return value error if either key or value are not JSON serializable + ''' + self._data[key] = value # Set the key + + # Check if key and value can be put in JSON + if not _is_serializable(key): + raise ValueError('%s is not JSON serializable' % (key,)) + if not _is_serializable(value): + raise ValueError('%s is not JSON serializable' % (value,)) + self._do_auto_flush() + return (key, value) + + def delete(self, key): + '''Deletes value. Will automatically flush if auto_flush is True and file_path is not None''' + del self._data[key] + self._do_auto_flush() + + def refresh(self): + '''Refresh data and then mark time read. Can be manually called''' + try: + self._data = json.loads(DeadSimpleKV._read_in(self.file_path)) + except FileNotFoundError: + pass + self._last_refresh = DeadSimpleKV._get_epoch() + + def flush(self): + '''Write out then mark time flushed. Can be manually called''' + DeadSimpleKV._write_out(self.file_path, json.dumps(self._data)) + self._last_flush = DeadSimpleKV._get_epoch() + + def _do_auto_flush(self): + if self.flush_seconds is not None and self.file_path is not None: + # flush if automatic and it is time to do so + if DeadSimpleKV._get_epoch() - self._last_flush >= self.flush_seconds: + self.flush() + + def _do_auto_refresh(self): + if self.refresh_seconds is not None and self.file_path is not None: + # refresh if automatic and time to do so + if DeadSimpleKV._get_epoch() - self._last_refresh >= self.refresh_seconds: + self.refresh() + + @staticmethod + def _get_epoch(): + return math.floor(time.time()) + + @staticmethod + def _write_out(file_path, data): + '''Write out the raw data''' + with open(file_path, 'w') as write_file: + write_file.write(data) + + @staticmethod + def _read_in(file_path): + '''Read in raw data''' + with open(file_path, 'r') as read_file: + return read_file.read()
Methods
+-
+
+def __init__(self, file_path=None, refresh_seconds=0, flush_seconds=0) +
+-
+
+Accepts a file path and refresh. +If file_path is not set, no data will be written to disk. +Refresh is an integer specifying how many seconds should pass before data is re-read from disk. +If refresh_seconds or flush_seconds are set to None they will not be done automatically
++Source code
+
+def __init__(self, file_path=None, refresh_seconds=0, flush_seconds=0): + ''' + Accepts a file path and refresh. + If file_path is not set, no data will be written to disk. + Refresh is an integer specifying how many seconds should pass before data is re-read from disk. + If refresh_seconds or flush_seconds are set to None they will not be done automatically + ''' + temp_time = DeadSimpleKV._get_epoch() # Initialization time + self.file_path = file_path # The file path where we write our data in JSON format + self.refresh_seconds = refresh_seconds # How often to refresh the + self.flush_seconds = flush_seconds # How often to flush out when setting + self._data = {} # The key store (in memory) + self._last_refresh = temp_time # time last refreshed from disk + self._last_flush = temp_time # time last flushed to disk + + try: + if os.path.exists(file_path): + self.refresh() + except TypeError: + pass
+ +def delete(self, key) +
+-
+
+Deletes value. Will automatically flush if auto_flush is True and file_path is not None
++Source code
+
+def delete(self, key): + '''Deletes value. Will automatically flush if auto_flush is True and file_path is not None''' + del self._data[key] + self._do_auto_flush()
+ +def flush(self) +
+-
+
+Write out then mark time flushed. Can be manually called
++Source code
+
+def flush(self): + '''Write out then mark time flushed. Can be manually called''' + DeadSimpleKV._write_out(self.file_path, json.dumps(self._data)) + self._last_flush = DeadSimpleKV._get_epoch()
+ +def get(self, key) +
+-
+
+++
Source code
+
+def get(self, key): + self._do_auto_refresh() + try: + return self._data[key] + except KeyError: + return None
+ +def put(self, key, value) +
+-
+
+Value setter. Will automatically flush if auto_flush is True and file_path is not None +Will return value error if either key or value are not JSON serializable
++Source code
+
+def put(self, key, value): + '''Value setter. Will automatically flush if auto_flush is True and file_path is not None + Will return value error if either key or value are not JSON serializable + ''' + self._data[key] = value # Set the key + + # Check if key and value can be put in JSON + if not _is_serializable(key): + raise ValueError('%s is not JSON serializable' % (key,)) + if not _is_serializable(value): + raise ValueError('%s is not JSON serializable' % (value,)) + self._do_auto_flush() + return (key, value)
+ +def refresh(self) +
+-
+
+Refresh data and then mark time read. Can be manually called
++Source code
+
+def refresh(self): + '''Refresh data and then mark time read. Can be manually called''' + try: + self._data = json.loads(DeadSimpleKV._read_in(self.file_path)) + except FileNotFoundError: + pass + self._last_refresh = DeadSimpleKV._get_epoch()
+
+