Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/yaml/constructor.py @ 0:26e78fe6e8c4 draft
"planemo upload commit c699937486c35866861690329de38ec1a5d9f783"
| author | shellac |
|---|---|
| date | Sat, 02 May 2020 07:14:21 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:26e78fe6e8c4 |
|---|---|
| 1 | |
| 2 __all__ = [ | |
| 3 'BaseConstructor', | |
| 4 'SafeConstructor', | |
| 5 'FullConstructor', | |
| 6 'UnsafeConstructor', | |
| 7 'Constructor', | |
| 8 'ConstructorError' | |
| 9 ] | |
| 10 | |
| 11 from .error import * | |
| 12 from .nodes import * | |
| 13 | |
| 14 import collections.abc, datetime, base64, binascii, re, sys, types | |
| 15 | |
| 16 class ConstructorError(MarkedYAMLError): | |
| 17 pass | |
| 18 | |
| 19 class 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 | |
| 171 class 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 | |
| 431 SafeConstructor.add_constructor( | |
| 432 'tag:yaml.org,2002:null', | |
| 433 SafeConstructor.construct_yaml_null) | |
| 434 | |
| 435 SafeConstructor.add_constructor( | |
| 436 'tag:yaml.org,2002:bool', | |
| 437 SafeConstructor.construct_yaml_bool) | |
| 438 | |
| 439 SafeConstructor.add_constructor( | |
| 440 'tag:yaml.org,2002:int', | |
| 441 SafeConstructor.construct_yaml_int) | |
| 442 | |
| 443 SafeConstructor.add_constructor( | |
| 444 'tag:yaml.org,2002:float', | |
| 445 SafeConstructor.construct_yaml_float) | |
| 446 | |
| 447 SafeConstructor.add_constructor( | |
| 448 'tag:yaml.org,2002:binary', | |
| 449 SafeConstructor.construct_yaml_binary) | |
| 450 | |
| 451 SafeConstructor.add_constructor( | |
| 452 'tag:yaml.org,2002:timestamp', | |
| 453 SafeConstructor.construct_yaml_timestamp) | |
| 454 | |
| 455 SafeConstructor.add_constructor( | |
| 456 'tag:yaml.org,2002:omap', | |
| 457 SafeConstructor.construct_yaml_omap) | |
| 458 | |
| 459 SafeConstructor.add_constructor( | |
| 460 'tag:yaml.org,2002:pairs', | |
| 461 SafeConstructor.construct_yaml_pairs) | |
| 462 | |
| 463 SafeConstructor.add_constructor( | |
| 464 'tag:yaml.org,2002:set', | |
| 465 SafeConstructor.construct_yaml_set) | |
| 466 | |
| 467 SafeConstructor.add_constructor( | |
| 468 'tag:yaml.org,2002:str', | |
| 469 SafeConstructor.construct_yaml_str) | |
| 470 | |
| 471 SafeConstructor.add_constructor( | |
| 472 'tag:yaml.org,2002:seq', | |
| 473 SafeConstructor.construct_yaml_seq) | |
| 474 | |
| 475 SafeConstructor.add_constructor( | |
| 476 'tag:yaml.org,2002:map', | |
| 477 SafeConstructor.construct_yaml_map) | |
| 478 | |
| 479 SafeConstructor.add_constructor(None, | |
| 480 SafeConstructor.construct_undefined) | |
| 481 | |
| 482 class 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 | |
| 661 FullConstructor.add_constructor( | |
| 662 'tag:yaml.org,2002:python/none', | |
| 663 FullConstructor.construct_yaml_null) | |
| 664 | |
| 665 FullConstructor.add_constructor( | |
| 666 'tag:yaml.org,2002:python/bool', | |
| 667 FullConstructor.construct_yaml_bool) | |
| 668 | |
| 669 FullConstructor.add_constructor( | |
| 670 'tag:yaml.org,2002:python/str', | |
| 671 FullConstructor.construct_python_str) | |
| 672 | |
| 673 FullConstructor.add_constructor( | |
| 674 'tag:yaml.org,2002:python/unicode', | |
| 675 FullConstructor.construct_python_unicode) | |
| 676 | |
| 677 FullConstructor.add_constructor( | |
| 678 'tag:yaml.org,2002:python/bytes', | |
| 679 FullConstructor.construct_python_bytes) | |
| 680 | |
| 681 FullConstructor.add_constructor( | |
| 682 'tag:yaml.org,2002:python/int', | |
| 683 FullConstructor.construct_yaml_int) | |
| 684 | |
| 685 FullConstructor.add_constructor( | |
| 686 'tag:yaml.org,2002:python/long', | |
| 687 FullConstructor.construct_python_long) | |
| 688 | |
| 689 FullConstructor.add_constructor( | |
| 690 'tag:yaml.org,2002:python/float', | |
| 691 FullConstructor.construct_yaml_float) | |
| 692 | |
| 693 FullConstructor.add_constructor( | |
| 694 'tag:yaml.org,2002:python/complex', | |
| 695 FullConstructor.construct_python_complex) | |
| 696 | |
| 697 FullConstructor.add_constructor( | |
| 698 'tag:yaml.org,2002:python/list', | |
| 699 FullConstructor.construct_yaml_seq) | |
| 700 | |
| 701 FullConstructor.add_constructor( | |
| 702 'tag:yaml.org,2002:python/tuple', | |
| 703 FullConstructor.construct_python_tuple) | |
| 704 | |
| 705 FullConstructor.add_constructor( | |
| 706 'tag:yaml.org,2002:python/dict', | |
| 707 FullConstructor.construct_yaml_map) | |
| 708 | |
| 709 FullConstructor.add_multi_constructor( | |
| 710 'tag:yaml.org,2002:python/name:', | |
| 711 FullConstructor.construct_python_name) | |
| 712 | |
| 713 FullConstructor.add_multi_constructor( | |
| 714 'tag:yaml.org,2002:python/module:', | |
| 715 FullConstructor.construct_python_module) | |
| 716 | |
| 717 FullConstructor.add_multi_constructor( | |
| 718 'tag:yaml.org,2002:python/object:', | |
| 719 FullConstructor.construct_python_object) | |
| 720 | |
| 721 FullConstructor.add_multi_constructor( | |
| 722 'tag:yaml.org,2002:python/object/new:', | |
| 723 FullConstructor.construct_python_object_new) | |
| 724 | |
| 725 class UnsafeConstructor(FullConstructor): | |
| 726 | |
| 727 def find_python_module(self, name, mark): | |
| 728 return super(UnsafeConstructor, self).find_python_module(name, mark, unsafe=True) | |
| 729 | |
| 730 def find_python_name(self, name, mark): | |
| 731 return super(UnsafeConstructor, self).find_python_name(name, mark, unsafe=True) | |
| 732 | |
| 733 def make_python_instance(self, suffix, node, args=None, kwds=None, newobj=False): | |
| 734 return super(UnsafeConstructor, self).make_python_instance( | |
| 735 suffix, node, args, kwds, newobj, unsafe=True) | |
| 736 | |
| 737 def set_python_instance_state(self, instance, state): | |
| 738 return super(UnsafeConstructor, self).set_python_instance_state( | |
| 739 instance, state, unsafe=True) | |
| 740 | |
| 741 UnsafeConstructor.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. | |
| 747 class Constructor(UnsafeConstructor): | |
| 748 pass |
