Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/ruamel/yaml/util.py @ 1:56ad4e20f292 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author | guerler |
---|---|
date | Fri, 31 Jul 2020 00:32:28 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:d30785e31577 | 1:56ad4e20f292 |
---|---|
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 | |
81 elif isinstance(stream, binary_type): | |
82 yaml_str = stream.decode('utf-8') # most likely, but the Reader checks BOM for this | |
83 else: | |
84 yaml_str = stream.read() | |
85 map_indent = None | |
86 indent = None # default if not found for some reason | |
87 block_seq_indent = None | |
88 prev_line_key_only = None | |
89 key_indent = 0 | |
90 for line in yaml_str.splitlines(): | |
91 rline = line.rstrip() | |
92 lline = rline.lstrip() | |
93 if lline.startswith('- '): | |
94 l_s = leading_spaces(line) | |
95 block_seq_indent = l_s - key_indent | |
96 idx = l_s + 1 | |
97 while line[idx] == ' ': # this will end as we rstripped | |
98 idx += 1 | |
99 if line[idx] == '#': # comment after - | |
100 continue | |
101 indent = idx - key_indent | |
102 break | |
103 if map_indent is None and prev_line_key_only is not None and rline: | |
104 idx = 0 | |
105 while line[idx] in ' -': | |
106 idx += 1 | |
107 if idx > prev_line_key_only: | |
108 map_indent = idx - prev_line_key_only | |
109 if rline.endswith(':'): | |
110 key_indent = leading_spaces(line) | |
111 idx = 0 | |
112 while line[idx] == ' ': # this will end on ':' | |
113 idx += 1 | |
114 prev_line_key_only = idx | |
115 continue | |
116 prev_line_key_only = None | |
117 if indent is None and map_indent is not None: | |
118 indent = map_indent | |
119 return round_trip_load(yaml_str, **kw), indent, block_seq_indent | |
120 | |
121 | |
122 def configobj_walker(cfg): | |
123 # type: (Any) -> Any | |
124 """ | |
125 walks over a ConfigObj (INI file with comments) generating | |
126 corresponding YAML output (including comments | |
127 """ | |
128 from configobj import ConfigObj # type: ignore | |
129 | |
130 assert isinstance(cfg, ConfigObj) | |
131 for c in cfg.initial_comment: | |
132 if c.strip(): | |
133 yield c | |
134 for s in _walk_section(cfg): | |
135 if s.strip(): | |
136 yield s | |
137 for c in cfg.final_comment: | |
138 if c.strip(): | |
139 yield c | |
140 | |
141 | |
142 def _walk_section(s, level=0): | |
143 # type: (Any, int) -> Any | |
144 from configobj import Section | |
145 | |
146 assert isinstance(s, Section) | |
147 indent = u' ' * level | |
148 for name in s.scalars: | |
149 for c in s.comments[name]: | |
150 yield indent + c.strip() | |
151 x = s[name] | |
152 if u'\n' in x: | |
153 i = indent + u' ' | |
154 x = u'|\n' + i + x.strip().replace(u'\n', u'\n' + i) | |
155 elif ':' in x: | |
156 x = u"'" + x.replace(u"'", u"''") + u"'" | |
157 line = u'{0}{1}: {2}'.format(indent, name, x) | |
158 c = s.inline_comments[name] | |
159 if c: | |
160 line += u' ' + c | |
161 yield line | |
162 for name in s.sections: | |
163 for c in s.comments[name]: | |
164 yield indent + c.strip() | |
165 line = u'{0}{1}:'.format(indent, name) | |
166 c = s.inline_comments[name] | |
167 if c: | |
168 line += u' ' + c | |
169 yield line | |
170 for val in _walk_section(s[name], level=level + 1): | |
171 yield val | |
172 | |
173 | |
174 # def config_obj_2_rt_yaml(cfg): | |
175 # from .comments import CommentedMap, CommentedSeq | |
176 # from configobj import ConfigObj | |
177 # assert isinstance(cfg, ConfigObj) | |
178 # #for c in cfg.initial_comment: | |
179 # # if c.strip(): | |
180 # # pass | |
181 # cm = CommentedMap() | |
182 # for name in s.sections: | |
183 # cm[name] = d = CommentedMap() | |
184 # | |
185 # | |
186 # #for c in cfg.final_comment: | |
187 # # if c.strip(): | |
188 # # yield c | |
189 # return cm |