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