Changeset 147 for pyyaml/trunk/lib/yaml
- Timestamp:
- 04/22/06 16:40:43 (6 years ago)
- Location:
- pyyaml/trunk/lib/yaml
- Files:
-
- 3 modified
-
__init__.py (modified) (1 diff)
-
constructor.py (modified) (2 diffs)
-
representer.py (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
pyyaml/trunk/lib/yaml/__init__.py
r146 r147 232 232 Dumper.add_representer(data_type, representer) 233 233 234 def add_multi_representer(data_type, multi_representer, Dumper=Dumper): 235 """ 236 Add a representer for the given type. 237 Multi-representer is a function accepting a Dumper instance 238 and an instance of the given data type or subtype 239 and producing the corresponding representation node. 240 """ 241 Dumper.add_multi_representer(data_type, multi_representer) 242 234 243 class YAMLObjectMetaclass(type): 235 244 """ -
pyyaml/trunk/lib/yaml/constructor.py
r146 r147 493 493 return self.find_python_module(suffix, node.start_mark) 494 494 495 class classobj: pass 496 497 def make_python_instance(self, suffix, node, 498 args=None, kwds=None, newobj=False): 499 if not args: 500 args = [] 501 if not kwds: 502 kwds = {} 503 cls = self.find_python_name(suffix, node.start_mark) 504 if newobj and isinstance(cls, type(self.classobj)) \ 505 and not args and not kwds: 506 instance = self.classobj() 507 instance.__class__ = cls 508 return instance 509 elif newobj and isinstance(cls, type): 510 return cls.__new__(cls, *args, **kwds) 511 else: 512 return cls(*args, **kwds) 513 514 def set_python_instance_state(self, instance, state): 515 if hasattr(instance, '__setstate__'): 516 instance.__setstate__(state) 517 else: 518 slotstate = {} 519 if isinstance(state, tuple) and len(state) == 2: 520 state, slotstate = state 521 if hasattr(instance, '__dict__'): 522 instance.__dict__.update(state) 523 elif state: 524 slotstate.update(state) 525 for key, value in slotstate.items(): 526 setattr(object, key, value) 527 528 def construct_python_object(self, suffix, node): 529 # Format: 530 # !!python/object:module.name { ... state ... } 531 instance = self.make_python_instance(suffix, node, newobj=True) 532 state = self.construct_mapping(node) 533 self.set_python_instance_state(instance, state) 534 return instance 535 536 def construct_python_object_apply(self, suffix, node, newobj=False): 537 # Format: 538 # !!python/object/apply # (or !!python/object/new) 539 # args: [ ... arguments ... ] 540 # kwds: { ... keywords ... } 541 # state: ... state ... 542 # listitems: [ ... listitems ... ] 543 # dictitems: { ... dictitems ... } 544 # or short format: 545 # !!python/object/apply [ ... arguments ... ] 546 # The difference between !!python/object/apply and !!python/object/new 547 # is how an object is created, check make_python_instance for details. 548 if isinstance(node, SequenceNode): 549 args = self.construct_sequence(node) 550 kwds = {} 551 state = {} 552 listitems = [] 553 dictitems = {} 554 else: 555 value = self.construct_mapping(node) 556 args = value.get('args', []) 557 kwds = value.get('kwds', {}) 558 state = value.get('state', {}) 559 listitems = value.get('listitems', []) 560 dictitems = value.get('dictitems', {}) 561 instance = self.make_python_instance(suffix, node, args, kwds, newobj) 562 if state: 563 self.set_python_instance_state(instance, state) 564 if listitems: 565 instance.extend(listitems) 566 if dictitems: 567 for key in dictitems: 568 instance[key] = dictitems[key] 569 return instance 570 571 def construct_python_object_new(self, suffix, node): 572 return self.construct_python_object_apply(suffix, node, newobj=True) 573 574 495 575 Constructor.add_constructor( 496 576 u'tag:yaml.org,2002:python/none', … … 545 625 Constructor.construct_python_module) 546 626 627 Constructor.add_multi_constructor( 628 u'tag:yaml.org,2002:python/object:', 629 Constructor.construct_python_object) 630 631 Constructor.add_multi_constructor( 632 u'tag:yaml.org,2002:python/object/apply:', 633 Constructor.construct_python_object_apply) 634 635 Constructor.add_multi_constructor( 636 u'tag:yaml.org,2002:python/object/new:', 637 Constructor.construct_python_object_new) 638 -
pyyaml/trunk/lib/yaml/representer.py
r143 r147 17 17 from sets import Set as set 18 18 19 import sys 19 import sys, copy_reg 20 20 21 21 class RepresenterError(YAMLError): … … 25 25 26 26 yaml_representers = {} 27 yaml_multi_representers = {} 27 28 28 29 def __init__(self): … … 30 31 31 32 def represent(self, data): 32 node = self.represent_ object(data)33 node = self.represent_data(data) 33 34 self.serialize(node) 34 35 self.represented_objects = {} … … 50 51 return bases 51 52 52 def represent_ object(self, data):53 def represent_data(self, data): 53 54 if self.ignore_aliases(data): 54 55 alias_key = None … … 65 66 if type(data) is self.instance_type: 66 67 data_types = self.get_classobj_bases(data.__class__)+list(data_types) 67 for data_type in data_types:68 if data_type in self.yaml_representers:69 node = self.yaml_representers[data_type](self, data)70 break71 else:72 if None in self.yaml_representers:73 node = self.yaml_representers[None](self, data)68 if data_types[0] in self.yaml_representers: 69 node = self.yaml_representers[data_types[0]](self, data) 70 else: 71 for data_type in data_types: 72 if data_type in self.yaml_multi_representers: 73 node = self.yaml_multi_representers[data_type](self, data) 74 break 74 75 else: 75 node = ScalarNode(None, unicode(data)) 76 if None in self.yaml_multi_representers: 77 node = self.yaml_multi_representers[None](self, data) 78 elif None in self.yaml_representers: 79 node = self.yaml_representers[None](self, data) 80 else: 81 node = ScalarNode(None, unicode(data)) 76 82 if alias_key is not None: 77 83 self.represented_objects[alias_key] = node … … 84 90 add_representer = classmethod(add_representer) 85 91 92 def add_multi_representer(cls, data_type, representer): 93 if not 'yaml_multi_representers' in cls.__dict__: 94 cls.yaml_multi_representers = cls.yaml_multi_representers.copy() 95 cls.yaml_multi_representers[data_type] = representer 96 add_multi_representer = classmethod(add_multi_representer) 97 86 98 def represent_scalar(self, tag, value, style=None): 87 99 return ScalarNode(tag, value, style=style) 88 100 89 101 def represent_sequence(self, tag, sequence, flow_style=None): 102 best_style = True 90 103 value = [] 91 104 for item in sequence: 92 value.append(self.represent_object(item)) 105 node_item = self.represent_data(item) 106 if not (isinstance(node_item, ScalarNode) and not node_item.style): 107 best_style = False 108 value.append(self.represent_data(item)) 109 if flow_style is None: 110 flow_style = best_style 93 111 return SequenceNode(tag, value, flow_style=flow_style) 94 112 95 113 def represent_mapping(self, tag, mapping, flow_style=None): 114 best_style = True 96 115 if hasattr(mapping, 'keys'): 97 116 value = {} 98 117 for item_key in mapping.keys(): 99 118 item_value = mapping[item_key] 100 value[self.represent_object(item_key)] = \ 101 self.represent_object(item_value) 119 node_key = self.represent_data(item_key) 120 node_value = self.represent_data(item_value) 121 if not (isinstance(node_key, ScalarNode) and not node_key.style): 122 best_style = False 123 if not (isinstance(node_value, ScalarNode) and not node_value.style): 124 best_style = False 125 value[node_key] = node_value 102 126 else: 103 127 value = [] 104 128 for item_key, item_value in mapping: 105 value.append((self.represent_object(item_key), 106 self.represent_object(item_value))) 129 node_key = self.represent_data(item_key) 130 node_value = self.represent_data(item_value) 131 if not (isinstance(node_key, ScalarNode) and not node_key.style): 132 best_style = False 133 if not (isinstance(node_value, ScalarNode) and not node_value.style): 134 best_style = False 135 value.append((node_key, node_value)) 136 if flow_style is None: 137 flow_style = best_style 107 138 return MappingNode(tag, value, flow_style=flow_style) 108 139 … … 259 290 260 291 class Representer(SafeRepresenter): 261 292 262 293 def represent_str(self, data): 263 294 tag = None … … 313 344 u'tag:yaml.org,2002:python/module:'+data.__name__, u'') 314 345 346 def represent_instance(self, data): 347 # For instances of classic classes, we use __getinitargs__ and 348 # __getstate__ to serialize the data. 349 350 # If data.__getinitargs__ exists, the object must be reconstructed by 351 # calling cls(**args), where args is a tuple returned by 352 # __getinitargs__. Otherwise, the cls.__init__ method should never be 353 # called and the class instance is created by instantiating a trivial 354 # class and assigning to the instance's __class__ variable. 355 356 # If data.__getstate__ exists, it returns the state of the object. 357 # Otherwise, the state of the object is data.__dict__. 358 359 # We produce either a !!python/object or !!python/object/new node. 360 # If data.__getinitargs__ does not exist and state is a dictionary, we 361 # produce a !!python/object node . Otherwise we produce a 362 # !!python/object/new node. 363 364 cls = data.__class__ 365 class_name = u'%s.%s' % (cls.__module__, cls.__name__) 366 args = None 367 state = None 368 if hasattr(data, '__getinitargs__'): 369 args = list(data.__getinitargs__()) 370 if hasattr(data, '__getstate__'): 371 state = data.__getstate__() 372 else: 373 state = data.__dict__ 374 if args is None and isinstance(state, dict): 375 return self.represent_mapping( 376 u'tag:yaml.org,2002:python/object:'+class_name, state) 377 if isinstance(state, dict) and not state: 378 return self.represent_sequence( 379 u'tag:yaml.org,2002:python/object/new:'+class_name, args) 380 value = {} 381 if args: 382 value['args'] = args 383 value['state'] = state 384 return self.represent_mapping( 385 u'tag:yaml.org,2002:python/object/new:'+class_name, value) 386 387 def represent_object(self, data): 388 # We use __reduce__ API to save the data. data.__reduce__ returns 389 # a tuple of length 2-5: 390 # (function, args, state, listitems, dictitems) 391 392 # For reconstructing, we calls function(*args), then set its state, 393 # listitems, and dictitems if they are not None. 394 395 # A special case is when function.__name__ == '__newobj__'. In this 396 # case we create the object with args[0].__new__(*args). 397 398 # Another special case is when __reduce__ returns a string - we don't 399 # support it. 400 401 # We produce a !!python/object, !!python/object/new or 402 # !!python/object/apply node. 403 404 cls = type(data) 405 if cls in copy_reg.dispatch_table: 406 reduce = copy_reg.dispatch_table[cls] 407 elif hasattr(data, '__reduce_ex__'): 408 reduce = data.__reduce_ex__(2) 409 elif hasattr(data, '__reduce__'): 410 reduce = data.__reduce__() 411 else: 412 raise RepresenterError("cannot represent object: %r" % data) 413 reduce = (list(reduce)+[None]*5)[:5] 414 function, args, state, listitems, dictitems = reduce 415 args = list(args) 416 if state is None: 417 state = {} 418 if listitems is not None: 419 listitems = list(listitems) 420 if dictitems is not None: 421 dictitems = dict(dictitems) 422 if function.__name__ == '__newobj__': 423 function = args[0] 424 args = args[1:] 425 tag = u'tag:yaml.org,2002:python/object/new:' 426 newobj = True 427 else: 428 tag = u'tag:yaml.org,2002:python/object/apply:' 429 newobj = False 430 function_name = u'%s.%s' % (function.__module__, function.__name__) 431 if not args and not listitems and not dictitems \ 432 and isinstance(state, dict) and newobj: 433 return self.represent_mapping( 434 u'tag:yaml.org,2002:python/object:'+function_name, state) 435 if not listitems and not dictitems \ 436 and isinstance(state, dict) and not state: 437 return self.represent_sequence(tag+function_name, args) 438 value = {} 439 if args: 440 value['args'] = args 441 if state or not isinstance(state, dict): 442 value['state'] = state 443 if listitems: 444 value['listitems'] = listitems 445 if dictitems: 446 value['dictitems'] = dictitems 447 return self.represent_mapping(tag+function_name, value) 448 315 449 Representer.add_representer(str, 316 450 Representer.represent_str) … … 343 477 Representer.represent_module) 344 478 479 Representer.add_multi_representer(Representer.instance_type, 480 Representer.represent_instance) 481 482 Representer.add_multi_representer(object, 483 Representer.represent_object) 484
