representer.py 48 KB

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