Mercurial > repos > shellac > sam_consensus_v3
comparison env/lib/python3.9/site-packages/ruamel/yaml/representer.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 from __future__ import print_function, absolute_import, division | |
4 | |
5 | |
6 from ruamel.yaml.error import * # NOQA | |
7 from ruamel.yaml.nodes import * # NOQA | |
8 from ruamel.yaml.compat import text_type, binary_type, to_unicode, PY2, PY3 | |
9 from ruamel.yaml.compat import ordereddict # type: ignore | |
10 from ruamel.yaml.compat import nprint, nprintf # NOQA | |
11 from ruamel.yaml.scalarstring import ( | |
12 LiteralScalarString, | |
13 FoldedScalarString, | |
14 SingleQuotedScalarString, | |
15 DoubleQuotedScalarString, | |
16 PlainScalarString, | |
17 ) | |
18 from ruamel.yaml.scalarint import ScalarInt, BinaryInt, OctalInt, HexInt, HexCapsInt | |
19 from ruamel.yaml.scalarfloat import ScalarFloat | |
20 from ruamel.yaml.scalarbool import ScalarBoolean | |
21 from ruamel.yaml.timestamp import TimeStamp | |
22 | |
23 import datetime | |
24 import sys | |
25 import types | |
26 | |
27 if PY3: | |
28 import copyreg | |
29 import base64 | |
30 else: | |
31 import copy_reg as copyreg # type: ignore | |
32 | |
33 if False: # MYPY | |
34 from typing import Dict, List, Any, Union, Text, Optional # NOQA | |
35 | |
36 # fmt: off | |
37 __all__ = ['BaseRepresenter', 'SafeRepresenter', 'Representer', | |
38 'RepresenterError', 'RoundTripRepresenter'] | |
39 # fmt: on | |
40 | |
41 | |
42 class RepresenterError(YAMLError): | |
43 pass | |
44 | |
45 | |
46 if PY2: | |
47 | |
48 def get_classobj_bases(cls): | |
49 # type: (Any) -> Any | |
50 bases = [cls] | |
51 for base in cls.__bases__: | |
52 bases.extend(get_classobj_bases(base)) | |
53 return bases | |
54 | |
55 | |
56 class BaseRepresenter(object): | |
57 | |
58 yaml_representers = {} # type: Dict[Any, Any] | |
59 yaml_multi_representers = {} # type: Dict[Any, Any] | |
60 | |
61 def __init__(self, default_style=None, default_flow_style=None, dumper=None): | |
62 # type: (Any, Any, Any, Any) -> None | |
63 self.dumper = dumper | |
64 if self.dumper is not None: | |
65 self.dumper._representer = self | |
66 self.default_style = default_style | |
67 self.default_flow_style = default_flow_style | |
68 self.represented_objects = {} # type: Dict[Any, Any] | |
69 self.object_keeper = [] # type: List[Any] | |
70 self.alias_key = None # type: Optional[int] | |
71 self.sort_base_mapping_type_on_output = True | |
72 | |
73 @property | |
74 def serializer(self): | |
75 # type: () -> Any | |
76 try: | |
77 if hasattr(self.dumper, 'typ'): | |
78 return self.dumper.serializer | |
79 return self.dumper._serializer | |
80 except AttributeError: | |
81 return self # cyaml | |
82 | |
83 def represent(self, data): | |
84 # type: (Any) -> None | |
85 node = self.represent_data(data) | |
86 self.serializer.serialize(node) | |
87 self.represented_objects = {} | |
88 self.object_keeper = [] | |
89 self.alias_key = None | |
90 | |
91 def represent_data(self, data): | |
92 # type: (Any) -> Any | |
93 if self.ignore_aliases(data): | |
94 self.alias_key = None | |
95 else: | |
96 self.alias_key = id(data) | |
97 if self.alias_key is not None: | |
98 if self.alias_key in self.represented_objects: | |
99 node = self.represented_objects[self.alias_key] | |
100 # if node is None: | |
101 # raise RepresenterError( | |
102 # "recursive objects are not allowed: %r" % data) | |
103 return node | |
104 # self.represented_objects[alias_key] = None | |
105 self.object_keeper.append(data) | |
106 data_types = type(data).__mro__ | |
107 if PY2: | |
108 # if type(data) is types.InstanceType: | |
109 if isinstance(data, types.InstanceType): | |
110 data_types = get_classobj_bases(data.__class__) + list(data_types) | |
111 if data_types[0] in self.yaml_representers: | |
112 node = self.yaml_representers[data_types[0]](self, data) | |
113 else: | |
114 for data_type in data_types: | |
115 if data_type in self.yaml_multi_representers: | |
116 node = self.yaml_multi_representers[data_type](self, data) | |
117 break | |
118 else: | |
119 if None in self.yaml_multi_representers: | |
120 node = self.yaml_multi_representers[None](self, data) | |
121 elif None in self.yaml_representers: | |
122 node = self.yaml_representers[None](self, data) | |
123 else: | |
124 node = ScalarNode(None, text_type(data)) | |
125 # if alias_key is not None: | |
126 # self.represented_objects[alias_key] = node | |
127 return node | |
128 | |
129 def represent_key(self, data): | |
130 # type: (Any) -> Any | |
131 """ | |
132 David Fraser: Extract a method to represent keys in mappings, so that | |
133 a subclass can choose not to quote them (for example) | |
134 used in represent_mapping | |
135 https://bitbucket.org/davidfraser/pyyaml/commits/d81df6eb95f20cac4a79eed95ae553b5c6f77b8c | |
136 """ | |
137 return self.represent_data(data) | |
138 | |
139 @classmethod | |
140 def add_representer(cls, data_type, representer): | |
141 # type: (Any, Any) -> None | |
142 if 'yaml_representers' not in cls.__dict__: | |
143 cls.yaml_representers = cls.yaml_representers.copy() | |
144 cls.yaml_representers[data_type] = representer | |
145 | |
146 @classmethod | |
147 def add_multi_representer(cls, data_type, representer): | |
148 # type: (Any, Any) -> None | |
149 if 'yaml_multi_representers' not in cls.__dict__: | |
150 cls.yaml_multi_representers = cls.yaml_multi_representers.copy() | |
151 cls.yaml_multi_representers[data_type] = representer | |
152 | |
153 def represent_scalar(self, tag, value, style=None, anchor=None): | |
154 # type: (Any, Any, Any, Any) -> Any | |
155 if style is None: | |
156 style = self.default_style | |
157 comment = None | |
158 if style and style[0] in '|>': | |
159 comment = getattr(value, 'comment', None) | |
160 if comment: | |
161 comment = [None, [comment]] | |
162 node = ScalarNode(tag, value, style=style, comment=comment, anchor=anchor) | |
163 if self.alias_key is not None: | |
164 self.represented_objects[self.alias_key] = node | |
165 return node | |
166 | |
167 def represent_sequence(self, tag, sequence, flow_style=None): | |
168 # type: (Any, Any, Any) -> Any | |
169 value = [] # type: List[Any] | |
170 node = SequenceNode(tag, value, flow_style=flow_style) | |
171 if self.alias_key is not None: | |
172 self.represented_objects[self.alias_key] = node | |
173 best_style = True | |
174 for item in sequence: | |
175 node_item = self.represent_data(item) | |
176 if not (isinstance(node_item, ScalarNode) and not node_item.style): | |
177 best_style = False | |
178 value.append(node_item) | |
179 if flow_style is None: | |
180 if self.default_flow_style is not None: | |
181 node.flow_style = self.default_flow_style | |
182 else: | |
183 node.flow_style = best_style | |
184 return node | |
185 | |
186 def represent_omap(self, tag, omap, flow_style=None): | |
187 # type: (Any, Any, Any) -> Any | |
188 value = [] # type: List[Any] | |
189 node = SequenceNode(tag, value, flow_style=flow_style) | |
190 if self.alias_key is not None: | |
191 self.represented_objects[self.alias_key] = node | |
192 best_style = True | |
193 for item_key in omap: | |
194 item_val = omap[item_key] | |
195 node_item = self.represent_data({item_key: item_val}) | |
196 # if not (isinstance(node_item, ScalarNode) \ | |
197 # and not node_item.style): | |
198 # best_style = False | |
199 value.append(node_item) | |
200 if flow_style is None: | |
201 if self.default_flow_style is not None: | |
202 node.flow_style = self.default_flow_style | |
203 else: | |
204 node.flow_style = best_style | |
205 return node | |
206 | |
207 def represent_mapping(self, tag, mapping, flow_style=None): | |
208 # type: (Any, Any, Any) -> Any | |
209 value = [] # type: List[Any] | |
210 node = MappingNode(tag, value, flow_style=flow_style) | |
211 if self.alias_key is not None: | |
212 self.represented_objects[self.alias_key] = node | |
213 best_style = True | |
214 if hasattr(mapping, 'items'): | |
215 mapping = list(mapping.items()) | |
216 if self.sort_base_mapping_type_on_output: | |
217 try: | |
218 mapping = sorted(mapping) | |
219 except TypeError: | |
220 pass | |
221 for item_key, item_value in mapping: | |
222 node_key = self.represent_key(item_key) | |
223 node_value = self.represent_data(item_value) | |
224 if not (isinstance(node_key, ScalarNode) and not node_key.style): | |
225 best_style = False | |
226 if not (isinstance(node_value, ScalarNode) and not node_value.style): | |
227 best_style = False | |
228 value.append((node_key, node_value)) | |
229 if flow_style is None: | |
230 if self.default_flow_style is not None: | |
231 node.flow_style = self.default_flow_style | |
232 else: | |
233 node.flow_style = best_style | |
234 return node | |
235 | |
236 def ignore_aliases(self, data): | |
237 # type: (Any) -> bool | |
238 return False | |
239 | |
240 | |
241 class SafeRepresenter(BaseRepresenter): | |
242 def ignore_aliases(self, data): | |
243 # type: (Any) -> bool | |
244 # https://docs.python.org/3/reference/expressions.html#parenthesized-forms : | |
245 # "i.e. two occurrences of the empty tuple may or may not yield the same object" | |
246 # so "data is ()" should not be used | |
247 if data is None or (isinstance(data, tuple) and data == ()): | |
248 return True | |
249 if isinstance(data, (binary_type, text_type, bool, int, float)): | |
250 return True | |
251 return False | |
252 | |
253 def represent_none(self, data): | |
254 # type: (Any) -> Any | |
255 return self.represent_scalar(u'tag:yaml.org,2002:null', u'null') | |
256 | |
257 if PY3: | |
258 | |
259 def represent_str(self, data): | |
260 # type: (Any) -> Any | |
261 return self.represent_scalar(u'tag:yaml.org,2002:str', data) | |
262 | |
263 def represent_binary(self, data): | |
264 # type: (Any) -> Any | |
265 if hasattr(base64, 'encodebytes'): | |
266 data = base64.encodebytes(data).decode('ascii') | |
267 else: | |
268 data = base64.encodestring(data).decode('ascii') | |
269 return self.represent_scalar(u'tag:yaml.org,2002:binary', data, style='|') | |
270 | |
271 else: | |
272 | |
273 def represent_str(self, data): | |
274 # type: (Any) -> Any | |
275 tag = None | |
276 style = None | |
277 try: | |
278 data = unicode(data, 'ascii') | |
279 tag = u'tag:yaml.org,2002:str' | |
280 except UnicodeDecodeError: | |
281 try: | |
282 data = unicode(data, 'utf-8') | |
283 tag = u'tag:yaml.org,2002:str' | |
284 except UnicodeDecodeError: | |
285 data = data.encode('base64') | |
286 tag = u'tag:yaml.org,2002:binary' | |
287 style = '|' | |
288 return self.represent_scalar(tag, data, style=style) | |
289 | |
290 def represent_unicode(self, data): | |
291 # type: (Any) -> Any | |
292 return self.represent_scalar(u'tag:yaml.org,2002:str', data) | |
293 | |
294 def represent_bool(self, data, anchor=None): | |
295 # type: (Any, Optional[Any]) -> Any | |
296 try: | |
297 value = self.dumper.boolean_representation[bool(data)] | |
298 except AttributeError: | |
299 if data: | |
300 value = u'true' | |
301 else: | |
302 value = u'false' | |
303 return self.represent_scalar(u'tag:yaml.org,2002:bool', value, anchor=anchor) | |
304 | |
305 def represent_int(self, data): | |
306 # type: (Any) -> Any | |
307 return self.represent_scalar(u'tag:yaml.org,2002:int', text_type(data)) | |
308 | |
309 if PY2: | |
310 | |
311 def represent_long(self, data): | |
312 # type: (Any) -> Any | |
313 return self.represent_scalar(u'tag:yaml.org,2002:int', text_type(data)) | |
314 | |
315 inf_value = 1e300 | |
316 while repr(inf_value) != repr(inf_value * inf_value): | |
317 inf_value *= inf_value | |
318 | |
319 def represent_float(self, data): | |
320 # type: (Any) -> Any | |
321 if data != data or (data == 0.0 and data == 1.0): | |
322 value = u'.nan' | |
323 elif data == self.inf_value: | |
324 value = u'.inf' | |
325 elif data == -self.inf_value: | |
326 value = u'-.inf' | |
327 else: | |
328 value = to_unicode(repr(data)).lower() | |
329 if getattr(self.serializer, 'use_version', None) == (1, 1): | |
330 if u'.' not in value and u'e' in value: | |
331 # Note that in some cases `repr(data)` represents a float number | |
332 # without the decimal parts. For instance: | |
333 # >>> repr(1e17) | |
334 # '1e17' | |
335 # Unfortunately, this is not a valid float representation according | |
336 # to the definition of the `!!float` tag in YAML 1.1. We fix | |
337 # this by adding '.0' before the 'e' symbol. | |
338 value = value.replace(u'e', u'.0e', 1) | |
339 return self.represent_scalar(u'tag:yaml.org,2002:float', value) | |
340 | |
341 def represent_list(self, data): | |
342 # type: (Any) -> Any | |
343 # pairs = (len(data) > 0 and isinstance(data, list)) | |
344 # if pairs: | |
345 # for item in data: | |
346 # if not isinstance(item, tuple) or len(item) != 2: | |
347 # pairs = False | |
348 # break | |
349 # if not pairs: | |
350 return self.represent_sequence(u'tag:yaml.org,2002:seq', data) | |
351 | |
352 # value = [] | |
353 # for item_key, item_value in data: | |
354 # value.append(self.represent_mapping(u'tag:yaml.org,2002:map', | |
355 # [(item_key, item_value)])) | |
356 # return SequenceNode(u'tag:yaml.org,2002:pairs', value) | |
357 | |
358 def represent_dict(self, data): | |
359 # type: (Any) -> Any | |
360 return self.represent_mapping(u'tag:yaml.org,2002:map', data) | |
361 | |
362 def represent_ordereddict(self, data): | |
363 # type: (Any) -> Any | |
364 return self.represent_omap(u'tag:yaml.org,2002:omap', data) | |
365 | |
366 def represent_set(self, data): | |
367 # type: (Any) -> Any | |
368 value = {} # type: Dict[Any, None] | |
369 for key in data: | |
370 value[key] = None | |
371 return self.represent_mapping(u'tag:yaml.org,2002:set', value) | |
372 | |
373 def represent_date(self, data): | |
374 # type: (Any) -> Any | |
375 value = to_unicode(data.isoformat()) | |
376 return self.represent_scalar(u'tag:yaml.org,2002:timestamp', value) | |
377 | |
378 def represent_datetime(self, data): | |
379 # type: (Any) -> Any | |
380 value = to_unicode(data.isoformat(' ')) | |
381 return self.represent_scalar(u'tag:yaml.org,2002:timestamp', value) | |
382 | |
383 def represent_yaml_object(self, tag, data, cls, flow_style=None): | |
384 # type: (Any, Any, Any, Any) -> Any | |
385 if hasattr(data, '__getstate__'): | |
386 state = data.__getstate__() | |
387 else: | |
388 state = data.__dict__.copy() | |
389 return self.represent_mapping(tag, state, flow_style=flow_style) | |
390 | |
391 def represent_undefined(self, data): | |
392 # type: (Any) -> None | |
393 raise RepresenterError('cannot represent an object: %s' % (data,)) | |
394 | |
395 | |
396 SafeRepresenter.add_representer(type(None), SafeRepresenter.represent_none) | |
397 | |
398 SafeRepresenter.add_representer(str, SafeRepresenter.represent_str) | |
399 | |
400 if PY2: | |
401 SafeRepresenter.add_representer(unicode, SafeRepresenter.represent_unicode) | |
402 else: | |
403 SafeRepresenter.add_representer(bytes, SafeRepresenter.represent_binary) | |
404 | |
405 SafeRepresenter.add_representer(bool, SafeRepresenter.represent_bool) | |
406 | |
407 SafeRepresenter.add_representer(int, SafeRepresenter.represent_int) | |
408 | |
409 if PY2: | |
410 SafeRepresenter.add_representer(long, SafeRepresenter.represent_long) | |
411 | |
412 SafeRepresenter.add_representer(float, SafeRepresenter.represent_float) | |
413 | |
414 SafeRepresenter.add_representer(list, SafeRepresenter.represent_list) | |
415 | |
416 SafeRepresenter.add_representer(tuple, SafeRepresenter.represent_list) | |
417 | |
418 SafeRepresenter.add_representer(dict, SafeRepresenter.represent_dict) | |
419 | |
420 SafeRepresenter.add_representer(set, SafeRepresenter.represent_set) | |
421 | |
422 SafeRepresenter.add_representer(ordereddict, SafeRepresenter.represent_ordereddict) | |
423 | |
424 if sys.version_info >= (2, 7): | |
425 import collections | |
426 | |
427 SafeRepresenter.add_representer( | |
428 collections.OrderedDict, SafeRepresenter.represent_ordereddict | |
429 ) | |
430 | |
431 SafeRepresenter.add_representer(datetime.date, SafeRepresenter.represent_date) | |
432 | |
433 SafeRepresenter.add_representer(datetime.datetime, SafeRepresenter.represent_datetime) | |
434 | |
435 SafeRepresenter.add_representer(None, SafeRepresenter.represent_undefined) | |
436 | |
437 | |
438 class Representer(SafeRepresenter): | |
439 if PY2: | |
440 | |
441 def represent_str(self, data): | |
442 # type: (Any) -> Any | |
443 tag = None | |
444 style = None | |
445 try: | |
446 data = unicode(data, 'ascii') | |
447 tag = u'tag:yaml.org,2002:str' | |
448 except UnicodeDecodeError: | |
449 try: | |
450 data = unicode(data, 'utf-8') | |
451 tag = u'tag:yaml.org,2002:python/str' | |
452 except UnicodeDecodeError: | |
453 data = data.encode('base64') | |
454 tag = u'tag:yaml.org,2002:binary' | |
455 style = '|' | |
456 return self.represent_scalar(tag, data, style=style) | |
457 | |
458 def represent_unicode(self, data): | |
459 # type: (Any) -> Any | |
460 tag = None | |
461 try: | |
462 data.encode('ascii') | |
463 tag = u'tag:yaml.org,2002:python/unicode' | |
464 except UnicodeEncodeError: | |
465 tag = u'tag:yaml.org,2002:str' | |
466 return self.represent_scalar(tag, data) | |
467 | |
468 def represent_long(self, data): | |
469 # type: (Any) -> Any | |
470 tag = u'tag:yaml.org,2002:int' | |
471 if int(data) is not data: | |
472 tag = u'tag:yaml.org,2002:python/long' | |
473 return self.represent_scalar(tag, to_unicode(data)) | |
474 | |
475 def represent_complex(self, data): | |
476 # type: (Any) -> Any | |
477 if data.imag == 0.0: | |
478 data = u'%r' % data.real | |
479 elif data.real == 0.0: | |
480 data = u'%rj' % data.imag | |
481 elif data.imag > 0: | |
482 data = u'%r+%rj' % (data.real, data.imag) | |
483 else: | |
484 data = u'%r%rj' % (data.real, data.imag) | |
485 return self.represent_scalar(u'tag:yaml.org,2002:python/complex', data) | |
486 | |
487 def represent_tuple(self, data): | |
488 # type: (Any) -> Any | |
489 return self.represent_sequence(u'tag:yaml.org,2002:python/tuple', data) | |
490 | |
491 def represent_name(self, data): | |
492 # type: (Any) -> Any | |
493 try: | |
494 name = u'%s.%s' % (data.__module__, data.__qualname__) | |
495 except AttributeError: | |
496 # probably PY2 | |
497 name = u'%s.%s' % (data.__module__, data.__name__) | |
498 return self.represent_scalar(u'tag:yaml.org,2002:python/name:' + name, "") | |
499 | |
500 def represent_module(self, data): | |
501 # type: (Any) -> Any | |
502 return self.represent_scalar(u'tag:yaml.org,2002:python/module:' + data.__name__, "") | |
503 | |
504 if PY2: | |
505 | |
506 def represent_instance(self, data): | |
507 # type: (Any) -> Any | |
508 # For instances of classic classes, we use __getinitargs__ and | |
509 # __getstate__ to serialize the data. | |
510 | |
511 # If data.__getinitargs__ exists, the object must be reconstructed | |
512 # by calling cls(**args), where args is a tuple returned by | |
513 # __getinitargs__. Otherwise, the cls.__init__ method should never | |
514 # be called and the class instance is created by instantiating a | |
515 # trivial class and assigning to the instance's __class__ variable. | |
516 | |
517 # If data.__getstate__ exists, it returns the state of the object. | |
518 # Otherwise, the state of the object is data.__dict__. | |
519 | |
520 # We produce either a !!python/object or !!python/object/new node. | |
521 # If data.__getinitargs__ does not exist and state is a dictionary, | |
522 # we produce a !!python/object node . Otherwise we produce a | |
523 # !!python/object/new node. | |
524 | |
525 cls = data.__class__ | |
526 class_name = u'%s.%s' % (cls.__module__, cls.__name__) | |
527 args = None | |
528 state = None | |
529 if hasattr(data, '__getinitargs__'): | |
530 args = list(data.__getinitargs__()) | |
531 if hasattr(data, '__getstate__'): | |
532 state = data.__getstate__() | |
533 else: | |
534 state = data.__dict__ | |
535 if args is None and isinstance(state, dict): | |
536 return self.represent_mapping( | |
537 u'tag:yaml.org,2002:python/object:' + class_name, state | |
538 ) | |
539 if isinstance(state, dict) and not state: | |
540 return self.represent_sequence( | |
541 u'tag:yaml.org,2002:python/object/new:' + class_name, args | |
542 ) | |
543 value = {} | |
544 if bool(args): | |
545 value['args'] = args | |
546 value['state'] = state # type: ignore | |
547 return self.represent_mapping( | |
548 u'tag:yaml.org,2002:python/object/new:' + class_name, value | |
549 ) | |
550 | |
551 def represent_object(self, data): | |
552 # type: (Any) -> Any | |
553 # We use __reduce__ API to save the data. data.__reduce__ returns | |
554 # a tuple of length 2-5: | |
555 # (function, args, state, listitems, dictitems) | |
556 | |
557 # For reconstructing, we calls function(*args), then set its state, | |
558 # listitems, and dictitems if they are not None. | |
559 | |
560 # A special case is when function.__name__ == '__newobj__'. In this | |
561 # case we create the object with args[0].__new__(*args). | |
562 | |
563 # Another special case is when __reduce__ returns a string - we don't | |
564 # support it. | |
565 | |
566 # We produce a !!python/object, !!python/object/new or | |
567 # !!python/object/apply node. | |
568 | |
569 cls = type(data) | |
570 if cls in copyreg.dispatch_table: | |
571 reduce = copyreg.dispatch_table[cls](data) | |
572 elif hasattr(data, '__reduce_ex__'): | |
573 reduce = data.__reduce_ex__(2) | |
574 elif hasattr(data, '__reduce__'): | |
575 reduce = data.__reduce__() | |
576 else: | |
577 raise RepresenterError('cannot represent object: %r' % (data,)) | |
578 reduce = (list(reduce) + [None] * 5)[:5] | |
579 function, args, state, listitems, dictitems = reduce | |
580 args = list(args) | |
581 if state is None: | |
582 state = {} | |
583 if listitems is not None: | |
584 listitems = list(listitems) | |
585 if dictitems is not None: | |
586 dictitems = dict(dictitems) | |
587 if function.__name__ == '__newobj__': | |
588 function = args[0] | |
589 args = args[1:] | |
590 tag = u'tag:yaml.org,2002:python/object/new:' | |
591 newobj = True | |
592 else: | |
593 tag = u'tag:yaml.org,2002:python/object/apply:' | |
594 newobj = False | |
595 try: | |
596 function_name = u'%s.%s' % (function.__module__, function.__qualname__) | |
597 except AttributeError: | |
598 # probably PY2 | |
599 function_name = u'%s.%s' % (function.__module__, function.__name__) | |
600 if not args and not listitems and not dictitems and isinstance(state, dict) and newobj: | |
601 return self.represent_mapping( | |
602 u'tag:yaml.org,2002:python/object:' + function_name, state | |
603 ) | |
604 if not listitems and not dictitems and isinstance(state, dict) and not state: | |
605 return self.represent_sequence(tag + function_name, args) | |
606 value = {} | |
607 if args: | |
608 value['args'] = args | |
609 if state or not isinstance(state, dict): | |
610 value['state'] = state | |
611 if listitems: | |
612 value['listitems'] = listitems | |
613 if dictitems: | |
614 value['dictitems'] = dictitems | |
615 return self.represent_mapping(tag + function_name, value) | |
616 | |
617 | |
618 if PY2: | |
619 Representer.add_representer(str, Representer.represent_str) | |
620 | |
621 Representer.add_representer(unicode, Representer.represent_unicode) | |
622 | |
623 Representer.add_representer(long, Representer.represent_long) | |
624 | |
625 Representer.add_representer(complex, Representer.represent_complex) | |
626 | |
627 Representer.add_representer(tuple, Representer.represent_tuple) | |
628 | |
629 Representer.add_representer(type, Representer.represent_name) | |
630 | |
631 if PY2: | |
632 Representer.add_representer(types.ClassType, Representer.represent_name) | |
633 | |
634 Representer.add_representer(types.FunctionType, Representer.represent_name) | |
635 | |
636 Representer.add_representer(types.BuiltinFunctionType, Representer.represent_name) | |
637 | |
638 Representer.add_representer(types.ModuleType, Representer.represent_module) | |
639 | |
640 if PY2: | |
641 Representer.add_multi_representer(types.InstanceType, Representer.represent_instance) | |
642 | |
643 Representer.add_multi_representer(object, Representer.represent_object) | |
644 | |
645 Representer.add_multi_representer(type, Representer.represent_name) | |
646 | |
647 from ruamel.yaml.comments import ( | |
648 CommentedMap, | |
649 CommentedOrderedMap, | |
650 CommentedSeq, | |
651 CommentedKeySeq, | |
652 CommentedKeyMap, | |
653 CommentedSet, | |
654 comment_attrib, | |
655 merge_attrib, | |
656 TaggedScalar, | |
657 ) # NOQA | |
658 | |
659 | |
660 class RoundTripRepresenter(SafeRepresenter): | |
661 # need to add type here and write out the .comment | |
662 # in serializer and emitter | |
663 | |
664 def __init__(self, default_style=None, default_flow_style=None, dumper=None): | |
665 # type: (Any, Any, Any) -> None | |
666 if not hasattr(dumper, 'typ') and default_flow_style is None: | |
667 default_flow_style = False | |
668 SafeRepresenter.__init__( | |
669 self, | |
670 default_style=default_style, | |
671 default_flow_style=default_flow_style, | |
672 dumper=dumper, | |
673 ) | |
674 | |
675 def ignore_aliases(self, data): | |
676 # type: (Any) -> bool | |
677 try: | |
678 if data.anchor is not None and data.anchor.value is not None: | |
679 return False | |
680 except AttributeError: | |
681 pass | |
682 return SafeRepresenter.ignore_aliases(self, data) | |
683 | |
684 def represent_none(self, data): | |
685 # type: (Any) -> Any | |
686 if len(self.represented_objects) == 0 and not self.serializer.use_explicit_start: | |
687 # this will be open ended (although it is not yet) | |
688 return self.represent_scalar(u'tag:yaml.org,2002:null', u'null') | |
689 return self.represent_scalar(u'tag:yaml.org,2002:null', "") | |
690 | |
691 def represent_literal_scalarstring(self, data): | |
692 # type: (Any) -> Any | |
693 tag = None | |
694 style = '|' | |
695 anchor = data.yaml_anchor(any=True) | |
696 if PY2 and not isinstance(data, unicode): | |
697 data = unicode(data, 'ascii') | |
698 tag = u'tag:yaml.org,2002:str' | |
699 return self.represent_scalar(tag, data, style=style, anchor=anchor) | |
700 | |
701 represent_preserved_scalarstring = represent_literal_scalarstring | |
702 | |
703 def represent_folded_scalarstring(self, data): | |
704 # type: (Any) -> Any | |
705 tag = None | |
706 style = '>' | |
707 anchor = data.yaml_anchor(any=True) | |
708 for fold_pos in reversed(getattr(data, 'fold_pos', [])): | |
709 if ( | |
710 data[fold_pos] == ' ' | |
711 and (fold_pos > 0 and not data[fold_pos - 1].isspace()) | |
712 and (fold_pos < len(data) and not data[fold_pos + 1].isspace()) | |
713 ): | |
714 data = data[:fold_pos] + '\a' + data[fold_pos:] | |
715 if PY2 and not isinstance(data, unicode): | |
716 data = unicode(data, 'ascii') | |
717 tag = u'tag:yaml.org,2002:str' | |
718 return self.represent_scalar(tag, data, style=style, anchor=anchor) | |
719 | |
720 def represent_single_quoted_scalarstring(self, data): | |
721 # type: (Any) -> Any | |
722 tag = None | |
723 style = "'" | |
724 anchor = data.yaml_anchor(any=True) | |
725 if PY2 and not isinstance(data, unicode): | |
726 data = unicode(data, 'ascii') | |
727 tag = u'tag:yaml.org,2002:str' | |
728 return self.represent_scalar(tag, data, style=style, anchor=anchor) | |
729 | |
730 def represent_double_quoted_scalarstring(self, data): | |
731 # type: (Any) -> Any | |
732 tag = None | |
733 style = '"' | |
734 anchor = data.yaml_anchor(any=True) | |
735 if PY2 and not isinstance(data, unicode): | |
736 data = unicode(data, 'ascii') | |
737 tag = u'tag:yaml.org,2002:str' | |
738 return self.represent_scalar(tag, data, style=style, anchor=anchor) | |
739 | |
740 def represent_plain_scalarstring(self, data): | |
741 # type: (Any) -> Any | |
742 tag = None | |
743 style = '' | |
744 anchor = data.yaml_anchor(any=True) | |
745 if PY2 and not isinstance(data, unicode): | |
746 data = unicode(data, 'ascii') | |
747 tag = u'tag:yaml.org,2002:str' | |
748 return self.represent_scalar(tag, data, style=style, anchor=anchor) | |
749 | |
750 def insert_underscore(self, prefix, s, underscore, anchor=None): | |
751 # type: (Any, Any, Any, Any) -> Any | |
752 if underscore is None: | |
753 return self.represent_scalar(u'tag:yaml.org,2002:int', prefix + s, anchor=anchor) | |
754 if underscore[0]: | |
755 sl = list(s) | |
756 pos = len(s) - underscore[0] | |
757 while pos > 0: | |
758 sl.insert(pos, '_') | |
759 pos -= underscore[0] | |
760 s = "".join(sl) | |
761 if underscore[1]: | |
762 s = '_' + s | |
763 if underscore[2]: | |
764 s += '_' | |
765 return self.represent_scalar(u'tag:yaml.org,2002:int', prefix + s, anchor=anchor) | |
766 | |
767 def represent_scalar_int(self, data): | |
768 # type: (Any) -> Any | |
769 if data._width is not None: | |
770 s = '{:0{}d}'.format(data, data._width) | |
771 else: | |
772 s = format(data, 'd') | |
773 anchor = data.yaml_anchor(any=True) | |
774 return self.insert_underscore("", s, data._underscore, anchor=anchor) | |
775 | |
776 def represent_binary_int(self, data): | |
777 # type: (Any) -> Any | |
778 if data._width is not None: | |
779 # cannot use '{:#0{}b}', that strips the zeros | |
780 s = '{:0{}b}'.format(data, data._width) | |
781 else: | |
782 s = format(data, 'b') | |
783 anchor = data.yaml_anchor(any=True) | |
784 return self.insert_underscore('0b', s, data._underscore, anchor=anchor) | |
785 | |
786 def represent_octal_int(self, data): | |
787 # type: (Any) -> Any | |
788 if data._width is not None: | |
789 # cannot use '{:#0{}o}', that strips the zeros | |
790 s = '{:0{}o}'.format(data, data._width) | |
791 else: | |
792 s = format(data, 'o') | |
793 anchor = data.yaml_anchor(any=True) | |
794 return self.insert_underscore('0o', s, data._underscore, anchor=anchor) | |
795 | |
796 def represent_hex_int(self, data): | |
797 # type: (Any) -> Any | |
798 if data._width is not None: | |
799 # cannot use '{:#0{}x}', that strips the zeros | |
800 s = '{:0{}x}'.format(data, data._width) | |
801 else: | |
802 s = format(data, 'x') | |
803 anchor = data.yaml_anchor(any=True) | |
804 return self.insert_underscore('0x', s, data._underscore, anchor=anchor) | |
805 | |
806 def represent_hex_caps_int(self, data): | |
807 # type: (Any) -> Any | |
808 if data._width is not None: | |
809 # cannot use '{:#0{}X}', that strips the zeros | |
810 s = '{:0{}X}'.format(data, data._width) | |
811 else: | |
812 s = format(data, 'X') | |
813 anchor = data.yaml_anchor(any=True) | |
814 return self.insert_underscore('0x', s, data._underscore, anchor=anchor) | |
815 | |
816 def represent_scalar_float(self, data): | |
817 # type: (Any) -> Any | |
818 """ this is way more complicated """ | |
819 value = None | |
820 anchor = data.yaml_anchor(any=True) | |
821 if data != data or (data == 0.0 and data == 1.0): | |
822 value = u'.nan' | |
823 elif data == self.inf_value: | |
824 value = u'.inf' | |
825 elif data == -self.inf_value: | |
826 value = u'-.inf' | |
827 if value: | |
828 return self.represent_scalar(u'tag:yaml.org,2002:float', value, anchor=anchor) | |
829 if data._exp is None and data._prec > 0 and data._prec == data._width - 1: | |
830 # no exponent, but trailing dot | |
831 value = u'{}{:d}.'.format(data._m_sign if data._m_sign else "", abs(int(data))) | |
832 elif data._exp is None: | |
833 # no exponent, "normal" dot | |
834 prec = data._prec | |
835 ms = data._m_sign if data._m_sign else "" | |
836 # -1 for the dot | |
837 value = u'{}{:0{}.{}f}'.format( | |
838 ms, abs(data), data._width - len(ms), data._width - prec - 1 | |
839 ) | |
840 if prec == 0 or (prec == 1 and ms != ""): | |
841 value = value.replace(u'0.', u'.') | |
842 while len(value) < data._width: | |
843 value += u'0' | |
844 else: | |
845 # exponent | |
846 m, es = u'{:{}.{}e}'.format( | |
847 # data, data._width, data._width - data._prec + (1 if data._m_sign else 0) | |
848 data, | |
849 data._width, | |
850 data._width + (1 if data._m_sign else 0), | |
851 ).split('e') | |
852 w = data._width if data._prec > 0 else (data._width + 1) | |
853 if data < 0: | |
854 w += 1 | |
855 m = m[:w] | |
856 e = int(es) | |
857 m1, m2 = m.split('.') # always second? | |
858 while len(m1) + len(m2) < data._width - (1 if data._prec >= 0 else 0): | |
859 m2 += u'0' | |
860 if data._m_sign and data > 0: | |
861 m1 = '+' + m1 | |
862 esgn = u'+' if data._e_sign else "" | |
863 if data._prec < 0: # mantissa without dot | |
864 if m2 != u'0': | |
865 e -= len(m2) | |
866 else: | |
867 m2 = "" | |
868 while (len(m1) + len(m2) - (1 if data._m_sign else 0)) < data._width: | |
869 m2 += u'0' | |
870 e -= 1 | |
871 value = m1 + m2 + data._exp + u'{:{}0{}d}'.format(e, esgn, data._e_width) | |
872 elif data._prec == 0: # mantissa with trailing dot | |
873 e -= len(m2) | |
874 value = ( | |
875 m1 + m2 + u'.' + data._exp + u'{:{}0{}d}'.format(e, esgn, data._e_width) | |
876 ) | |
877 else: | |
878 if data._m_lead0 > 0: | |
879 m2 = u'0' * (data._m_lead0 - 1) + m1 + m2 | |
880 m1 = u'0' | |
881 m2 = m2[: -data._m_lead0] # these should be zeros | |
882 e += data._m_lead0 | |
883 while len(m1) < data._prec: | |
884 m1 += m2[0] | |
885 m2 = m2[1:] | |
886 e -= 1 | |
887 value = ( | |
888 m1 + u'.' + m2 + data._exp + u'{:{}0{}d}'.format(e, esgn, data._e_width) | |
889 ) | |
890 | |
891 if value is None: | |
892 value = to_unicode(repr(data)).lower() | |
893 return self.represent_scalar(u'tag:yaml.org,2002:float', value, anchor=anchor) | |
894 | |
895 def represent_sequence(self, tag, sequence, flow_style=None): | |
896 # type: (Any, Any, Any) -> Any | |
897 value = [] # type: List[Any] | |
898 # if the flow_style is None, the flow style tacked on to the object | |
899 # explicitly will be taken. If that is None as well the default flow | |
900 # style rules | |
901 try: | |
902 flow_style = sequence.fa.flow_style(flow_style) | |
903 except AttributeError: | |
904 flow_style = flow_style | |
905 try: | |
906 anchor = sequence.yaml_anchor() | |
907 except AttributeError: | |
908 anchor = None | |
909 node = SequenceNode(tag, value, flow_style=flow_style, anchor=anchor) | |
910 if self.alias_key is not None: | |
911 self.represented_objects[self.alias_key] = node | |
912 best_style = True | |
913 try: | |
914 comment = getattr(sequence, comment_attrib) | |
915 node.comment = comment.comment | |
916 # reset any comment already printed information | |
917 if node.comment and node.comment[1]: | |
918 for ct in node.comment[1]: | |
919 ct.reset() | |
920 item_comments = comment.items | |
921 for v in item_comments.values(): | |
922 if v and v[1]: | |
923 for ct in v[1]: | |
924 ct.reset() | |
925 item_comments = comment.items | |
926 node.comment = comment.comment | |
927 try: | |
928 node.comment.append(comment.end) | |
929 except AttributeError: | |
930 pass | |
931 except AttributeError: | |
932 item_comments = {} | |
933 for idx, item in enumerate(sequence): | |
934 node_item = self.represent_data(item) | |
935 self.merge_comments(node_item, item_comments.get(idx)) | |
936 if not (isinstance(node_item, ScalarNode) and not node_item.style): | |
937 best_style = False | |
938 value.append(node_item) | |
939 if flow_style is None: | |
940 if len(sequence) != 0 and self.default_flow_style is not None: | |
941 node.flow_style = self.default_flow_style | |
942 else: | |
943 node.flow_style = best_style | |
944 return node | |
945 | |
946 def merge_comments(self, node, comments): | |
947 # type: (Any, Any) -> Any | |
948 if comments is None: | |
949 assert hasattr(node, 'comment') | |
950 return node | |
951 if getattr(node, 'comment', None) is not None: | |
952 for idx, val in enumerate(comments): | |
953 if idx >= len(node.comment): | |
954 continue | |
955 nc = node.comment[idx] | |
956 if nc is not None: | |
957 assert val is None or val == nc | |
958 comments[idx] = nc | |
959 node.comment = comments | |
960 return node | |
961 | |
962 def represent_key(self, data): | |
963 # type: (Any) -> Any | |
964 if isinstance(data, CommentedKeySeq): | |
965 self.alias_key = None | |
966 return self.represent_sequence(u'tag:yaml.org,2002:seq', data, flow_style=True) | |
967 if isinstance(data, CommentedKeyMap): | |
968 self.alias_key = None | |
969 return self.represent_mapping(u'tag:yaml.org,2002:map', data, flow_style=True) | |
970 return SafeRepresenter.represent_key(self, data) | |
971 | |
972 def represent_mapping(self, tag, mapping, flow_style=None): | |
973 # type: (Any, Any, Any) -> Any | |
974 value = [] # type: List[Any] | |
975 try: | |
976 flow_style = mapping.fa.flow_style(flow_style) | |
977 except AttributeError: | |
978 flow_style = flow_style | |
979 try: | |
980 anchor = mapping.yaml_anchor() | |
981 except AttributeError: | |
982 anchor = None | |
983 node = MappingNode(tag, value, flow_style=flow_style, anchor=anchor) | |
984 if self.alias_key is not None: | |
985 self.represented_objects[self.alias_key] = node | |
986 best_style = True | |
987 # no sorting! !! | |
988 try: | |
989 comment = getattr(mapping, comment_attrib) | |
990 node.comment = comment.comment | |
991 if node.comment and node.comment[1]: | |
992 for ct in node.comment[1]: | |
993 ct.reset() | |
994 item_comments = comment.items | |
995 for v in item_comments.values(): | |
996 if v and v[1]: | |
997 for ct in v[1]: | |
998 ct.reset() | |
999 try: | |
1000 node.comment.append(comment.end) | |
1001 except AttributeError: | |
1002 pass | |
1003 except AttributeError: | |
1004 item_comments = {} | |
1005 merge_list = [m[1] for m in getattr(mapping, merge_attrib, [])] | |
1006 try: | |
1007 merge_pos = getattr(mapping, merge_attrib, [[0]])[0][0] | |
1008 except IndexError: | |
1009 merge_pos = 0 | |
1010 item_count = 0 | |
1011 if bool(merge_list): | |
1012 items = mapping.non_merged_items() | |
1013 else: | |
1014 items = mapping.items() | |
1015 for item_key, item_value in items: | |
1016 item_count += 1 | |
1017 node_key = self.represent_key(item_key) | |
1018 node_value = self.represent_data(item_value) | |
1019 item_comment = item_comments.get(item_key) | |
1020 if item_comment: | |
1021 assert getattr(node_key, 'comment', None) is None | |
1022 node_key.comment = item_comment[:2] | |
1023 nvc = getattr(node_value, 'comment', None) | |
1024 if nvc is not None: # end comment already there | |
1025 nvc[0] = item_comment[2] | |
1026 nvc[1] = item_comment[3] | |
1027 else: | |
1028 node_value.comment = item_comment[2:] | |
1029 if not (isinstance(node_key, ScalarNode) and not node_key.style): | |
1030 best_style = False | |
1031 if not (isinstance(node_value, ScalarNode) and not node_value.style): | |
1032 best_style = False | |
1033 value.append((node_key, node_value)) | |
1034 if flow_style is None: | |
1035 if ((item_count != 0) or bool(merge_list)) and self.default_flow_style is not None: | |
1036 node.flow_style = self.default_flow_style | |
1037 else: | |
1038 node.flow_style = best_style | |
1039 if bool(merge_list): | |
1040 # because of the call to represent_data here, the anchors | |
1041 # are marked as being used and thereby created | |
1042 if len(merge_list) == 1: | |
1043 arg = self.represent_data(merge_list[0]) | |
1044 else: | |
1045 arg = self.represent_data(merge_list) | |
1046 arg.flow_style = True | |
1047 value.insert(merge_pos, (ScalarNode(u'tag:yaml.org,2002:merge', '<<'), arg)) | |
1048 return node | |
1049 | |
1050 def represent_omap(self, tag, omap, flow_style=None): | |
1051 # type: (Any, Any, Any) -> Any | |
1052 value = [] # type: List[Any] | |
1053 try: | |
1054 flow_style = omap.fa.flow_style(flow_style) | |
1055 except AttributeError: | |
1056 flow_style = flow_style | |
1057 try: | |
1058 anchor = omap.yaml_anchor() | |
1059 except AttributeError: | |
1060 anchor = None | |
1061 node = SequenceNode(tag, value, flow_style=flow_style, anchor=anchor) | |
1062 if self.alias_key is not None: | |
1063 self.represented_objects[self.alias_key] = node | |
1064 best_style = True | |
1065 try: | |
1066 comment = getattr(omap, comment_attrib) | |
1067 node.comment = comment.comment | |
1068 if node.comment and node.comment[1]: | |
1069 for ct in node.comment[1]: | |
1070 ct.reset() | |
1071 item_comments = comment.items | |
1072 for v in item_comments.values(): | |
1073 if v and v[1]: | |
1074 for ct in v[1]: | |
1075 ct.reset() | |
1076 try: | |
1077 node.comment.append(comment.end) | |
1078 except AttributeError: | |
1079 pass | |
1080 except AttributeError: | |
1081 item_comments = {} | |
1082 for item_key in omap: | |
1083 item_val = omap[item_key] | |
1084 node_item = self.represent_data({item_key: item_val}) | |
1085 # node_item.flow_style = False | |
1086 # node item has two scalars in value: node_key and node_value | |
1087 item_comment = item_comments.get(item_key) | |
1088 if item_comment: | |
1089 if item_comment[1]: | |
1090 node_item.comment = [None, item_comment[1]] | |
1091 assert getattr(node_item.value[0][0], 'comment', None) is None | |
1092 node_item.value[0][0].comment = [item_comment[0], None] | |
1093 nvc = getattr(node_item.value[0][1], 'comment', None) | |
1094 if nvc is not None: # end comment already there | |
1095 nvc[0] = item_comment[2] | |
1096 nvc[1] = item_comment[3] | |
1097 else: | |
1098 node_item.value[0][1].comment = item_comment[2:] | |
1099 # if not (isinstance(node_item, ScalarNode) \ | |
1100 # and not node_item.style): | |
1101 # best_style = False | |
1102 value.append(node_item) | |
1103 if flow_style is None: | |
1104 if self.default_flow_style is not None: | |
1105 node.flow_style = self.default_flow_style | |
1106 else: | |
1107 node.flow_style = best_style | |
1108 return node | |
1109 | |
1110 def represent_set(self, setting): | |
1111 # type: (Any) -> Any | |
1112 flow_style = False | |
1113 tag = u'tag:yaml.org,2002:set' | |
1114 # return self.represent_mapping(tag, value) | |
1115 value = [] # type: List[Any] | |
1116 flow_style = setting.fa.flow_style(flow_style) | |
1117 try: | |
1118 anchor = setting.yaml_anchor() | |
1119 except AttributeError: | |
1120 anchor = None | |
1121 node = MappingNode(tag, value, flow_style=flow_style, anchor=anchor) | |
1122 if self.alias_key is not None: | |
1123 self.represented_objects[self.alias_key] = node | |
1124 best_style = True | |
1125 # no sorting! !! | |
1126 try: | |
1127 comment = getattr(setting, comment_attrib) | |
1128 node.comment = comment.comment | |
1129 if node.comment and node.comment[1]: | |
1130 for ct in node.comment[1]: | |
1131 ct.reset() | |
1132 item_comments = comment.items | |
1133 for v in item_comments.values(): | |
1134 if v and v[1]: | |
1135 for ct in v[1]: | |
1136 ct.reset() | |
1137 try: | |
1138 node.comment.append(comment.end) | |
1139 except AttributeError: | |
1140 pass | |
1141 except AttributeError: | |
1142 item_comments = {} | |
1143 for item_key in setting.odict: | |
1144 node_key = self.represent_key(item_key) | |
1145 node_value = self.represent_data(None) | |
1146 item_comment = item_comments.get(item_key) | |
1147 if item_comment: | |
1148 assert getattr(node_key, 'comment', None) is None | |
1149 node_key.comment = item_comment[:2] | |
1150 node_key.style = node_value.style = '?' | |
1151 if not (isinstance(node_key, ScalarNode) and not node_key.style): | |
1152 best_style = False | |
1153 if not (isinstance(node_value, ScalarNode) and not node_value.style): | |
1154 best_style = False | |
1155 value.append((node_key, node_value)) | |
1156 best_style = best_style | |
1157 return node | |
1158 | |
1159 def represent_dict(self, data): | |
1160 # type: (Any) -> Any | |
1161 """write out tag if saved on loading""" | |
1162 try: | |
1163 t = data.tag.value | |
1164 except AttributeError: | |
1165 t = None | |
1166 if t: | |
1167 if t.startswith('!!'): | |
1168 tag = 'tag:yaml.org,2002:' + t[2:] | |
1169 else: | |
1170 tag = t | |
1171 else: | |
1172 tag = u'tag:yaml.org,2002:map' | |
1173 return self.represent_mapping(tag, data) | |
1174 | |
1175 def represent_list(self, data): | |
1176 # type: (Any) -> Any | |
1177 try: | |
1178 t = data.tag.value | |
1179 except AttributeError: | |
1180 t = None | |
1181 if t: | |
1182 if t.startswith('!!'): | |
1183 tag = 'tag:yaml.org,2002:' + t[2:] | |
1184 else: | |
1185 tag = t | |
1186 else: | |
1187 tag = u'tag:yaml.org,2002:seq' | |
1188 return self.represent_sequence(tag, data) | |
1189 | |
1190 def represent_datetime(self, data): | |
1191 # type: (Any) -> Any | |
1192 inter = 'T' if data._yaml['t'] else ' ' | |
1193 _yaml = data._yaml | |
1194 if _yaml['delta']: | |
1195 data += _yaml['delta'] | |
1196 value = data.isoformat(inter) | |
1197 else: | |
1198 value = data.isoformat(inter) | |
1199 if _yaml['tz']: | |
1200 value += _yaml['tz'] | |
1201 return self.represent_scalar(u'tag:yaml.org,2002:timestamp', to_unicode(value)) | |
1202 | |
1203 def represent_tagged_scalar(self, data): | |
1204 # type: (Any) -> Any | |
1205 try: | |
1206 tag = data.tag.value | |
1207 except AttributeError: | |
1208 tag = None | |
1209 try: | |
1210 anchor = data.yaml_anchor() | |
1211 except AttributeError: | |
1212 anchor = None | |
1213 return self.represent_scalar(tag, data.value, style=data.style, anchor=anchor) | |
1214 | |
1215 def represent_scalar_bool(self, data): | |
1216 # type: (Any) -> Any | |
1217 try: | |
1218 anchor = data.yaml_anchor() | |
1219 except AttributeError: | |
1220 anchor = None | |
1221 return SafeRepresenter.represent_bool(self, data, anchor=anchor) | |
1222 | |
1223 | |
1224 RoundTripRepresenter.add_representer(type(None), RoundTripRepresenter.represent_none) | |
1225 | |
1226 RoundTripRepresenter.add_representer( | |
1227 LiteralScalarString, RoundTripRepresenter.represent_literal_scalarstring | |
1228 ) | |
1229 | |
1230 RoundTripRepresenter.add_representer( | |
1231 FoldedScalarString, RoundTripRepresenter.represent_folded_scalarstring | |
1232 ) | |
1233 | |
1234 RoundTripRepresenter.add_representer( | |
1235 SingleQuotedScalarString, RoundTripRepresenter.represent_single_quoted_scalarstring | |
1236 ) | |
1237 | |
1238 RoundTripRepresenter.add_representer( | |
1239 DoubleQuotedScalarString, RoundTripRepresenter.represent_double_quoted_scalarstring | |
1240 ) | |
1241 | |
1242 RoundTripRepresenter.add_representer( | |
1243 PlainScalarString, RoundTripRepresenter.represent_plain_scalarstring | |
1244 ) | |
1245 | |
1246 RoundTripRepresenter.add_representer(ScalarInt, RoundTripRepresenter.represent_scalar_int) | |
1247 | |
1248 RoundTripRepresenter.add_representer(BinaryInt, RoundTripRepresenter.represent_binary_int) | |
1249 | |
1250 RoundTripRepresenter.add_representer(OctalInt, RoundTripRepresenter.represent_octal_int) | |
1251 | |
1252 RoundTripRepresenter.add_representer(HexInt, RoundTripRepresenter.represent_hex_int) | |
1253 | |
1254 RoundTripRepresenter.add_representer(HexCapsInt, RoundTripRepresenter.represent_hex_caps_int) | |
1255 | |
1256 RoundTripRepresenter.add_representer(ScalarFloat, RoundTripRepresenter.represent_scalar_float) | |
1257 | |
1258 RoundTripRepresenter.add_representer(ScalarBoolean, RoundTripRepresenter.represent_scalar_bool) | |
1259 | |
1260 RoundTripRepresenter.add_representer(CommentedSeq, RoundTripRepresenter.represent_list) | |
1261 | |
1262 RoundTripRepresenter.add_representer(CommentedMap, RoundTripRepresenter.represent_dict) | |
1263 | |
1264 RoundTripRepresenter.add_representer( | |
1265 CommentedOrderedMap, RoundTripRepresenter.represent_ordereddict | |
1266 ) | |
1267 | |
1268 if sys.version_info >= (2, 7): | |
1269 import collections | |
1270 | |
1271 RoundTripRepresenter.add_representer( | |
1272 collections.OrderedDict, RoundTripRepresenter.represent_ordereddict | |
1273 ) | |
1274 | |
1275 RoundTripRepresenter.add_representer(CommentedSet, RoundTripRepresenter.represent_set) | |
1276 | |
1277 RoundTripRepresenter.add_representer( | |
1278 TaggedScalar, RoundTripRepresenter.represent_tagged_scalar | |
1279 ) | |
1280 | |
1281 RoundTripRepresenter.add_representer(TimeStamp, RoundTripRepresenter.represent_datetime) |