Source code for core.json_config

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Proxy to abstract access to JSON configuration and gracefully handle missing
keys."""

import json
import os

from . import log


[docs]class JSONConfiguration(object): """Proxy for JSON-based configuration files.""" def __init__(self, filename, default=None, warn=True): """ Constructor for JSONConfiguration. Args: filename: JSON filename to load data from. Use None to only use object from default. default: default value to use in case loading fails. warn (bool): Log a warning if the file is missing, default True. """ self.filename = filename self.data = default if default else {} if filename is None: return if not os.path.isfile(filename): if warn: log.w("JSONConfiguration: File " + filename + " does not exist") return try: with open(filename, encoding="utf-8") as file: self.data = json.load(file) except Exception: log.e('Note: Failed to read JSON from ' + filename + ', ignoring data - details follow', stack=True)
[docs] @staticmethod def from_text(text): """Create a JSONConfiguration object from a string.""" return JSONConfiguration(None, json.loads(text))
[docs] def save_data(self): """Saves the data to the original JSON file. Has no effect if no filename was given during construction.""" if self.filename: with open(self.filename, 'w', encoding="utf-8") as file: json.dump(self.data, file, indent=2)
[docs] def get(self, path, default=None): """ Retrieves a value from the configuration. Returns default if the path does not exist. Args: path: ``/``-delimited path to the string. default: value returned if path does not exist. """ try: path = path.split('/') result = self.data for p in path: result = result[p] return result except KeyError: return default
[docs] def has_value(self, path): """Returns True if the path exists in the configuration.""" return self.get_value(path) is not None
[docs] def get_value(self, path, default=None): """ Retrieves a value from the configuration. Returns default if the path does not exist. Args: path: ``/``-delimited path to the string. default: value returned if path does not exist. """ return self.get(path, default)
[docs] def get_string(self, path): """ Retrieves a value from the configuration. Returns an empty string if the path does not exist. Args: path: ``/``-delimited path to the string. """ return self.get_value(path, "")
[docs] def get_number(self, path): """ Retrieves a value from the configuration. Returns 0 if the path does not exist. Args: path: ``/``-delimited path to the string. """ return self.get_value(path, 0)
[docs] def get_bool(self, path): """ Retrieves a value from the configuration. Returns False if the path does not exist. Args: path: ``/``-delimited path to the string. """ return self.get_value(path, False)
[docs] def get_list(self, path): """ Retrieves a value from the configuration. Returns an empty list if the path does not exist. Args: path: ``/``-delimited path to the string. """ return self.get_value(path, [])
[docs] def get_dict(self, path): """ Retrieves a value from the configuration. Returns an empty dictionary if the path does not exist. Args: path: ``/``-delimited path to the string. """ return self.get_value(path, {})
[docs] def set_value(self, key, value): """ Writes a value to a key. Note: Arbitrary paths not supported - you must refresh entire key. Args: key: the key to save the value under. value: the value to save. """ self.__setitem__(key, value) # pylint: disable=unnecessary-dunder-call
def __getitem__(self, key): """Accessor for indexing directly into the configuration.""" return self.get_value(key) def __setitem__(self, key, value): """Accessor for writing into the configuration with indexing.""" self.data[key] = value