Changeset 222 for pyyaml/trunk/lib/yaml/constructor.py
- Timestamp:
- 08/03/06 12:07:29 (7 years ago)
- File:
-
- 1 edited
-
pyyaml/trunk/lib/yaml/constructor.py (modified) (16 diffs)
Legend:
- Unmodified
- Added
- Removed
-
pyyaml/trunk/lib/yaml/constructor.py
r198 r222 22 22 pass 23 23 24 class BaseConstructor :24 class BaseConstructor(object): 25 25 26 26 yaml_constructors = {} … … 30 30 self.constructed_objects = {} 31 31 self.recursive_objects = {} 32 self.state_generators = [] 33 self.deep_construct = False 32 34 33 35 def check_data(self): … … 40 42 return self.construct_document(self.get_node()) 41 43 44 def g(): yield None 45 generator_type = type(g()) 46 del g 47 42 48 def construct_document(self, node): 43 49 data = self.construct_object(node) 50 while self.state_generators: 51 state_generators = self.state_generators 52 self.state_generators = [] 53 for generator in state_generators: 54 for dummy in generator: 55 pass 44 56 self.constructed_objects = {} 45 57 self.recursive_objects = {} 58 self.deep_construct = False 46 59 return data 47 60 48 def construct_object(self, node): 61 def construct_object(self, node, deep=False): 62 if deep: 63 old_deep = self.deep_construct 64 self.deep_construct = True 49 65 if node in self.constructed_objects: 50 66 return self.constructed_objects[node] 51 67 if node in self.recursive_objects: 52 68 raise ConstructorError(None, None, 53 "found recursive node", node.start_mark)69 "found unconstructable recursive node", node.start_mark) 54 70 self.recursive_objects[node] = None 55 71 constructor = None 72 state_constructor = None 73 tag_suffix = None 56 74 if node.tag in self.yaml_constructors: 57 constructor = lambda node: self.yaml_constructors[node.tag](self, node)75 constructor = self.yaml_constructors[node.tag] 58 76 else: 59 77 for tag_prefix in self.yaml_multi_constructors: 60 78 if node.tag.startswith(tag_prefix): 61 79 tag_suffix = node.tag[len(tag_prefix):] 62 constructor = lambda node: \ 63 self.yaml_multi_constructors[tag_prefix](self, tag_suffix, node) 80 constructor = self.yaml_multi_constructors[tag_prefix] 64 81 break 65 82 else: 66 83 if None in self.yaml_multi_constructors: 67 constructor = lambda node: \68 self.yaml_multi_constructors[None](self, node.tag, node)84 tag_suffix = node.tag 85 constructor = self.yaml_multi_constructors[None] 69 86 elif None in self.yaml_constructors: 70 constructor = lambda node: \ 71 self.yaml_constructors[None](self, node) 87 constructor = self.yaml_constructors[None] 72 88 elif isinstance(node, ScalarNode): 73 constructor = self. construct_scalar89 constructor = self.__class__.construct_scalar 74 90 elif isinstance(node, SequenceNode): 75 constructor = self. construct_sequence91 constructor = self.__class__.construct_sequence 76 92 elif isinstance(node, MappingNode): 77 constructor = self.construct_mapping 78 else: 79 print node.tag 80 data = constructor(node) 93 constructor = self.__class__.construct_mapping 94 if tag_suffix is None: 95 data = constructor(self, node) 96 else: 97 data = constructor(self, tag_suffix, node) 98 if isinstance(data, self.generator_type): 99 generator = data 100 data = generator.next() 101 if self.deep_construct: 102 for dummy in generator: 103 pass 104 else: 105 self.state_generators.append(generator) 81 106 self.constructed_objects[node] = data 82 107 del self.recursive_objects[node] 108 if deep: 109 self.deep_construct = old_deep 83 110 return data 84 111 85 112 def construct_scalar(self, node): 86 113 if not isinstance(node, ScalarNode): 87 if isinstance(node, MappingNode):88 for key_node in node.value:89 if key_node.tag == u'tag:yaml.org,2002:value':90 return self.construct_scalar(node.value[key_node])91 114 raise ConstructorError(None, None, 92 115 "expected a scalar node, but found %s" % node.id, … … 94 117 return node.value 95 118 96 def construct_sequence(self, node ):119 def construct_sequence(self, node, deep=False): 97 120 if not isinstance(node, SequenceNode): 98 121 raise ConstructorError(None, None, 99 122 "expected a sequence node, but found %s" % node.id, 100 123 node.start_mark) 101 return [self.construct_object(child) for child in node.value] 102 103 def construct_mapping(self, node): 124 return [self.construct_object(child, deep=deep) 125 for child in node.value] 126 127 def construct_mapping(self, node, deep=False): 104 128 if not isinstance(node, MappingNode): 105 129 raise ConstructorError(None, None, … … 107 131 node.start_mark) 108 132 mapping = {} 109 merge = None 110 for key_node in node.value: 133 for key_node, value_node in node.value: 134 key = self.construct_object(key_node, deep=deep) 135 try: 136 hash(key) 137 except TypeError, exc: 138 raise ConstructorError("while constructing a mapping", node.start_mark, 139 "found unacceptable key (%s)" % exc, key_node.start_mark) 140 value = self.construct_object(value_node, deep=deep) 141 mapping[key] = value 142 return mapping 143 144 def construct_pairs(self, node, deep=False): 145 if not isinstance(node, MappingNode): 146 raise ConstructorError(None, None, 147 "expected a mapping node, but found %s" % node.id, 148 node.start_mark) 149 pairs = [] 150 for key_node, value_node in node.value: 151 key = self.construct_object(key_node, deep=deep) 152 value = self.construct_object(value_node, deep=deep) 153 pairs.append((key, value)) 154 return pairs 155 156 def add_constructor(cls, tag, constructor): 157 if not 'yaml_constructors' in cls.__dict__: 158 cls.yaml_constructors = cls.yaml_constructors.copy() 159 cls.yaml_constructors[tag] = constructor 160 add_constructor = classmethod(add_constructor) 161 162 def add_multi_constructor(cls, tag_prefix, multi_constructor): 163 if not 'yaml_multi_constructors' in cls.__dict__: 164 cls.yaml_multi_constructors = cls.yaml_multi_constructors.copy() 165 cls.yaml_multi_constructors[tag_prefix] = multi_constructor 166 add_multi_constructor = classmethod(add_multi_constructor) 167 168 class SafeConstructor(BaseConstructor): 169 170 def construct_scalar(self, node): 171 if isinstance(node, MappingNode): 172 for key_node, value_node in node.value: 173 if key_node.tag == u'tag:yaml.org,2002:value': 174 return self.construct_scalar(value_node) 175 return BaseConstructor.construct_scalar(self, node) 176 177 def flatten_mapping(self, node): 178 merge = [] 179 index = 0 180 while index < len(node.value): 181 key_node, value_node = node.value[index] 111 182 if key_node.tag == u'tag:yaml.org,2002:merge': 112 if merge is not None: 113 raise ConstructorError("while constructing a mapping", node.start_mark, 114 "found duplicate merge key", key_node.start_mark) 115 value_node = node.value[key_node] 183 del node.value[index] 116 184 if isinstance(value_node, MappingNode): 117 merge = [self.construct_mapping(value_node)] 185 self.flatten_mapping(value_node) 186 merge.extend(value_node.value) 118 187 elif isinstance(value_node, SequenceNode): 119 merge = []188 submerge = [] 120 189 for subnode in value_node.value: 121 190 if not isinstance(subnode, MappingNode): … … 124 193 "expected a mapping for merging, but found %s" 125 194 % subnode.id, subnode.start_mark) 126 merge.append(self.construct_mapping(subnode)) 127 merge.reverse() 195 self.flatten_mapping(subnode) 196 submerge.append(subnode.value) 197 submerge.reverse() 198 for value in submerge: 199 merge.extend(value) 128 200 else: 129 201 raise ConstructorError("while constructing a mapping", node.start_mark, … … 131 203 % value_node.id, value_node.start_mark) 132 204 elif key_node.tag == u'tag:yaml.org,2002:value': 133 if '=' in mapping: 134 raise ConstructorError("while construction a mapping", node.start_mark, 135 "found duplicate value key", key_node.start_mark) 136 value = self.construct_object(node.value[key_node]) 137 mapping['='] = value 205 key_node.tag = u'tag:yaml.org,2002:str' 206 index += 1 138 207 else: 139 key = self.construct_object(key_node) 140 try: 141 duplicate_key = key in mapping 142 except TypeError, exc: 143 raise ConstructorError("while constructing a mapping", node.start_mark, 144 "found unacceptable key (%s)" % exc, key_node.start_mark) 145 if duplicate_key: 146 raise ConstructorError("while constructing a mapping", node.start_mark, 147 "found duplicate key", key_node.start_mark) 148 value = self.construct_object(node.value[key_node]) 149 mapping[key] = value 150 if merge is not None: 151 merge.append(mapping) 152 mapping = {} 153 for submapping in merge: 154 mapping.update(submapping) 155 return mapping 156 157 def construct_pairs(self, node): 158 if not isinstance(node, MappingNode): 159 raise ConstructorError(None, None, 160 "expected a mapping node, but found %s" % node.id, 161 node.start_mark) 162 pairs = [] 163 for key_node in node.value: 164 key = self.construct_object(key_node) 165 value = self.construct_object(node.value[key_node]) 166 pairs.append((key, value)) 167 return pairs 168 169 def add_constructor(cls, tag, constructor): 170 if not 'yaml_constructors' in cls.__dict__: 171 cls.yaml_constructors = cls.yaml_constructors.copy() 172 cls.yaml_constructors[tag] = constructor 173 add_constructor = classmethod(add_constructor) 174 175 def add_multi_constructor(cls, tag_prefix, multi_constructor): 176 if not 'yaml_multi_constructors' in cls.__dict__: 177 cls.yaml_multi_constructors = cls.yaml_multi_constructors.copy() 178 cls.yaml_multi_constructors[tag_prefix] = multi_constructor 179 add_multi_constructor = classmethod(add_multi_constructor) 180 181 class SafeConstructor(BaseConstructor): 208 index += 1 209 if merge: 210 node.value = merge + node.value 211 212 def construct_mapping(self, node, deep=False): 213 if isinstance(node, MappingNode): 214 self.flatten_mapping(node) 215 return BaseConstructor.construct_mapping(self, node, deep=deep) 182 216 183 217 def construct_yaml_null(self, node): … … 297 331 # Note: we do not check for duplicate keys, because it's too 298 332 # CPU-expensive. 333 omap = [] 334 yield omap 299 335 if not isinstance(node, SequenceNode): 300 336 raise ConstructorError("while constructing an ordered map", node.start_mark, 301 337 "expected a sequence, but found %s" % node.id, node.start_mark) 302 omap = []303 338 for subnode in node.value: 304 339 if not isinstance(subnode, MappingNode): … … 310 345 "expected a single mapping item, but found %d items" % len(subnode.value), 311 346 subnode.start_mark) 312 key_node = subnode.value.keys()[0]347 key_node, value_node = subnode.value[0] 313 348 key = self.construct_object(key_node) 314 value = self.construct_object( subnode.value[key_node])349 value = self.construct_object(value_node) 315 350 omap.append((key, value)) 316 return omap317 351 318 352 def construct_yaml_pairs(self, node): 319 353 # Note: the same code as `construct_yaml_omap`. 354 pairs = [] 355 yield pairs 320 356 if not isinstance(node, SequenceNode): 321 357 raise ConstructorError("while constructing pairs", node.start_mark, 322 358 "expected a sequence, but found %s" % node.id, node.start_mark) 323 pairs = []324 359 for subnode in node.value: 325 360 if not isinstance(subnode, MappingNode): … … 331 366 "expected a single mapping item, but found %d items" % len(subnode.value), 332 367 subnode.start_mark) 333 key_node = subnode.value.keys()[0]368 key_node, value_node = subnode.value[0] 334 369 key = self.construct_object(key_node) 335 value = self.construct_object( subnode.value[key_node])370 value = self.construct_object(value_node) 336 371 pairs.append((key, value)) 337 return pairs338 372 339 373 def construct_yaml_set(self, node): 374 data = set() 375 yield data 340 376 value = self.construct_mapping(node) 341 return set(value)377 data.update(value) 342 378 343 379 def construct_yaml_str(self, node): … … 349 385 350 386 def construct_yaml_seq(self, node): 351 return self.construct_sequence(node) 387 data = [] 388 yield data 389 data.extend(self.construct_sequence(node)) 352 390 353 391 def construct_yaml_map(self, node): 354 return self.construct_mapping(node) 392 data = {} 393 yield data 394 value = self.construct_mapping(node) 395 data.update(value) 355 396 356 397 def construct_yaml_object(self, node, cls): 357 state = self.construct_mapping(node)358 398 data = cls.__new__(cls) 399 yield data 359 400 if hasattr(data, '__setstate__'): 401 state = self.construct_mapping(node, deep=True) 360 402 data.__setstate__(state) 361 403 else: 404 state = self.construct_mapping(node) 362 405 data.__dict__.update(state) 363 return data364 406 365 407 def construct_undefined(self, node): … … 435 477 436 478 def construct_python_tuple(self, node): 437 return tuple(self.construct_ yaml_seq(node))479 return tuple(self.construct_sequence(node)) 438 480 439 481 def find_python_module(self, name, mark): … … 526 568 # !!python/object:module.name { ... state ... } 527 569 instance = self.make_python_instance(suffix, node, newobj=True) 528 state = self.construct_mapping(node) 570 yield instance 571 deep = hasattr(instance, '__setstate__') 572 state = self.construct_mapping(node, deep=deep) 529 573 self.set_python_instance_state(instance, state) 530 return instance531 574 532 575 def construct_python_object_apply(self, suffix, node, newobj=False): … … 543 586 # is how an object is created, check make_python_instance for details. 544 587 if isinstance(node, SequenceNode): 545 args = self.construct_sequence(node )588 args = self.construct_sequence(node, deep=True) 546 589 kwds = {} 547 590 state = {} … … 549 592 dictitems = {} 550 593 else: 551 value = self.construct_mapping(node )594 value = self.construct_mapping(node, deep=True) 552 595 args = value.get('args', []) 553 596 kwds = value.get('kwds', {}) … … 568 611 return self.construct_python_object_apply(suffix, node, newobj=True) 569 612 570 571 613 Constructor.add_constructor( 572 614 u'tag:yaml.org,2002:python/none',
Note: See TracChangeset
for help on using the changeset viewer.
