constructor.py 28 KB

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