def find_loader(path_or_stream, parser_or_type=None, is_path_=False): """ Find out parser object appropriate to load configuration from a file of given path or file or file-like object. :param path_or_stream: Configuration file path or file or file-like object :param parser_or_type: Forced configuration parser type or parser object itself :param is_path_: Specify True if given `path_or_stream` is a file path :return: An instance of a class inherits :class:`~anyconfig.backend.base.Parser` or None """ if anyconfig.backends.is_parser(parser_or_type): return parser_or_type try: psr = anyconfig.backends.find_parser(path_or_stream, forced_type=parser_or_type, is_path_=is_path_) LOGGER.debug("Using config parser: %r [%s]", psr, psr.type()) return psr() # TBD: Passing initialization arguments. except (ValueError, UnknownParserTypeError, UnknownFileTypeError): raise
def single_load(path_or_stream, ac_parser=None, ac_template=False, ac_context=None, **options): """ Load single config file. :param path_or_stream: Configuration file path or file / file-like object :param ac_parser: Forced parser type or parser object :param ac_template: Assume configuration file may be a template file and try to compile it AAR if True :param ac_context: A dict presents context to instantiate template :param options: Optional keyword arguments such as: - Common options: - ac_namedtuple: Convert result to nested namedtuple object if True - ac_schema: JSON schema file path to validate given config file - Common backend options: - ignore_missing: Ignore and just return empty result if given file (``path_or_stream``) does not exist. - Backend specific options such as {"indent": 2} for JSON backend :return: dict or dict-like object supports merge operations """ is_path_ = is_path(path_or_stream) if is_path_: path_or_stream = anyconfig.utils.ensure_expandusr(path_or_stream) filepath = path_or_stream else: filepath = anyconfig.utils.get_path_from_stream(path_or_stream) psr = find_loader(path_or_stream, ac_parser, is_path_) if psr is None: return None schema = _load_schema(ac_template=ac_template, ac_context=ac_context, **options) options["ac_schema"] = None # It's not needed now. LOGGER.info("Loading: %s", filepath) if ac_template and filepath is not None: try: LOGGER.debug("Compiling: %s", filepath) content = anyconfig.template.render(filepath, ac_context) cnf = psr.loads(content, **options) return _maybe_validated(cnf, schema, **options) except Exception as exc: LOGGER.warning( "Failed to compile %s, fallback to no template " "mode, exc=%r", path_or_stream, exc) cnf = psr.load(path_or_stream, **options) return _maybe_validated(cnf, schema, **options)
def find_loader(path_or_stream, parser_or_type=None, is_path_=False): """ Find out config parser object appropriate to load from a file of given path or file/file-like object. :param path_or_stream: Configuration file path or file / file-like object :param parser_or_type: Forced configuration parser type or parser object :param is_path_: True if given `path_or_stream` is a file path :return: Config parser instance or None """ if anyconfig.backends.is_parser(parser_or_type): return parser_or_type (psr, err) = anyconfig.backends.find_parser(path_or_stream, parser_or_type, is_path_=is_path_) if err: LOGGER.error(err) if psr is None: if parser_or_type is None: LOGGER.warning("No parser (type) was given!") else: LOGGER.warning("Parser %s was not found!", str(parser_or_type)) return None LOGGER.debug("Using config parser: %r [%s]", psr, psr.type()) return psr() # TBD: Passing initialization arguments.
def single_load(path_or_stream, ac_parser=None, ac_template=False, ac_context=None, **options): """ Load single config file. :param path_or_stream: Configuration file path or file / file-like object :param ac_parser: Forced parser type or parser object :param ac_template: Assume configuration file may be a template file and try to compile it AAR if True :param ac_context: A dict presents context to instantiate template :param options: Optional keyword arguments such as: - Common options: - ac_namedtuple: Convert result to nested namedtuple object if True - ac_schema: JSON schema file path to validate given config file - Common backend options: - ignore_missing: Ignore and just return empty result if given file (``path_or_stream``) does not exist. - Backend specific options such as {"indent": 2} for JSON backend :return: dict or dict-like object supports merge operations """ is_path_ = is_path(path_or_stream) if is_path_: path_or_stream = anyconfig.utils.ensure_expandusr(path_or_stream) filepath = path_or_stream else: filepath = anyconfig.utils.get_path_from_stream(path_or_stream) psr = find_loader(path_or_stream, ac_parser, is_path_) if psr is None: return None schema = _load_schema(ac_template=ac_template, ac_context=ac_context, **options) options["ac_schema"] = None # It's not needed now. LOGGER.info("Loading: %s", filepath) if ac_template and filepath is not None: try: LOGGER.debug("Compiling: %s", filepath) content = anyconfig.template.render(filepath, ac_context) cnf = psr.loads(content, **options) return _maybe_validated(cnf, schema, **options) except Exception as exc: LOGGER.warning("Failed to compile %s, fallback to no template " "mode, exc=%r", path_or_stream, exc) cnf = psr.load(path_or_stream, **options) return _maybe_validated(cnf, schema, **options)
def mk_dump_dir_if_not_exist(f): """ Make dir to dump f if that dir does not exist. :param f: path of file to dump """ dumpdir = os.path.dirname(f) if not os.path.exists(dumpdir): logging.debug("Creating output dir as it's not found: " + dumpdir) os.makedirs(dumpdir)
def loads(content, ac_parser=None, ac_template=False, ac_context=None, **options): """ :param content: Configuration file's content :param ac_parser: Forced parser type or parser object :param ac_template: Assume configuration file may be a template file and try to compile it AAR if True :param ac_context: Context dict to instantiate template :param options: Optional keyword arguments. See also the description of `options` in `single_load` function. :return: dict or dict-like object supports merge operations """ msg = "Try parsing with a built-in parser because %s" if ac_parser is None: LOGGER.warning(msg, "ac_parser was not given.") return None psr = find_loader(None, ac_parser) if psr is None: LOGGER.warning(msg, "parser '%s' was not found" % ac_parser) return None schema = None ac_schema = options.get("ac_schema", None) if ac_schema is not None: options["ac_schema"] = None schema = loads(ac_schema, ac_parser=psr, ac_template=ac_template, ac_context=ac_context, **options) if ac_template: try: LOGGER.debug("Compiling") content = anyconfig.template.render_s(content, ac_context) except Exception as exc: LOGGER.warning( "Failed to compile and fallback to no template " "mode: '%s', exc=%r", content[:50] + '...', exc) cnf = psr.loads(content, **options) return _maybe_validated(cnf, schema, **options)
def loads(config_content, forced_type=None, ac_template=False, ac_context=None, ac_schema=None, **kwargs): """ :param config_content: Configuration file's content :param forced_type: Forced configuration parser type :param ignore_missing: Ignore missing config files :param ac_template: Assume configuration file may be a template file and try to compile it AAR if True :param ac_context: Context dict to instantiate template :param ac_schema: JSON schema content to validate given config file :param kwargs: Backend specific optional arguments, e.g. {"indent": 2} for JSON loader/dumper backend :return: Dict-like object (instance of anyconfig.mergeabledict.MergeableDict by default) supports merge operations. """ if forced_type is None: LOGGER.warn("No config type was given. Try to parse...") return anyconfig.parser.parse(config_content) cparser = find_loader(None, forced_type) if cparser is None: return anyconfig.parser.parse(config_content) if ac_schema is not None: kwargs["ac_schema"] = None # Avoid infinit loop format_checker = kwargs.get("format_checker", None) schema = loads(ac_schema, forced_type, ac_template, ac_context, **kwargs) if ac_template: try: LOGGER.debug("Compiling") config_content = anyconfig.template.render_s(config_content, ac_context) except Exception as exc: LOGGER.debug("Exc=%s", str(exc)) LOGGER.warn("Failed to compile and fallback to no template " "mode: '%s'", config_content[:50] + "...") config = cparser.loads(config_content, **kwargs) if ac_schema is not None: if not _validate(config, schema, format_checker): LOGGER.warn("Validation failed: schema=%s", schema) return None return config
def find_loader(path_or_stream, forced_type=None, is_path_=None): """ Find out config parser object appropriate to load from a file of given path or file/file-like object. :param path_or_stream: Configuration file path or file / file-like object :param forced_type: Forced configuration parser type :param is_path_: True if given `path_or_stream` is a file path :return: Config parser instance or None """ (psr, err) = anyconfig.backends.find_parser(path_or_stream, forced_type, is_path_=is_path_) if psr is None: LOGGER.error(err) return None LOGGER.debug("Using config parser of type: %s", psr.type()) return psr() # TBD: Passing initialization arguments.
def find_loader(config_path, forced_type=None): """ :param config_path: Configuration file path :param forced_type: Forced configuration parser type :return: Parser-inherited class object """ if forced_type is not None: cparser = anyconfig.backends.find_by_type(forced_type) if not cparser: LOGGER.error("No parser found for given type: %s", forced_type) return None else: cparser = anyconfig.backends.find_by_file(config_path) if not cparser: LOGGER.error("No parser found for given file: %s", config_path) return None LOGGER.debug("Using config parser of type: %s", cparser.type()) return cparser
def loads(content, ac_parser=None, ac_template=False, ac_context=None, **options): """ :param content: Configuration file's content :param ac_parser: Forced parser type or parser object :param ac_template: Assume configuration file may be a template file and try to compile it AAR if True :param ac_context: Context dict to instantiate template :param options: Optional keyword arguments. See also the description of `options` in `single_load` function. :return: dict or dict-like object supports merge operations """ msg = "Try parsing with a built-in parser because %s" if ac_parser is None: LOGGER.warning(msg, "ac_parser was not given.") return None psr = find_loader(None, ac_parser) if psr is None: LOGGER.warning(msg, "parser '%s' was not found" % ac_parser) return None schema = None ac_schema = options.get("ac_schema", None) if ac_schema is not None: options["ac_schema"] = None schema = loads(ac_schema, ac_parser=psr, ac_template=ac_template, ac_context=ac_context, **options) if ac_template: try: LOGGER.debug("Compiling") content = anyconfig.template.render_s(content, ac_context) except Exception as exc: LOGGER.warning("Failed to compile and fallback to no template " "mode: '%s', exc=%r", content[:50] + '...', exc) cnf = psr.loads(content, **options) return _maybe_validated(cnf, schema, **options)
def single_load( config_path, forced_type=None, ignore_missing=False, ac_template=False, ac_context=None, ac_schema=None, **kwargs ): """ Load single config file. :param config_path: Configuration file path :param forced_type: Forced configuration parser type :param ignore_missing: Ignore and just return empty result if given file (``config_path``) does not exist :param ac_template: Assume configuration file may be a template file and try to compile it AAR if True :param ac_context: A dict presents context to instantiate template :param ac_schema: JSON schema file path to validate given config file :param kwargs: Backend specific optional arguments, e.g. {"indent": 2} for JSON loader/dumper backend :return: Dict-like object (instance of anyconfig.mergeabledict.MergeableDict by default) supports merge operations. """ config_path = anyconfig.utils.ensure_expandusr(config_path) cparser = find_loader(config_path, forced_type) if cparser is None: return None if ac_schema is not None: kwargs["ac_schema"] = None # Avoid infinit loop format_checker = kwargs.get("format_checker", None) LOGGER.info("Loading schema: %s", ac_schema) schema = load( ac_schema, forced_type=forced_type, ignore_missing=ignore_missing, ac_template=ac_template, ac_context=ac_context, **kwargs ) LOGGER.info("Loading: %s", config_path) if ac_template: try: LOGGER.debug("Compiling: %s", config_path) config_content = anyconfig.template.render(config_path, ac_context) config = cparser.loads(config_content, ignore_missing=ignore_missing, **kwargs) if ac_schema is not None: if not _validate(config, schema, format_checker): return None return config except Exception as exc: LOGGER.debug("Exc=%s", str(exc)) LOGGER.warn("Failed to compile %s, fallback to no template " "mode", config_path) config = cparser.load(config_path, ignore_missing=ignore_missing, **kwargs) if ac_schema is not None: if not _validate(config, schema, format_checker): return None return config