#!/usr/bin/python # -*- coding: utf-8 -*- # Hive Appier Framework # Copyright (c) 2008-2024 Hive Solutions Lda. # # This file is part of Hive Appier Framework. # # Hive Appier Framework is free software: you can redistribute it and/or modify # it under the terms of the Apache License as published by the Apache # Foundation, either version 2.0 of the License, or (at your option) any # later version. # # Hive Appier Framework 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 # Apache License for more details. # # You should have received a copy of the Apache License along with # Hive Appier Framework. If not, see . __author__ = "João Magalhães " """ The author(s) of the module """ __copyright__ = "Copyright (c) 2008-2024 Hive Solutions Lda." """ The copyright for the module """ __license__ = "Apache License, Version 2.0" """ The license for the module """ import os import shelve import pickle from . import util from . import common from . import config from . import redisdb from . import component from . import exceptions class Preferences(component.Component): def __init__(self, name="preferences", owner=None, *args, **kwargs): component.Component.__init__(self, name=name, owner=owner, *args, **kwargs) load = kwargs.pop("load", True) if load: self.load(*args, **kwargs) def __getitem__(self, key): return self.get(key, strict=True) def __setitem__(self, key, value): self.set(key, value) def __delitem__(self, key): self.delete(key) @classmethod def new(cls, *args, **kwargs): return cls(*args, **kwargs) def get(self, name, default=None, strict=False, *args, **kwargs): return self._get(name, default=default, strict=strict, *args, **kwargs) def set(self, name, value, *args, **kwargs): flush = kwargs.get("flush", True) result = self._set(name, value, *args, **kwargs) if flush: self.flush() return result def delete(self, name, *args, **kwargs): return self._delete(name, *args, **kwargs) def flush(self, *args, **kwargs): return self._flush(*args, **kwargs) def clear(self, *args, **kwargs): return self._clear(*args, **kwargs) def _get(self, name, default=None, strict=False, *args, **kwargs): raise exceptions.NotImplementedError() def _set(self, name, value, *args, **kwargs): raise exceptions.NotImplementedError() def _delete(self, name, *args, **kwargs): raise exceptions.NotImplementedError() def _flush(self, *args, **kwargs): raise exceptions.NotImplementedError() def _clear(self, *args, **kwargs): raise exceptions.NotImplementedError() class MemoryPreferences(Preferences): def __init__(self, name="memory", owner=None, *args, **kwargs): Preferences.__init__(self, name=name, owner=owner, *args, **kwargs) def _load(self, *args, **kwargs): Preferences._load(self, *args, **kwargs) self._preferences = dict() def _unload(self, *args, **kwargs): Preferences._unload(self, *args, **kwargs) self._preferences = None def _get(self, name, default=None, strict=False, *args, **kwargs): if strict: return self._preferences[name] return self._preferences.get(name, default) def _set(self, name, value, *args, **kwargs): self._preferences[name] = value def _delete(self, name, *args, **kwargs): del self._preferences[name] def _flush(self, *args, **kwargs): pass def _clear(self, *args, **kwargs): self._preferences.clear() class FilePreferences(Preferences): def __init__(self, name="file", owner=None, *args, **kwargs): Preferences.__init__(self, name=name, owner=owner, *args, **kwargs) def _load(self, *args, **kwargs): Preferences._load(self, *args, **kwargs) self.preferences_path = kwargs.pop("preferences_path", None) self._open() def _unload(self, *args, **kwargs): Preferences._unload(self, *args, **kwargs) self._close() def _get(self, name, default=None, strict=False, *args, **kwargs): if strict: return self._shelve[name] return self._shelve.get(name, default) def _set(self, name, value, *args, **kwargs): self._shelve[name] = value def _delete(self, name, *args, **kwargs): del self._shelve[name] def _flush(self, *args, **kwargs): self._sync() def _clear(self, *args, **kwargs): if not os.path.exists(self.preferences_path): return os.remove(self.preferences_path) def _open(self): self._ensure_path() self._shelve = shelve.open(self.preferences_path, protocol=2, writeback=True) def _close(self): if not self._shelve: return self._shelve.close() self._shelve = None def _ensure_path(self): if self.preferences_path: return app_path = common.base().get_base_path() util.verify(not app_path == None, message="No app path available") preferences_path = os.path.join(app_path, "preferences.shelve") preferences_path = config.conf("PREFERENCES_PATH", preferences_path) preferences_path = os.path.expanduser(preferences_path) preferences_path = os.path.abspath(preferences_path) preferences_path = os.path.normpath(preferences_path) self.preferences_path = preferences_path def _sync(self, secure=None): if secure == None: secure = self._db_secure() if secure: self._shelve.close() self._open() else: self._shelve.sync() def _db_secure(self): return self._db_type() == "dbm" def _db_type(self): shelve_cls = type(self._shelve.dict) shelve_dbm = shelve_cls.__name__ return shelve_dbm class RedisPreferences(Preferences): SERIALIZER = pickle """ The serializer to be used for the values contained in the preferences (used on top of the class) """ PREFIX = "appier_preferences_" """The default prefix value that is going to be prepended to the key name to handle preferences""" def __init__(self, name="redis", owner=None, *args, **kwargs): Preferences.__init__(self, name=name, owner=owner, *args, **kwargs) def _load(self, *args, **kwargs): Preferences._load(self, *args, **kwargs) self._serializer = kwargs.pop("serializer", self.__class__.SERIALIZER) self._prefix = kwargs.pop("prefix", self.__class__.PREFIX) self._prefix += self.owner.name + "_" if self.owner else "" self._open() def _unload(self, *args, **kwargs): Preferences._unload(self, *args, **kwargs) self._close() def _get(self, name, default=None, strict=False, *args, **kwargs): name = self._fqn(name) value = self._redis.get(name) if not value: if strict: raise KeyError("not found") return default try: return self._serializer.loads(value) except Exception: return default def _set(self, name, value, *args, **kwargs): name = self._fqn(name) value = self._serializer.dumps(value) self._redis.set(name, value) def _delete(self, name, *args, **kwargs): name = self._fqn(name) self._redis.delete(name) def _flush(self, *args, **kwargs): pass def _clear(self, *args, **kwargs): self._redis.flushdb() def _open(self): self._redis = redisdb.get_connection() self._redis.ping() def _close(self): self._redis = None def _fqn(self, name): return self._prefix + name