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) |
