constructor.py 28 KB

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