class Config(object): """Config is the main class for this module; initialize the values with the default configuration, allows query/edit or save it's state.""" _instance = None OSX = 1 WINDOWS = 2 OTHER = 3 DIR_MODE = 0700 # Settings description param_definition = { 'build_user_dir': "Build the user data directory", 'plugins_enabled': "List of plugins enabled", 'lang': """The application language must be locale_COUNTRY or ':system:'. Examples: en_UK for English (United Kingdom) ca_ES for catalan es_ES for spanish """, 'copy': """Copy files to the collection folder policy: never never copy files always copy all the files remote only network files """, } # Default settings _default = { 'build_user_dir': True, 'plugins_enabled': [], 'lang': ':system:', 'copy': 'http', } def __init__(self, platform=None): """ Constructor for Config, initialize all the attributes""" if not Config._instance is None: raise Exception("Called more that once") Config.isntance = self self.__file__ = FILEPATH if platform is None: platform = Config.get_current_os() elif platform not in [Config.OSX, Config.WINDOWS, Config.OTHER]: raise Exception("Platform identifier %s not found" % platform) self.platform = platform self.resources = self.get_resources_path() self.home = ":auto:" # Parse all the parameters self._settings = [] self.storage = None self.set_settings(None) def save(self): """Persistences call, stores all the data at disc""" if self.storage is not None: self.storage.save(self._settings) def set(self, key, value): """Overrides a value of the settings or creates a new one""" self._settings[key] = value def set_home(self, home, memory=False): """Sets the home folder""" # self._settings['home'] = home self.home = home if not memory: self.storage = JSONStorage(self.get_home(), 'settings') self.reload() def set_settings(self, params): """Loads the parameters overriding the defaults""" settings = self._default.copy() if params is not None: if not isinstance(params, dict): raise ValueError("Params must be a dict") for defined in self.param_definition.keys(): if defined in params: settings[defined] = params[defined] logging.debug('Set configuration key ' + defined + ' to ' + str(params[defined])) self._settings = settings self.storage = JSONStorage(self.get_home(), 'settings') def get_settings(self): """Returns the settings""" return self._settings def reload(self): """Reloads the stored configuration (if exists)""" if self.storage is not None: self.set_settings(self.storage.load()) @staticmethod def get_instance(): """Returns the config instance""" if Config._instance is None: Config._instance = Config() return Config._instance def get_resources_path(self): """Returns the resources path, in MacOs is the folder Resources inside the bundle """ # determine if application is a script file or frozen exe application_path = '' if getattr(sys, 'frozen', False): application_path = os.path.dirname(sys.executable) if self.platform == Config.OSX: application_path = application_path.replace( 'MacOS', 'Resources' ) else: application_path = self.__file__.replace( os.path.join('collector', 'core'), '') return os.path.abspath(application_path) def get_appdata_path(self): """Returns the app data folder, this folder is inside the application""" return os.path.join(self.resources, 'data') def get_home(self): """Returns the user data path (home)""" value = self.home if value == ':auto:': value = Config.calculate_data_path(self.platform) elif value == ':resources:': value = self.get_appdata_path() return value get_data_path = get_home def get_plugin_path(self): """Returns the user plugin path""" return os.path.join(self.get_home(), 'plugins') @staticmethod def get_current_os(platform=None): """Try to discover the current OS""" if platform is None: platform = sys.platform platform = platform.lower() if platform in 'win32' or platform in 'win64': return Config.WINDOWS elif platform in 'darwin': return Config.OSX else: return Config.OTHER @staticmethod def calculate_data_path(platform=None): """ Calculates the user data directory, the exact location depends of the OS""" config_dir = None if platform is None: platform = Config.get_current_os() if platform == Config.WINDOWS: # TODO try to use distutils get_special_folder_path #config_dir = get_special_folder_path("CSIDL_APPDATA") config_dir = os.path.expanduser('~') config_dir = os.path.join(config_dir, 'Collector') elif platform == Config.OSX: config_dir = os.path.expanduser( '~/Library/Application Support/Collector') else: bdir = os.path.abspath(os.path.expanduser( os.environ.get('XDG_CONFIG_HOME', '~/.config'))) config_dir = os.path.join(bdir, 'collector') return config_dir def build_data_directory(self): """Creates the content inside the user data directory""" subfolders = ['user_plugins', 'config', 'collections'] import shutil base = self.get_home() if not os.path.exists(base): os.makedirs(base, mode=Config.DIR_MODE) appdata = self.get_appdata_path() # Do a full copy because no previus data exists for folder in subfolders: dst = os.path.join(base, folder) src = os.path.join(appdata, folder) shutil.copytree(src, dst) # TODO check if some data is missing? def conf(self, key): """Returns the setting value for the requested key""" if key != 'home': return self._settings[key] else: return self.get_home() get = conf
class PersistenceDict(Persistence): """Implementation of persistence using a python dictionary""" _autoid = 1 def __init__(self, schema, path, params=None): super(PersistenceDict, self).__init__(schema, path, params) self.items = [] self.data_storage = None self.memory = False self.class_ = type(str(schema.collection + "_" + schema.id), (FileDict,), {"schema": schema.id}) # configure self.configure() def configure(self): """Configures the storage system""" # Read params if self.params is None: self.params = {} params = self.params self.memory = params.get('memory', False) data = params.get('data', None) if self.path is not None: self.data_storage = JSONStorage( self.path, self.subcollection, self.memory) self.items = self.data_storage.load() if self.items is None: self.items = [] if data is not None: self.items = data self._calc_autoid() def _calc_autoid(self): """Searchs the max id used and set's the new autoid value""" maxid = 0 for i in self.items: maxid = max(maxid, i['id']) self._autoid = maxid + 1 def filter(self, fitlers): # TODO raise Exception("Not Implemented") def get_filters(self): #TODO return [] def get_last(self, count): """Returns the last items created, the number of items are defined with the count parameter, the items are orderded by last inserted""" result = self.items[-count:] # Reverse the count objects = [] result.reverse() for item in result: objects.append(FileDict(item)) return objects def get(self, _id): if isinstance(_id, str): _id = int(_id) for item in self.items: if _id == item['id']: return FileDict(item) return None def get_all(self, start_at, limit, order=None): """Returns all the items starting at *start_at*, the results could be limited whit *limit*""" result = [] objects = [] if limit == 0: objects = self.items[start_at:] else: objects = self.items[start_at:(start_at + limit)] for item in objects: result.append(FileDict(item)) return result def search(self, term): results = [] term = term.lower() for item in self.items: if item['title'].lower().find(term) != -1: results.append(FileDict(item)) return results def save(self, values): if 'id' in values: for item in self.items: if values['id'] == item['id']: item.update(values) else: values['id'] = self._autoid self._autoid += 1 self.items.append(values) self.commit() def delete(self, _id): for item in self.items: if item['id'] == _id: self.items.remove(item) self.commit() def commit(self): """Stores the changes""" if self.data_storage is not None: self.data_storage.save(self.items) def load_references(self, collections, item): if 'refLoaded' in item: return item = item.copy() item['refLoaded'] = True return item