constructor.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. # SPDX-License-Identifier: MIT
  2. __all__ = ['BaseConstructor', 'SafeConstructor', 'Constructor',
  3. 'ConstructorError']
  4. from error import *
  5. from nodes import *
  6. import datetime
  7. import binascii, re, sys, types
  8. class ConstructorError(MarkedYAMLError):
  9. pass
  10. class BaseConstructor(object):
  11. yaml_constructors = {}
  12. yaml_multi_constructors = {}
  13. def __init__(self):
  14. self.constructed_objects = {}
  15. self.recursive_objects = {}
  16. self.state_generators = []
  17. self.deep_construct = False
  18. def check_data(self):
  19. # If there are more documents available?
  20. return self.check_node()
  21. def get_data(self):
  22. # Construct and return the next document.
  23. if self.check_node():
  24. return self.construct_document(self.get_node())
  25. def get_single_data(self):
  26. # Ensure that the stream contains a single document and construct it.
  27. node = self.get_single_node()
  28. if node is not None:
  29. return self.construct_document(node)
  30. return None
  31. def construct_document(self, node):
  32. data = self.construct_object(node)
  33. while self.state_generators:
  34. state_generators = self.state_generators
  35. self.state_generators = []
  36. for generator in state_generators:
  37. for dummy in generator:
  38. pass
  39. self.constructed_objects = {}
  40. self.recursive_objects = {}
  41. self.deep_construct = False
  42. return data
  43. def construct_object(self, node, deep=False):
  44. if node in self.constructed_objects:
  45. return self.constructed_objects[node]
  46. if deep:
  47. old_deep = self.deep_construct
  48. self.deep_construct = True
  49. if node in self.recursive_objects:
  50. raise ConstructorError(None, None,
  51. "found unconstructable recursive node", node.start_mark)
  52. self.recursive_objects[node] = None
  53. constructor = None
  54. tag_suffix = None
  55. if node.tag in self.yaml_constructors:
  56. constructor = self.yaml_constructors[node.tag]
  57. else:
  58. for tag_prefix in self.yaml_multi_constructors:
  59. if node.tag.startswith(tag_prefix):
  60. tag_suffix = node.tag[len(tag_prefix):]
  61. constructor = self.yaml_multi_constructors[tag_prefix]
  62. break
  63. else:
  64. if None in self.yaml_multi_constructors:
  65. tag_suffix = node.tag
  66. constructor = self.yaml_multi_constructors[None]
  67. elif None in self.yaml_constructors:
  68. constructor = self.yaml_constructors[None]
  69. elif isinstance(node, ScalarNode):
  70. constructor = self.__class__.construct_scalar
  71. elif isinstance(node, SequenceNode):
  72. constructor = self.__class__.construct_sequence
  73. elif isinstance(node, MappingNode):
  74. constructor = self.__class__.construct_mapping
  75. if tag_suffix is None:
  76. data = constructor(self, node)
  77. else:
  78. data = constructor(self, tag_suffix, node)
  79. if isinstance(data, types.GeneratorType):
  80. generator = data
  81. data = generator.next()
  82. if self.deep_construct:
  83. for dummy in generator:
  84. pass
  85. else:
  86. self.state_generators.append(generator)
  87. self.constructed_objects[node] = data
  88. del self.recursive_objects[node]
  89. if deep:
  90. self.deep_construct = old_deep
  91. return data
  92. def construct_scalar(self, node):
  93. if not isinstance(node, ScalarNode):
  94. raise ConstructorError(None, None,
  95. "expected a scalar node, but found %s" % node.id,
  96. node.start_mark)
  97. return node.value
  98. def construct_sequence(self, node, deep=False):
  99. if not isinstance(node, SequenceNode):
  100. raise ConstructorError(None, None,
  101. "expected a sequence node, but found %s" % node.id,
  102. node.start_mark)
  103. return [self.construct_object(child, deep=deep)
  104. for child in node.value]
  105. def construct_mapping(self, node, deep=False):
  106. if not isinstance(node, MappingNode):
  107. raise ConstructorError(None, None,
  108. "expected a mapping node, but found %s" % node.id,
  109. node.start_mark)
  110. mapping = {}
  111. for key_node, value_node in node.value:
  112. key = self.construct_object(key_node, deep=deep)
  113. try:
  114. hash(key)
  115. except TypeError, exc:
  116. raise ConstructorError("while constructing a mapping", node.start_mark,
  117. "found unacceptable key (%s)" % exc, key_node.start_mark)
  118. value = self.construct_object(value_node, deep=deep)
  119. mapping[key] = value
  120. return mapping
  121. def construct_pairs(self, node, deep=False):
  122. if not isinstance(node, MappingNode):
  123. raise ConstructorError(None, None,
  124. "expected a mapping node, but found %s" % node.id,
  125. node.start_mark)
  126. pairs = []
  127. for key_node, value_node in node.value:
  128. key = self.construct_object(key_node, deep=deep)
  129. value = self.construct_object(value_node, deep=deep)
  130. pairs.append((key, value))
  131. return pairs
  132. def add_constructor(cls, tag, constructor):
  133. if not 'yaml_constructors' in cls.__dict__:
  134. cls.yaml_constructors = cls.yaml_constructors.copy()
  135. cls.yaml_constructors[tag] = constructor
  136. add_constructor = classmethod(add_constructor)
  137. def add_multi_constructor(cls, tag_prefix, multi_constructor):
  138. if not 'yaml_multi_constructors' in cls.__dict__:
  139. cls.yaml_multi_constructors = cls.yaml_multi_constructors.copy()
  140. cls.yaml_multi_constructors[tag_prefix] = multi_constructor
  141. add_multi_constructor = classmethod(add_multi_constructor)
  142. class SafeConstructor(BaseConstructor):
  143. def construct_scalar(self, node):
  144. if isinstance(node, MappingNode):
  145. for key_node, value_node in node.value:
  146. if key_node.tag == u'tag:yaml.org,2002:value':
  147. return self.construct_scalar(value_node)
  148. return BaseConstructor.construct_scalar(self, node)
  149. def flatten_mapping(self, node):
  150. merge = []
  151. index = 0
  152. while index < len(node.value):
  153. key_node, value_node = node.value[index]
  154. if key_node.tag == u'tag:yaml.org,2002:merge':
  155. del node.value[index]
  156. if isinstance(value_node, MappingNode):
  157. self.flatten_mapping(value_node)
  158. merge.extend(value_node.value)
  159. elif isinstance(value_node, SequenceNode):
  160. submerge = []
  161. for subnode in value_node.value:
  162. if not isinstance(subnode, MappingNode):
  163. raise ConstructorError("while constructing a mapping",
  164. node.start_mark,
  165. "expected a mapping for merging, but found %s"
  166. % subnode.id, subnode.start_mark)
  167. self.flatten_mapping(subnode)
  168. submerge.append(subnode.value)
  169. submerge.reverse()
  170. for value in submerge:
  171. merge.extend(value)
  172. else:
  173. raise ConstructorError("while constructing a mapping", node.start_mark,
  174. "expected a mapping or list of mappings for merging, but found %s"
  175. % value_node.id, value_node.start_mark)
  176. elif key_node.tag == u'tag:yaml.org,2002:value':
  177. key_node.tag = u'tag:yaml.org,2002:str'
  178. index += 1
  179. else:
  180. index += 1
  181. if merge:
  182. node.value = merge + node.value
  183. def construct_mapping(self, node, deep=False):
  184. if isinstance(node, MappingNode):
  185. self.flatten_mapping(node)
  186. return BaseConstructor.construct_mapping(self, node, deep=deep)
  187. def construct_yaml_null(self, node):
  188. self.construct_scalar(node)
  189. return None
  190. bool_values = {
  191. u'yes': True,
  192. u'no': False,
  193. u'true': True,
  194. u'false': False,
  195. u'on': True,
  196. u'off': False,
  197. }
  198. def construct_yaml_bool(self, node):
  199. value = self.construct_scalar(node)
  200. return self.bool_values[value.lower()]
  201. def construct_yaml_int(self, node):
  202. value = str(self.construct_scalar(node))
  203. value = value.replace('_', '')
  204. sign = +1
  205. if value[0] == '-':
  206. sign = -1
  207. if value[0] in '+-':
  208. value = value[1:]
  209. if value == '0':
  210. return 0
  211. elif value.startswith('0b'):
  212. return sign*int(value[2:], 2)
  213. elif value.startswith('0x'):
  214. return sign*int(value[2:], 16)
  215. elif value[0] == '0':
  216. return sign*int(value, 8)
  217. elif ':' in value:
  218. digits = [int(part) for part in value.split(':')]
  219. digits.reverse()
  220. base = 1
  221. value = 0
  222. for digit in digits:
  223. value += digit*base
  224. base *= 60
  225. return sign*value
  226. else:
  227. return sign*int(value)
  228. inf_value = 1e300
  229. while inf_value != inf_value*inf_value:
  230. inf_value *= inf_value
  231. nan_value = -inf_value/inf_value # Trying to make a quiet NaN (like C99).
  232. def construct_yaml_float(self, node):
  233. value = str(self.construct_scalar(node))
  234. value = value.replace('_', '').lower()
  235. sign = +1
  236. if value[0] == '-':
  237. sign = -1
  238. if value[0] in '+-':
  239. value = value[1:]
  240. if value == '.inf':
  241. return sign*self.inf_value
  242. elif value == '.nan':
  243. return self.nan_value
  244. elif ':' in value:
  245. digits = [float(part) for part in value.split(':')]
  246. digits.reverse()
  247. base = 1
  248. value = 0.0
  249. for digit in digits:
  250. value += digit*base
  251. base *= 60
  252. return sign*value
  253. else:
  254. return sign*float(value)
  255. def construct_yaml_binary(self, node):
  256. value = self.construct_scalar(node)
  257. try:
  258. return str(value).decode('base64')
  259. except (binascii.Error, UnicodeEncodeError), exc:
  260. raise ConstructorError(None, None,
  261. "failed to decode base64 data: %s" % exc, node.start_mark)
  262. timestamp_regexp = re.compile(
  263. ur'''^(?P<year>[0-9][0-9][0-9][0-9])
  264. -(?P<month>[0-9][0-9]?)
  265. -(?P<day>[0-9][0-9]?)
  266. (?:(?:[Tt]|[ \t]+)
  267. (?P<hour>[0-9][0-9]?)
  268. :(?P<minute>[0-9][0-9])
  269. :(?P<second>[0-9][0-9])
  270. (?:\.(?P<fraction>[0-9]*))?
  271. (?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?)
  272. (?::(?P<tz_minute>[0-9][0-9]))?))?)?$''', re.X)
  273. def construct_yaml_timestamp(self, node):
  274. value = self.construct_scalar(node)
  275. match = self.timestamp_regexp.match(node.value)
  276. values = match.groupdict()
  277. year = int(values['year'])
  278. month = int(values['month'])
  279. day = int(values['day'])
  280. if not values['hour']:
  281. return datetime.date(year, month, day)
  282. hour = int(values['hour'])
  283. minute = int(values['minute'])
  284. second = int(values['second'])
  285. fraction = 0
  286. if values['fraction']:
  287. fraction = values['fraction'][:6]
  288. while len(fraction) < 6:
  289. fraction += '0'
  290. fraction = int(fraction)
  291. delta = None
  292. if values['tz_sign']:
  293. tz_hour = int(values['tz_hour'])
  294. tz_minute = int(values['tz_minute'] or 0)
  295. delta = datetime.timedelta(hours=tz_hour, minutes=tz_minute)
  296. if values['tz_sign'] == '-':
  297. delta = -delta
  298. data = datetime.datetime(year, month, day, hour, minute, second, fraction)
  299. if delta:
  300. data -= delta
  301. return data
  302. def construct_yaml_omap(self, node):
  303. # Note: we do not check for duplicate keys, because it's too
  304. # CPU-expensive.
  305. omap = []
  306. yield omap
  307. if not isinstance(node, SequenceNode):
  308. raise ConstructorError("while constructing an ordered map", node.start_mark,
  309. "expected a sequence, but found %s" % node.id, node.start_mark)
  310. for subnode in node.value:
  311. if not isinstance(subnode, MappingNode):
  312. raise ConstructorError("while constructing an ordered map", node.start_mark,
  313. "expected a mapping of length 1, but found %s" % subnode.id,
  314. subnode.start_mark)
  315. if len(subnode.value) != 1:
  316. raise ConstructorError("while constructing an ordered map", node.start_mark,
  317. "expected a single mapping item, but found %d items" % len(subnode.value),
  318. subnode.start_mark)
  319. key_node, value_node = subnode.value[0]
  320. key = self.construct_object(key_node)
  321. value = self.construct_object(value_node)
  322. omap.append((key, value))
  323. def construct_yaml_pairs(self, node):
  324. # Note: the same code as `construct_yaml_omap`.
  325. pairs = []
  326. yield pairs
  327. if not isinstance(node, SequenceNode):
  328. raise ConstructorError("while constructing pairs", node.start_mark,
  329. "expected a sequence, but found %s" % node.id, node.start_mark)
  330. for subnode in node.value:
  331. if not isinstance(subnode, MappingNode):
  332. raise ConstructorError("while constructing pairs", node.start_mark,
  333. "expected a mapping of length 1, but found %s" % subnode.id,
  334. subnode.start_mark)
  335. if len(subnode.value) != 1:
  336. raise ConstructorError("while constructing pairs", node.start_mark,
  337. "expected a single mapping item, but found %d items" % len(subnode.value),
  338. subnode.start_mark)
  339. key_node, value_node = subnode.value[0]
  340. key = self.construct_object(key_node)
  341. value = self.construct_object(value_node)
  342. pairs.append((key, value))
  343. def construct_yaml_set(self, node):
  344. data = set()
  345. yield data
  346. value = self.construct_mapping(node)
  347. data.update(value)
  348. def construct_yaml_str(self, node):
  349. value = self.construct_scalar(node)
  350. try:
  351. return value.encode('ascii')
  352. except UnicodeEncodeError:
  353. return value
  354. def construct_yaml_seq(self, node):
  355. data = []
  356. yield data
  357. data.extend(self.construct_sequence(node))
  358. def construct_yaml_map(self, node):
  359. data = {}
  360. yield data
  361. value = self.construct_mapping(node)
  362. data.update(value)
  363. def construct_yaml_object(self, node, cls):
  364. data = cls.__new__(cls)
  365. yield data
  366. if hasattr(data, '__setstate__'):
  367. state = self.construct_mapping(node, deep=True)
  368. data.__setstate__(state)
  369. else:
  370. state = self.construct_mapping(node)
  371. data.__dict__.update(state)
  372. def construct_undefined(self, node):
  373. raise ConstructorError(None, None,
  374. "could not determine a constructor for the tag %r" % node.tag.encode('utf-8'),
  375. node.start_mark)
  376. SafeConstructor.add_constructor(
  377. u'tag:yaml.org,2002:null',
  378. SafeConstructor.construct_yaml_null)
  379. SafeConstructor.add_constructor(
  380. u'tag:yaml.org,2002:bool',
  381. SafeConstructor.construct_yaml_bool)
  382. SafeConstructor.add_constructor(
  383. u'tag:yaml.org,2002:int',
  384. SafeConstructor.construct_yaml_int)
  385. SafeConstructor.add_constructor(
  386. u'tag:yaml.org,2002:float',
  387. SafeConstructor.construct_yaml_float)
  388. SafeConstructor.add_constructor(
  389. u'tag:yaml.org,2002:binary',
  390. SafeConstructor.construct_yaml_binary)
  391. SafeConstructor.add_constructor(
  392. u'tag:yaml.org,2002:timestamp',
  393. SafeConstructor.construct_yaml_timestamp)
  394. SafeConstructor.add_constructor(
  395. u'tag:yaml.org,2002:omap',
  396. SafeConstructor.construct_yaml_omap)
  397. SafeConstructor.add_constructor(
  398. u'tag:yaml.org,2002:pairs',
  399. SafeConstructor.construct_yaml_pairs)
  400. SafeConstructor.add_constructor(
  401. u'tag:yaml.org,2002:set',
  402. SafeConstructor.construct_yaml_set)
  403. SafeConstructor.add_constructor(
  404. u'tag:yaml.org,2002:str',
  405. SafeConstructor.construct_yaml_str)
  406. SafeConstructor.add_constructor(
  407. u'tag:yaml.org,2002:seq',
  408. SafeConstructor.construct_yaml_seq)
  409. SafeConstructor.add_constructor(
  410. u'tag:yaml.org,2002:map',
  411. SafeConstructor.construct_yaml_map)
  412. SafeConstructor.add_constructor(None,
  413. SafeConstructor.construct_undefined)
  414. class Constructor(SafeConstructor):
  415. def construct_python_str(self, node):
  416. return self.construct_scalar(node).encode('utf-8')
  417. def construct_python_unicode(self, node):
  418. return self.construct_scalar(node)
  419. def construct_python_long(self, node):
  420. return long(self.construct_yaml_int(node))
  421. def construct_python_complex(self, node):
  422. return complex(self.construct_scalar(node))
  423. def construct_python_tuple(self, node):
  424. return tuple(self.construct_sequence(node))
  425. def find_python_module(self, name, mark):
  426. if not name:
  427. raise ConstructorError("while constructing a Python module", mark,
  428. "expected non-empty name appended to the tag", mark)
  429. try:
  430. __import__(name)
  431. except ImportError, exc:
  432. raise ConstructorError("while constructing a Python module", mark,
  433. "cannot find module %r (%s)" % (name.encode('utf-8'), exc), mark)
  434. return sys.modules[name]
  435. def find_python_name(self, name, mark):
  436. if not name:
  437. raise ConstructorError("while constructing a Python object", mark,
  438. "expected non-empty name appended to the tag", mark)
  439. if u'.' in name:
  440. module_name, object_name = name.rsplit('.', 1)
  441. else:
  442. module_name = '__builtin__'
  443. object_name = name
  444. try:
  445. __import__(module_name)
  446. except ImportError, exc:
  447. raise ConstructorError("while constructing a Python object", mark,
  448. "cannot find module %r (%s)" % (module_name.encode('utf-8'), exc), mark)
  449. module = sys.modules[module_name]
  450. if not hasattr(module, object_name):
  451. raise ConstructorError("while constructing a Python object", mark,
  452. "cannot find %r in the module %r" % (object_name.encode('utf-8'),
  453. module.__name__), mark)
  454. return getattr(module, object_name)
  455. def construct_python_name(self, suffix, node):
  456. value = self.construct_scalar(node)
  457. if value:
  458. raise ConstructorError("while constructing a Python name", node.start_mark,
  459. "expected the empty value, but found %r" % value.encode('utf-8'),
  460. node.start_mark)
  461. return self.find_python_name(suffix, node.start_mark)
  462. def construct_python_module(self, suffix, node):
  463. value = self.construct_scalar(node)
  464. if value:
  465. raise ConstructorError("while constructing a Python module", node.start_mark,
  466. "expected the empty value, but found %r" % value.encode('utf-8'),
  467. node.start_mark)
  468. return self.find_python_module(suffix, node.start_mark)
  469. class classobj: pass
  470. def make_python_instance(self, suffix, node,
  471. args=None, kwds=None, newobj=False):
  472. if not args:
  473. args = []
  474. if not kwds:
  475. kwds = {}
  476. cls = self.find_python_name(suffix, node.start_mark)
  477. if newobj and isinstance(cls, type(self.classobj)) \
  478. and not args and not kwds:
  479. instance = self.classobj()
  480. instance.__class__ = cls
  481. return instance
  482. elif newobj and isinstance(cls, type):
  483. return cls.__new__(cls, *args, **kwds)
  484. else:
  485. return cls(*args, **kwds)
  486. def set_python_instance_state(self, instance, state):
  487. if hasattr(instance, '__setstate__'):
  488. instance.__setstate__(state)
  489. else:
  490. slotstate = {}
  491. if isinstance(state, tuple) and len(state) == 2:
  492. state, slotstate = state
  493. if hasattr(instance, '__dict__'):
  494. instance.__dict__.update(state)
  495. elif state:
  496. slotstate.update(state)
  497. for key, value in slotstate.items():
  498. setattr(object, key, value)
  499. def construct_python_object(self, suffix, node):
  500. # Format:
  501. # !!python/object:module.name { ... state ... }
  502. instance = self.make_python_instance(suffix, node, newobj=True)
  503. yield instance
  504. deep = hasattr(instance, '__setstate__')
  505. state = self.construct_mapping(node, deep=deep)
  506. self.set_python_instance_state(instance, state)
  507. def construct_python_object_apply(self, suffix, node, newobj=False):
  508. # Format:
  509. # !!python/object/apply # (or !!python/object/new)
  510. # args: [ ... arguments ... ]
  511. # kwds: { ... keywords ... }
  512. # state: ... state ...
  513. # listitems: [ ... listitems ... ]
  514. # dictitems: { ... dictitems ... }
  515. # or short format:
  516. # !!python/object/apply [ ... arguments ... ]
  517. # The difference between !!python/object/apply and !!python/object/new
  518. # is how an object is created, check make_python_instance for details.
  519. if isinstance(node, SequenceNode):
  520. args = self.construct_sequence(node, deep=True)
  521. kwds = {}
  522. state = {}
  523. listitems = []
  524. dictitems = {}
  525. else:
  526. value = self.construct_mapping(node, deep=True)
  527. args = value.get('args', [])
  528. kwds = value.get('kwds', {})
  529. state = value.get('state', {})
  530. listitems = value.get('listitems', [])
  531. dictitems = value.get('dictitems', {})
  532. instance = self.make_python_instance(suffix, node, args, kwds, newobj)
  533. if state:
  534. self.set_python_instance_state(instance, state)
  535. if listitems:
  536. instance.extend(listitems)
  537. if dictitems:
  538. for key in dictitems:
  539. instance[key] = dictitems[key]
  540. return instance
  541. def construct_python_object_new(self, suffix, node):
  542. return self.construct_python_object_apply(suffix, node, newobj=True)
  543. Constructor.add_constructor(
  544. u'tag:yaml.org,2002:python/none',
  545. Constructor.construct_yaml_null)
  546. Constructor.add_constructor(
  547. u'tag:yaml.org,2002:python/bool',
  548. Constructor.construct_yaml_bool)
  549. Constructor.add_constructor(
  550. u'tag:yaml.org,2002:python/str',
  551. Constructor.construct_python_str)
  552. Constructor.add_constructor(
  553. u'tag:yaml.org,2002:python/unicode',
  554. Constructor.construct_python_unicode)
  555. Constructor.add_constructor(
  556. u'tag:yaml.org,2002:python/int',
  557. Constructor.construct_yaml_int)
  558. Constructor.add_constructor(
  559. u'tag:yaml.org,2002:python/long',
  560. Constructor.construct_python_long)
  561. Constructor.add_constructor(
  562. u'tag:yaml.org,2002:python/float',
  563. Constructor.construct_yaml_float)
  564. Constructor.add_constructor(
  565. u'tag:yaml.org,2002:python/complex',
  566. Constructor.construct_python_complex)
  567. Constructor.add_constructor(
  568. u'tag:yaml.org,2002:python/list',
  569. Constructor.construct_yaml_seq)
  570. Constructor.add_constructor(
  571. u'tag:yaml.org,2002:python/tuple',
  572. Constructor.construct_python_tuple)
  573. Constructor.add_constructor(
  574. u'tag:yaml.org,2002:python/dict',
  575. Constructor.construct_yaml_map)
  576. Constructor.add_multi_constructor(
  577. u'tag:yaml.org,2002:python/name:',
  578. Constructor.construct_python_name)
  579. Constructor.add_multi_constructor(
  580. u'tag:yaml.org,2002:python/module:',
  581. Constructor.construct_python_module)
  582. Constructor.add_multi_constructor(
  583. u'tag:yaml.org,2002:python/object:',
  584. Constructor.construct_python_object)
  585. Constructor.add_multi_constructor(
  586. u'tag:yaml.org,2002:python/object/apply:',
  587. Constructor.construct_python_object_apply)
  588. Constructor.add_multi_constructor(
  589. u'tag:yaml.org,2002:python/object/new:',
  590. Constructor.construct_python_object_new)