Example #1
0
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
Example #2
0
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)
Example #3
0
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.
Example #4
0
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.
Example #5
0
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)
Example #6
0
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)
Example #7
0
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)
Example #8
0
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)
Example #9
0
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
Example #10
0
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.
Example #11
0
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
Example #12
0
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)
Example #13
0
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