Ejemplo n.º 1
0
class GflConf(object, metaclass=GflConfMetadata):

    # Parameters that can be modified at run time
    __props = {}
    # Parameters that are read from a configuration file and cannot be changed at run time
    __readonly_props = {}

    __home_dir = PathUtils.join(PathUtils.user_home_dir(), ".gfl")
    __data_dir = PathUtils.join(__home_dir, "data")
    __logs_dir = PathUtils.join(__home_dir, "logs")
    __cache_dir = PathUtils.join(__home_dir, "cache")
    __temp_dir = gfl_tempdir

    @classmethod
    def load(cls) -> None:
        """
        load config properties from disk file.

        :return:
        """
        base_config_path = PathUtils.join(PathUtils.src_root_dir(),
                                          "resources", "config.yaml")
        with open(base_config_path) as f:
            cls.__readonly_props = yaml.load(f, Loader=yaml.SafeLoader)

        path = PathUtils.join(cls.home_dir, "config.yaml")
        if os.path.exists(path):
            with open(path) as f:
                config_data = yaml.load(f, Loader=yaml.SafeLoader)
                cls.__readonly_props.update(config_data)

        if os.path.exists(cls.logs_dir):
            cls.load_logging_config()
        else:
            warnings.warn("cannot found logs dir.")

    @classmethod
    def load_logging_config(cls) -> None:
        """

        """
        logging_config_path = PathUtils.join(PathUtils.src_root_dir(),
                                             "resources", "logging.yaml")
        with open(logging_config_path) as f:
            text = f.read().replace("{logs_root}", GflConf.logs_dir)
            data = yaml.load(text, yaml.SafeLoader)

        if cls.get_property("debug"):
            data["root"]["level"] = "DEBUG"
            data["loggers"]["gfl"]["level"] = "DEBUG"

        logging.config.dictConfig(data)

    @classmethod
    def generate_config(cls, path: str = None) -> None:
        """
        generate config file in ``path``.

        :param path: the config file path, if it's None, will be replaced by './config.yaml'.
        :return:
        """
        if path is None:
            path = "config.yaml"
        src_path = PathUtils.join(PathUtils.src_root_dir(), "resources",
                                  "config.yaml")
        shutil.copy(src_path, path)

    @classmethod
    def set_config(cls, d: dict) -> None:
        """
        Batch update config properties. Generally, this method is not recommend.

        :param d: a dict represent config properties.
        :return:
        """
        cls.__props.update(d.copy())

    @classmethod
    def get_property(cls, key, default=None):
        """
        Get the value of readonly parameters.

        :param key: a string of the key to get the value
        :param default: return value if key not found
        """
        op_res, val = cls.__get_from_dict(cls.__props, cls.__split_key(key),
                                          default)
        if op_res:
            return val
        return cls.__get_from_dict(cls.__readonly_props, cls.__split_key(key),
                                   default)[1]

    @classmethod
    def set_property(cls, key, value):
        """
        Set parameters at run time.

        :param key:
        :param value:
        :return:
        """
        cls.__set_to_dict(cls.__props, cls.__split_key(key), value)

    @classmethod
    def remove_property(cls, key):
        cls.__remove_from_dict(cls.__props, cls.__split_key(key))

    @classmethod
    def __split_key(cls, key: str):
        if key is None or key.strip() == "":
            raise ValueError("key cannot be none or empty.")
        return key.split(".")

    @classmethod
    def __exists_in_dict(cls, d: dict, k_seq: list):
        if k_seq is None or len(k_seq) == 0:
            return False
        for k in k_seq:
            if k in d:
                d = d[k]
            else:
                return False
        return True

    @classmethod
    def __get_from_dict(cls, d: dict, k_seq: list, default=None):
        if k_seq is None or len(k_seq) == 0:
            raise ValueError("key cannot be none or empty")
        for k in k_seq:
            if k in d:
                d = d[k]
            else:
                return False, default
        return True, d

    @classmethod
    def __remove_from_dict(cls, d: dict, k_seq: list):
        if k_seq is None or len(k_seq) == 0:
            raise ValueError("key cannot be none or empty")
        for k in k_seq[:-1]:
            if k not in d:
                return False
            d = d[k]
        try:
            del d[k_seq[-1]]
            return True
        except:
            return False

    @classmethod
    def __set_to_dict(cls, d: dict, k_seq: list, value):
        if k_seq is None or len(k_seq) == 0:
            raise ValueError("key cannot be none or empty")
        for k in k_seq[:-1]:
            if k not in d:
                d[k] = {}
            d = d[k]
        d[k_seq[-1]] = value
Ejemplo n.º 2
0
class GflConf(object, metaclass=GflConfMetadata):

    # Parameters that can be modified at run time
    props = {}
    # Parameters that are read from a configuration file and cannot be changed at run time
    readonly_props = {}
    # home directory
    __home_dir = PathUtils.join(PathUtils.user_home_dir(), ".gfl")
    __data_dir = PathUtils.join(__home_dir, "data")
    __logs_dir = PathUtils.join(__home_dir, "logs")
    __cache_dir = PathUtils.join(__home_dir, "cache")

    @classmethod
    def reload(cls):
        """
        Reload readonly parameters from the YAML file.
        :return:
        """
        with open(PathUtils.join(cls.__home_dir, "conf.yaml"), "r") as f:
            cls.readonly_props = yaml.safe_load(f.read())

    @classmethod
    def load_logging_conf(cls):
        logging.config.fileConfig(
            PathUtils.join(cls.__home_dir, "logging.conf"))

    @classmethod
    def get_property(cls, key, default=None):
        """
        Get the value of readonly parameters.

        :param key: a string of the key to get the value
        """
        op_res, readonly_val = cls.__get_from_dict(cls.readonly_props,
                                                   cls.__split_key(key),
                                                   default)
        if op_res:
            return readonly_val
        return cls.__get_from_dict(cls.readonly_props, cls.__split_key(key),
                                   default)[1]

    @classmethod
    def set_property(cls, key, value):
        """
        Set parameters at run time.
        """
        k_seq = cls.__split_key(key)
        if cls.__exists_in_dict(cls.readonly_props, k_seq):
            raise ValueError("readonly key[%d] cannot be modified." % key)
        cls.__set_to_dict(cls.props, cls.__split_key(key), value)

    @classmethod
    def init_conf(cls):
        """
        Serialize default configuration into a YAML stream.
        """
        with open(PathUtils.join(cls.__home_dir, "conf.yaml"), "w") as f:
            yaml.safe_dump(default_conf, f)

    @classmethod
    def __split_key(cls, key: str):
        if key is None or key.strip() == "":
            raise ValueError("key cannot be none or empty.")
        return key.split(".")

    @classmethod
    def __exists_in_dict(cls, d: dict, k_seq: list):
        if k_seq is None or len(k_seq) == 0:
            return False
        for k in k_seq:
            if k in d:
                d = d[k]
            else:
                return False
        return True

    @classmethod
    def __get_from_dict(cls, d: dict, k_seq: list, default=None):
        if k_seq is None or len(k_seq) == 0:
            raise ValueError("key cannot be none or empty")
        for k in k_seq:
            if k in d:
                d = d[k]
            else:
                return False, default
        return True, d

    @classmethod
    def __set_to_dict(cls, d: dict, k_seq: list, value):
        if k_seq is None or len(k_seq) == 0:
            raise ValueError("key cannot be none or empty")
        for k in k_seq[:-1]:
            if k not in d:
                d[k] = {}
            d = d[k]

        d[k_seq[-1]] = value