diff options
author | Anthon van der Neut <anthon@mnt.org> | 2016-02-27 10:15:02 +0100 |
---|---|---|
committer | Anthon van der Neut <anthon@mnt.org> | 2016-02-27 10:15:02 +0100 |
commit | 2f9cdc98cc0adea615cb2180481c7780eef48f97 (patch) | |
tree | ff710ad0913ced7c241f0445e95e6eefeb24ae1b /util.py | |
parent | acc0b296466c5364569b1df8402d2cb95ca01915 (diff) | |
download | ruamel.yaml-2f9cdc98cc0adea615cb2180481c7780eef48f97.tar.gz |
pep8 compliance, util.load_yaml_guess_indent0.11.2
Diffstat (limited to 'util.py')
-rw-r--r-- | util.py | 118 |
1 files changed, 118 insertions, 0 deletions
@@ -0,0 +1,118 @@ +# coding: utf-8 + +""" +some helper functions that might be generally useful +""" + +from __future__ import print_function +from __future__ import absolute_import + +from .compat import text_type, binary_type +from .main import round_trip_load + + +# originally as comment +# https://github.com/pre-commit/pre-commit/pull/211#issuecomment-186466605 +# if you use this in your code, I suggest adding a test in your test suite +# that check this routines output against a known piece of your YAML +# before upgrades to this code break your round-tripped YAML +def load_yaml_guess_indent(stream): + # load a yaml file guess the indentation, if you use TABs ... + if isinstance(stream, text_type): + yaml_str = stream + elif isinstance(stream, binary_type): + yaml_str = stream.decode('utf-8') # most likely, but the Reader checks BOM for this + else: + yaml_str = stream.read() + indent = None # default if not found for some reason + prev_line_key_only = None + for line in yaml_str.splitlines(): + rline = line.rstrip() + if rline.startswith('- '): + idx = 1 + while line[idx] == ' ': # this will end as we rstripped + idx += 1 + if line[idx] == '#': # comment after - + continue + indent = idx + break + if rline.endswith(':'): + idx = 0 + while line[idx] == ' ': # this will end on ':' + idx += 1 + prev_line_key_only = idx + continue + if prev_line_key_only is not None and rline: + idx = 0 + while line[idx] in ' -': # this will end on ':' + idx += 1 + if idx > prev_line_key_only: + indent = idx - prev_line_key_only + break + prev_line_key_only = None + return round_trip_load(yaml_str), indent + + +def configobj_walker(cfg): + """ + walks over a ConfigObj (INI file with comments) generating + corresponding YAML output (including comments + """ + from configobj import ConfigObj + assert isinstance(cfg, ConfigObj) + for c in cfg.initial_comment: + if c.strip(): + yield c + for s in _walk_section(cfg): + if s.strip(): + yield s + for c in cfg.final_comment: + if c.strip(): + yield c + + +def _walk_section(s, level=0): + from configobj import Section + assert isinstance(s, Section) + indent = u' ' * level + for name in s.scalars: + for c in s.comments[name]: + yield indent + c.strip() + x = s[name] + if u'\n' in x: + i = indent + u' ' + x = u'|\n' + i + x.strip().replace(u'\n', u'\n' + i) + elif ':' in x: + x = u"'" + x.replace(u"'", u"''") + u"'" + line = u'{0}{1}: {2}'.format(indent, name, x) + c = s.inline_comments[name] + if c: + line += u' ' + c + yield line + for name in s.sections: + for c in s.comments[name]: + yield indent + c.strip() + line = u'{0}{1}:'.format(indent, name) + c = s.inline_comments[name] + if c: + line += u' ' + c + yield line + for val in _walk_section(s[name], level=level+1): + yield val + +# def config_obj_2_rt_yaml(cfg): +# from .comments import CommentedMap, CommentedSeq +# from configobj import ConfigObj +# assert isinstance(cfg, ConfigObj) +# #for c in cfg.initial_comment: +# # if c.strip(): +# # pass +# cm = CommentedMap() +# for name in s.sections: +# cm[name] = d = CommentedMap() +# +# +# #for c in cfg.final_comment: +# # if c.strip(): +# # yield c +# return cm |