Mercurial > repos > shellac > sam_consensus_v3
comparison env/lib/python3.9/site-packages/ruamel/yaml/util.py @ 0:4f3585e2f14b draft default tip
"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
| author | shellac |
|---|---|
| date | Mon, 22 Mar 2021 18:12:50 +0000 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:4f3585e2f14b |
|---|---|
| 1 # coding: utf-8 | |
| 2 | |
| 3 """ | |
| 4 some helper functions that might be generally useful | |
| 5 """ | |
| 6 | |
| 7 from __future__ import absolute_import, print_function | |
| 8 | |
| 9 from functools import partial | |
| 10 import re | |
| 11 | |
| 12 from .compat import text_type, binary_type | |
| 13 | |
| 14 if False: # MYPY | |
| 15 from typing import Any, Dict, Optional, List, Text # NOQA | |
| 16 from .compat import StreamTextType # NOQA | |
| 17 | |
| 18 | |
| 19 class LazyEval(object): | |
| 20 """ | |
| 21 Lightweight wrapper around lazily evaluated func(*args, **kwargs). | |
| 22 | |
| 23 func is only evaluated when any attribute of its return value is accessed. | |
| 24 Every attribute access is passed through to the wrapped value. | |
| 25 (This only excludes special cases like method-wrappers, e.g., __hash__.) | |
| 26 The sole additional attribute is the lazy_self function which holds the | |
| 27 return value (or, prior to evaluation, func and arguments), in its closure. | |
| 28 """ | |
| 29 | |
| 30 def __init__(self, func, *args, **kwargs): | |
| 31 # type: (Any, Any, Any) -> None | |
| 32 def lazy_self(): | |
| 33 # type: () -> Any | |
| 34 return_value = func(*args, **kwargs) | |
| 35 object.__setattr__(self, 'lazy_self', lambda: return_value) | |
| 36 return return_value | |
| 37 | |
| 38 object.__setattr__(self, 'lazy_self', lazy_self) | |
| 39 | |
| 40 def __getattribute__(self, name): | |
| 41 # type: (Any) -> Any | |
| 42 lazy_self = object.__getattribute__(self, 'lazy_self') | |
| 43 if name == 'lazy_self': | |
| 44 return lazy_self | |
| 45 return getattr(lazy_self(), name) | |
| 46 | |
| 47 def __setattr__(self, name, value): | |
| 48 # type: (Any, Any) -> None | |
| 49 setattr(self.lazy_self(), name, value) | |
| 50 | |
| 51 | |
| 52 RegExp = partial(LazyEval, re.compile) | |
| 53 | |
| 54 | |
| 55 # originally as comment | |
| 56 # https://github.com/pre-commit/pre-commit/pull/211#issuecomment-186466605 | |
| 57 # if you use this in your code, I suggest adding a test in your test suite | |
| 58 # that check this routines output against a known piece of your YAML | |
| 59 # before upgrades to this code break your round-tripped YAML | |
| 60 def load_yaml_guess_indent(stream, **kw): | |
| 61 # type: (StreamTextType, Any) -> Any | |
| 62 """guess the indent and block sequence indent of yaml stream/string | |
| 63 | |
| 64 returns round_trip_loaded stream, indent level, block sequence indent | |
| 65 - block sequence indent is the number of spaces before a dash relative to previous indent | |
| 66 - if there are no block sequences, indent is taken from nested mappings, block sequence | |
| 67 indent is unset (None) in that case | |
| 68 """ | |
| 69 from .main import round_trip_load | |
| 70 | |
| 71 # load a yaml file guess the indentation, if you use TABs ... | |
| 72 def leading_spaces(l): | |
| 73 # type: (Any) -> int | |
| 74 idx = 0 | |
| 75 while idx < len(l) and l[idx] == ' ': | |
| 76 idx += 1 | |
| 77 return idx | |
| 78 | |
| 79 if isinstance(stream, text_type): | |
| 80 yaml_str = stream # type: Any | |
| 81 elif isinstance(stream, binary_type): | |
| 82 # most likely, but the Reader checks BOM for this | |
| 83 yaml_str = stream.decode('utf-8') | |
| 84 else: | |
| 85 yaml_str = stream.read() | |
| 86 map_indent = None | |
| 87 indent = None # default if not found for some reason | |
| 88 block_seq_indent = None | |
| 89 prev_line_key_only = None | |
| 90 key_indent = 0 | |
| 91 for line in yaml_str.splitlines(): | |
| 92 rline = line.rstrip() | |
| 93 lline = rline.lstrip() | |
| 94 if lline.startswith('- '): | |
| 95 l_s = leading_spaces(line) | |
| 96 block_seq_indent = l_s - key_indent | |
| 97 idx = l_s + 1 | |
| 98 while line[idx] == ' ': # this will end as we rstripped | |
| 99 idx += 1 | |
| 100 if line[idx] == '#': # comment after - | |
| 101 continue | |
| 102 indent = idx - key_indent | |
| 103 break | |
| 104 if map_indent is None and prev_line_key_only is not None and rline: | |
| 105 idx = 0 | |
| 106 while line[idx] in ' -': | |
| 107 idx += 1 | |
| 108 if idx > prev_line_key_only: | |
| 109 map_indent = idx - prev_line_key_only | |
| 110 if rline.endswith(':'): | |
| 111 key_indent = leading_spaces(line) | |
| 112 idx = 0 | |
| 113 while line[idx] == ' ': # this will end on ':' | |
| 114 idx += 1 | |
| 115 prev_line_key_only = idx | |
| 116 continue | |
| 117 prev_line_key_only = None | |
| 118 if indent is None and map_indent is not None: | |
| 119 indent = map_indent | |
| 120 return round_trip_load(yaml_str, **kw), indent, block_seq_indent | |
| 121 | |
| 122 | |
| 123 def configobj_walker(cfg): | |
| 124 # type: (Any) -> Any | |
| 125 """ | |
| 126 walks over a ConfigObj (INI file with comments) generating | |
| 127 corresponding YAML output (including comments | |
| 128 """ | |
| 129 from configobj import ConfigObj # type: ignore | |
| 130 | |
| 131 assert isinstance(cfg, ConfigObj) | |
| 132 for c in cfg.initial_comment: | |
| 133 if c.strip(): | |
| 134 yield c | |
| 135 for s in _walk_section(cfg): | |
| 136 if s.strip(): | |
| 137 yield s | |
| 138 for c in cfg.final_comment: | |
| 139 if c.strip(): | |
| 140 yield c | |
| 141 | |
| 142 | |
| 143 def _walk_section(s, level=0): | |
| 144 # type: (Any, int) -> Any | |
| 145 from configobj import Section | |
| 146 | |
| 147 assert isinstance(s, Section) | |
| 148 indent = u' ' * level | |
| 149 for name in s.scalars: | |
| 150 for c in s.comments[name]: | |
| 151 yield indent + c.strip() | |
| 152 x = s[name] | |
| 153 if u'\n' in x: | |
| 154 i = indent + u' ' | |
| 155 x = u'|\n' + i + x.strip().replace(u'\n', u'\n' + i) | |
| 156 elif ':' in x: | |
| 157 x = u"'" + x.replace(u"'", u"''") + u"'" | |
| 158 line = u'{0}{1}: {2}'.format(indent, name, x) | |
| 159 c = s.inline_comments[name] | |
| 160 if c: | |
| 161 line += u' ' + c | |
| 162 yield line | |
| 163 for name in s.sections: | |
| 164 for c in s.comments[name]: | |
| 165 yield indent + c.strip() | |
| 166 line = u'{0}{1}:'.format(indent, name) | |
| 167 c = s.inline_comments[name] | |
| 168 if c: | |
| 169 line += u' ' + c | |
| 170 yield line | |
| 171 for val in _walk_section(s[name], level=level + 1): | |
| 172 yield val | |
| 173 | |
| 174 | |
| 175 # def config_obj_2_rt_yaml(cfg): | |
| 176 # from .comments import CommentedMap, CommentedSeq | |
| 177 # from configobj import ConfigObj | |
| 178 # assert isinstance(cfg, ConfigObj) | |
| 179 # #for c in cfg.initial_comment: | |
| 180 # # if c.strip(): | |
| 181 # # pass | |
| 182 # cm = CommentedMap() | |
| 183 # for name in s.sections: | |
| 184 # cm[name] = d = CommentedMap() | |
| 185 # | |
| 186 # | |
| 187 # #for c in cfg.final_comment: | |
| 188 # # if c.strip(): | |
| 189 # # yield c | |
| 190 # return cm |
