Skip to content

Commit

Permalink
enhancement: make ruamel.yaml based backend works w/o PyYAML
Browse files Browse the repository at this point in the history
Make ruamel.yaml based backend works w/o PyYAML by:

- Introduce anyconfig.backend.yaml.common to move common parts
  from anyconfig.backend.yamlpyyaml
- Remove dependency to anyconfig.backend.yaml.pyyaml from
  anyconfig.backend.yaml.ruamel_yaml and simplify it

This enhanement also might close the issue #99.
  • Loading branch information
ssato committed Feb 8, 2019
1 parent a5b9c0a commit 4f8286b
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 27 deletions.
36 changes: 36 additions & 0 deletions anyconfig/backend/yaml/common.py
@@ -0,0 +1,36 @@
#
# Copyright (C) 2011 - 2018 Satoru SATOH <ssato @ redhat.com>
# Copyright (C) 2019 Satoru SATOH <satoru.satoh@gmail.com>
# License: MIT
#
r"""Common parts for YAML backends:
"""
from __future__ import absolute_import
import anyconfig.backend.base


def filter_from_options(key, options):
"""
:param key: Key str in options
:param options: Mapping object
:return:
New mapping object from `options` in which the item with `key` filtered
>>> filter_from_options('a', dict(a=1, b=2))
{'b': 2}
"""
return anyconfig.utils.filter_options([k for k in options.keys()
if k != key], options)


class Parser(anyconfig.backend.base.StreamParser):
"""
Parser for YAML files.
"""
_type = "yaml"
_extensions = ["yaml", "yml"]
_ordered = True
_allow_primitives = True
_dict_opts = ["ac_dict"]

# vim:sw=4:ts=4:et:
30 changes: 7 additions & 23 deletions anyconfig/backend/yaml/pyyaml.py
Expand Up @@ -49,22 +49,10 @@
import anyconfig.compat
import anyconfig.utils

from . import common

_MAPPING_TAG = yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG


def filter_from_options(key, options):
"""
:param key: Key str in options
:param options: Mapping object
:return:
New mapping object from `options` in which the item with `key` filtered

>>> filter_from_options('a', dict(a=1, b=2))
{'b': 2}
"""
return anyconfig.utils.filter_options([k for k in options.keys()
if k != key], options)
_MAPPING_TAG = yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG


def _customized_loader(container, loader=Loader, mapping_tag=_MAPPING_TAG):
Expand Down Expand Up @@ -151,7 +139,7 @@ def yml_fnc(fname, *args, **options):
"""
key = "ac_safe"
fnc = getattr(yaml, r"safe_" + fname if options.get(key) else fname)
return fnc(*args, **filter_from_options(key, options))
return fnc(*args, **common.filter_from_options(key, options))


def yml_load(stream, container, yml_fnc=yml_fnc, **options):
Expand All @@ -171,7 +159,8 @@ def yml_load(stream, container, yml_fnc=yml_fnc, **options):

options["Loader"] = _customized_loader(container)

ret = yml_fnc("load", stream, **filter_from_options("ac_dict", options))
ret = yml_fnc("load", stream,
**common.filter_from_options("ac_dict", options))
if ret is None:
return container()

Expand All @@ -196,26 +185,21 @@ def yml_dump(data, stream, yml_fnc=yml_fnc, **options):
if _is_dict:
# Type information and the order of items are lost on dump currently.
data = anyconfig.dicts.convert_to(data, ac_dict=dict)
options = filter_from_options("ac_dict", options)
options = common.filter_from_options("ac_dict", options)

return yml_fnc("dump", data, stream, **options)


class Parser(anyconfig.backend.base.StreamParser):
class Parser(common.Parser):
"""
Parser for YAML files.
"""
_type = "yaml"
_cid = "pyyaml"
_extensions = ["yaml", "yml"]
_load_opts = ["Loader", "ac_safe", "ac_dict"]
_dump_opts = ["stream", "ac_safe", "Dumper", "default_style",
"default_flow_style", "canonical", "indent", "width",
"allow_unicode", "line_break", "encoding", "explicit_start",
"explicit_end", "version", "tags"]
_ordered = True
_allow_primitives = True
_dict_opts = ["ac_dict"]

load_from_stream = anyconfig.backend.base.to_method(yml_load)
dump_to_stream = anyconfig.backend.base.to_method(yml_dump)
Expand Down
22 changes: 18 additions & 4 deletions anyconfig/backend/yaml/ruamel_yaml.py
Expand Up @@ -39,9 +39,10 @@
from __future__ import absolute_import

import ruamel.yaml as ryaml
import anyconfig.backend.base
import anyconfig.utils

from . import pyyaml
from . import common


try:
Expand Down Expand Up @@ -77,6 +78,8 @@ def yml_fnc(fname, *args, **options):
:param args: [stream] for load or [cnf, stream] for dump
:param options: keyword args may contain "ac_safe" to load/dump safely
"""
options = common.filter_from_options("ac_dict", options)

if "ac_safe" in options:
options["typ"] = "safe" # Override it.

Expand All @@ -93,16 +96,27 @@ def yml_fnc(fname, *args, **options):
def yml_load(stream, container, **options):
""".. seealso:: :func:`anyconfig.backend.yaml.pyyaml.yml_load`
"""
return pyyaml.yml_load(stream, container, yml_fnc=yml_fnc, **options)
ret = yml_fnc("load", stream, **options)
if ret is None:
return container()

return ret


def yml_dump(data, stream, **options):
""".. seealso:: :func:`anyconfig.backend.yaml.pyyaml.yml_dump`
"""
return pyyaml.yml_dump(data, stream, yml_fnc=yml_fnc, **options)
# .. todo:: Needed?
# if anyconfig.utils.is_dict_like(data):
# if options.get("ac_ordered"):
# factory = collections.OrderedDict
# else:
# factory = dict
# data = anyconfig.dicts.convert_to(data, ac_dict=factory)
return yml_fnc("dump", data, stream, **options)


class Parser(pyyaml.Parser):
class Parser(common.Parser):
"""Parser for YAML files.
"""
_cid = "ruamel.yaml"
Expand Down

0 comments on commit 4f8286b

Please sign in to comment.