Mercurial > repos > shellac > sam_consensus_v3
comparison env/lib/python3.9/site-packages/pip/_vendor/toml/encoder.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 import datetime | |
2 import re | |
3 import sys | |
4 from decimal import Decimal | |
5 | |
6 from pip._vendor.toml.decoder import InlineTableDict | |
7 | |
8 if sys.version_info >= (3,): | |
9 unicode = str | |
10 | |
11 | |
12 def dump(o, f, encoder=None): | |
13 """Writes out dict as toml to a file | |
14 | |
15 Args: | |
16 o: Object to dump into toml | |
17 f: File descriptor where the toml should be stored | |
18 encoder: The ``TomlEncoder`` to use for constructing the output string | |
19 | |
20 Returns: | |
21 String containing the toml corresponding to dictionary | |
22 | |
23 Raises: | |
24 TypeError: When anything other than file descriptor is passed | |
25 """ | |
26 | |
27 if not f.write: | |
28 raise TypeError("You can only dump an object to a file descriptor") | |
29 d = dumps(o, encoder=encoder) | |
30 f.write(d) | |
31 return d | |
32 | |
33 | |
34 def dumps(o, encoder=None): | |
35 """Stringifies input dict as toml | |
36 | |
37 Args: | |
38 o: Object to dump into toml | |
39 encoder: The ``TomlEncoder`` to use for constructing the output string | |
40 | |
41 Returns: | |
42 String containing the toml corresponding to dict | |
43 | |
44 Examples: | |
45 ```python | |
46 >>> import toml | |
47 >>> output = { | |
48 ... 'a': "I'm a string", | |
49 ... 'b': ["I'm", "a", "list"], | |
50 ... 'c': 2400 | |
51 ... } | |
52 >>> toml.dumps(output) | |
53 'a = "I\'m a string"\nb = [ "I\'m", "a", "list",]\nc = 2400\n' | |
54 ``` | |
55 """ | |
56 | |
57 retval = "" | |
58 if encoder is None: | |
59 encoder = TomlEncoder(o.__class__) | |
60 addtoretval, sections = encoder.dump_sections(o, "") | |
61 retval += addtoretval | |
62 outer_objs = [id(o)] | |
63 while sections: | |
64 section_ids = [id(section) for section in sections.values()] | |
65 for outer_obj in outer_objs: | |
66 if outer_obj in section_ids: | |
67 raise ValueError("Circular reference detected") | |
68 outer_objs += section_ids | |
69 newsections = encoder.get_empty_table() | |
70 for section in sections: | |
71 addtoretval, addtosections = encoder.dump_sections( | |
72 sections[section], section) | |
73 | |
74 if addtoretval or (not addtoretval and not addtosections): | |
75 if retval and retval[-2:] != "\n\n": | |
76 retval += "\n" | |
77 retval += "[" + section + "]\n" | |
78 if addtoretval: | |
79 retval += addtoretval | |
80 for s in addtosections: | |
81 newsections[section + "." + s] = addtosections[s] | |
82 sections = newsections | |
83 return retval | |
84 | |
85 | |
86 def _dump_str(v): | |
87 if sys.version_info < (3,) and hasattr(v, 'decode') and isinstance(v, str): | |
88 v = v.decode('utf-8') | |
89 v = "%r" % v | |
90 if v[0] == 'u': | |
91 v = v[1:] | |
92 singlequote = v.startswith("'") | |
93 if singlequote or v.startswith('"'): | |
94 v = v[1:-1] | |
95 if singlequote: | |
96 v = v.replace("\\'", "'") | |
97 v = v.replace('"', '\\"') | |
98 v = v.split("\\x") | |
99 while len(v) > 1: | |
100 i = -1 | |
101 if not v[0]: | |
102 v = v[1:] | |
103 v[0] = v[0].replace("\\\\", "\\") | |
104 # No, I don't know why != works and == breaks | |
105 joinx = v[0][i] != "\\" | |
106 while v[0][:i] and v[0][i] == "\\": | |
107 joinx = not joinx | |
108 i -= 1 | |
109 if joinx: | |
110 joiner = "x" | |
111 else: | |
112 joiner = "u00" | |
113 v = [v[0] + joiner + v[1]] + v[2:] | |
114 return unicode('"' + v[0] + '"') | |
115 | |
116 | |
117 def _dump_float(v): | |
118 return "{}".format(v).replace("e+0", "e+").replace("e-0", "e-") | |
119 | |
120 | |
121 def _dump_time(v): | |
122 utcoffset = v.utcoffset() | |
123 if utcoffset is None: | |
124 return v.isoformat() | |
125 # The TOML norm specifies that it's local time thus we drop the offset | |
126 return v.isoformat()[:-6] | |
127 | |
128 | |
129 class TomlEncoder(object): | |
130 | |
131 def __init__(self, _dict=dict, preserve=False): | |
132 self._dict = _dict | |
133 self.preserve = preserve | |
134 self.dump_funcs = { | |
135 str: _dump_str, | |
136 unicode: _dump_str, | |
137 list: self.dump_list, | |
138 bool: lambda v: unicode(v).lower(), | |
139 int: lambda v: v, | |
140 float: _dump_float, | |
141 Decimal: _dump_float, | |
142 datetime.datetime: lambda v: v.isoformat().replace('+00:00', 'Z'), | |
143 datetime.time: _dump_time, | |
144 datetime.date: lambda v: v.isoformat() | |
145 } | |
146 | |
147 def get_empty_table(self): | |
148 return self._dict() | |
149 | |
150 def dump_list(self, v): | |
151 retval = "[" | |
152 for u in v: | |
153 retval += " " + unicode(self.dump_value(u)) + "," | |
154 retval += "]" | |
155 return retval | |
156 | |
157 def dump_inline_table(self, section): | |
158 """Preserve inline table in its compact syntax instead of expanding | |
159 into subsection. | |
160 | |
161 https://github.com/toml-lang/toml#user-content-inline-table | |
162 """ | |
163 retval = "" | |
164 if isinstance(section, dict): | |
165 val_list = [] | |
166 for k, v in section.items(): | |
167 val = self.dump_inline_table(v) | |
168 val_list.append(k + " = " + val) | |
169 retval += "{ " + ", ".join(val_list) + " }\n" | |
170 return retval | |
171 else: | |
172 return unicode(self.dump_value(section)) | |
173 | |
174 def dump_value(self, v): | |
175 # Lookup function corresponding to v's type | |
176 dump_fn = self.dump_funcs.get(type(v)) | |
177 if dump_fn is None and hasattr(v, '__iter__'): | |
178 dump_fn = self.dump_funcs[list] | |
179 # Evaluate function (if it exists) else return v | |
180 return dump_fn(v) if dump_fn is not None else self.dump_funcs[str](v) | |
181 | |
182 def dump_sections(self, o, sup): | |
183 retstr = "" | |
184 if sup != "" and sup[-1] != ".": | |
185 sup += '.' | |
186 retdict = self._dict() | |
187 arraystr = "" | |
188 for section in o: | |
189 section = unicode(section) | |
190 qsection = section | |
191 if not re.match(r'^[A-Za-z0-9_-]+$', section): | |
192 qsection = _dump_str(section) | |
193 if not isinstance(o[section], dict): | |
194 arrayoftables = False | |
195 if isinstance(o[section], list): | |
196 for a in o[section]: | |
197 if isinstance(a, dict): | |
198 arrayoftables = True | |
199 if arrayoftables: | |
200 for a in o[section]: | |
201 arraytabstr = "\n" | |
202 arraystr += "[[" + sup + qsection + "]]\n" | |
203 s, d = self.dump_sections(a, sup + qsection) | |
204 if s: | |
205 if s[0] == "[": | |
206 arraytabstr += s | |
207 else: | |
208 arraystr += s | |
209 while d: | |
210 newd = self._dict() | |
211 for dsec in d: | |
212 s1, d1 = self.dump_sections(d[dsec], sup + | |
213 qsection + "." + | |
214 dsec) | |
215 if s1: | |
216 arraytabstr += ("[" + sup + qsection + | |
217 "." + dsec + "]\n") | |
218 arraytabstr += s1 | |
219 for s1 in d1: | |
220 newd[dsec + "." + s1] = d1[s1] | |
221 d = newd | |
222 arraystr += arraytabstr | |
223 else: | |
224 if o[section] is not None: | |
225 retstr += (qsection + " = " + | |
226 unicode(self.dump_value(o[section])) + '\n') | |
227 elif self.preserve and isinstance(o[section], InlineTableDict): | |
228 retstr += (qsection + " = " + | |
229 self.dump_inline_table(o[section])) | |
230 else: | |
231 retdict[qsection] = o[section] | |
232 retstr += arraystr | |
233 return (retstr, retdict) | |
234 | |
235 | |
236 class TomlPreserveInlineDictEncoder(TomlEncoder): | |
237 | |
238 def __init__(self, _dict=dict): | |
239 super(TomlPreserveInlineDictEncoder, self).__init__(_dict, True) | |
240 | |
241 | |
242 class TomlArraySeparatorEncoder(TomlEncoder): | |
243 | |
244 def __init__(self, _dict=dict, preserve=False, separator=","): | |
245 super(TomlArraySeparatorEncoder, self).__init__(_dict, preserve) | |
246 if separator.strip() == "": | |
247 separator = "," + separator | |
248 elif separator.strip(' \t\n\r,'): | |
249 raise ValueError("Invalid separator for arrays") | |
250 self.separator = separator | |
251 | |
252 def dump_list(self, v): | |
253 t = [] | |
254 retval = "[" | |
255 for u in v: | |
256 t.append(self.dump_value(u)) | |
257 while t != []: | |
258 s = [] | |
259 for u in t: | |
260 if isinstance(u, list): | |
261 for r in u: | |
262 s.append(r) | |
263 else: | |
264 retval += " " + unicode(u) + self.separator | |
265 t = s | |
266 retval += "]" | |
267 return retval | |
268 | |
269 | |
270 class TomlNumpyEncoder(TomlEncoder): | |
271 | |
272 def __init__(self, _dict=dict, preserve=False): | |
273 import numpy as np | |
274 super(TomlNumpyEncoder, self).__init__(_dict, preserve) | |
275 self.dump_funcs[np.float16] = _dump_float | |
276 self.dump_funcs[np.float32] = _dump_float | |
277 self.dump_funcs[np.float64] = _dump_float | |
278 self.dump_funcs[np.int16] = self._dump_int | |
279 self.dump_funcs[np.int32] = self._dump_int | |
280 self.dump_funcs[np.int64] = self._dump_int | |
281 | |
282 def _dump_int(self, v): | |
283 return "{}".format(int(v)) | |
284 | |
285 | |
286 class TomlPreserveCommentEncoder(TomlEncoder): | |
287 | |
288 def __init__(self, _dict=dict, preserve=False): | |
289 from pip._vendor.toml.decoder import CommentValue | |
290 super(TomlPreserveCommentEncoder, self).__init__(_dict, preserve) | |
291 self.dump_funcs[CommentValue] = lambda v: v.dump(self.dump_value) | |
292 | |
293 | |
294 class TomlPathlibEncoder(TomlEncoder): | |
295 | |
296 def _dump_pathlib_path(self, v): | |
297 return _dump_str(str(v)) | |
298 | |
299 def dump_value(self, v): | |
300 if (3, 4) <= sys.version_info: | |
301 import pathlib | |
302 if isinstance(v, pathlib.PurePath): | |
303 v = str(v) | |
304 return super(TomlPathlibEncoder, self).dump_value(v) |