Changes between Version 2 and Version 3 of PyYAML
- Timestamp:
- 04/10/06 21:22:36 (7 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
PyYAML
v2 v3 33 33 Note that PyYAML3000 is still young and may have some bugs. In particular, 34 34 there are two major drawbacks: 35 * There in no '''YAML emitter''' yet.35 * ~~There in no '''YAML emitter''' yet.~~ 36 36 * PyYAML3000 is written in Python and is slow comparing to C based parsers. 37 37 … … 61 61 Now convert it to a native Python object: 62 62 {{{ 63 >>> yaml.load _document(data)63 >>> yaml.load(data) 64 64 ['YAML', 'is', 'fun!'] 65 }}} 66 67 Conversely, you may convert a Python object into a YAML document: 68 {{{ 69 >>> print yaml.dump(['YAML', 'is', 'fun!']) 70 - YAML 71 - is 72 - fun! 65 73 }}} 66 74 … … 76 84 ... - pairs: !!pairs [1: 2, 3: 4, 5: 6] 77 85 ... """ 78 >>> for x in yaml.load _document(data): print x86 >>> for x in yaml.load(data): print x 79 87 None 80 88 True … … 84 92 {'primes (sort of)': set([2, 3, 5, 7, 11, 13])} 85 93 {'pairs': [(1, 2), (3, 4), (5, 6)]} 94 >>> print yaml.dump([None, True, False, 123, 123.456, 'a string', 95 ... {'a': 'dictionary'}, ['a', 'list']]) 96 - null 97 - true 98 - false 99 - 123 100 - 123.456 101 - a string 102 - a: dictionary 103 - - a 104 - list 86 105 }}} 87 106 … … 91 110 '''!!value'''. 92 111 93 === Defining custo ntags ===112 === Defining custom tags === 94 113 95 114 You may define constructors for your own application-specific tags. You may use … … 98 117 99 118 If you use '''yaml.YAMLObject''', you need to define the class attribute '''yaml_tag''' 100 and the class method '''from_yaml''': 101 {{{ 102 #!python 103 >>> class Person(yaml.YAMLObject): 104 ... yaml_tag = '!Person' 105 ... @classmethod 106 ... def from_yaml(cls, constructor, node): 107 ... # Convert the node to a dictionary 108 ... attributes = constructor.construct_mapping(node) 109 ... # Convert spaces into underlines. 110 ... for key in attributes: 111 ... if ' ' in key: 112 ... value = attributes[key] 113 ... del attributes[key] 114 ... key = key.replace(' ', '_') 115 ... attributes[key] = value 116 ... # Create an object 117 ... return cls(**attributes) 118 ... def __init__(self, first_name, last_name, email=None, birthday=None): 119 ... self.first_name = first_name 120 ... self.last_name = last_name 121 ... self.email = email 122 ... self.birthday = birthday 123 }}} 124 125 If you don't want to use metaclass magic, you may define the constructor 126 as a function and register it: 127 {{{ 128 #!python 129 >>> def construct_person(constructor, node): 130 ... # ... 131 >>> yaml.Constructor.add_constructor('!Person', construct_person) 132 }}} 133 134 After that, PyYAML 3000 will understand the '''!Person''' tag and convert it into the '''Person''' object: 135 {{{ 136 #!python 137 >>> data = """ 138 ... --- !Person 119 and the class methods '''from_yaml''', '''to_yaml''': 120 {{{ 121 #!python 122 class Person(yaml.YAMLObject): 123 yaml_tag = '!Person' 124 @classmethod 125 def from_yaml(cls, constructor, node): 126 # Convert the node to a dictionary 127 attributes = constructor.construct_mapping(node) 128 # Convert spaces into underlines 129 for key in attributes: 130 if ' ' in key: 131 value = attributes[key] 132 del attributes[key] 133 key = key.replace(' ', '_') 134 attributes[key] = value 135 # Create an object 136 return cls(**attributes) 137 @classmethod 138 def to_yaml(cls, representer, person): 139 # Create mapping node 140 mapping = {} 141 for attribute in person.__dict__: 142 key = attribute.replace('_', ' ') 143 value = getattr(person, attribute) 144 if value is not None: 145 mapping[key] = getattr(person, attribute) 146 return representer.represent_mapping(cls.yaml_tag, mapping) 147 def __init__(self, first_name=None, last_name=None, email=None, birthday=None): 148 self.first_name = first_name 149 self.last_name = last_name 150 self.email = email 151 self.birthday = birthday 152 }}} 153 154 After that, PyYAML 3000 will convert '''!Person'''-tagged nodes to '''Person''' objects and vice versa. 155 {{{ 156 #!python 157 >>> p = yaml.load(""" 158 ... !Person 139 159 ... first name: Kirill 140 160 ... last name: Simonov 141 161 ... email: xi(at)resolvent.net 142 ... """ 143 >>> p = yaml.load_document(data) 144 >>> p 145 <__main__.Person object at 0xb7de408c> 162 ... """) 163 >>> print p 164 <__main__.Person object at 0xb7b5e44c> 146 165 >>> p.first_name, p.last_name, p.email, p.birthday 147 166 ('Kirill', 'Simonov', 'xi(at)resolvent.net', None) 167 >>> print yaml.dump(p) 168 !Person 169 first name: Kirill 170 last name: Simonov 171 email: xi(at)resolvent.net 172 }}} 173 174 If you don't want to use metaclass magic, you may define the constructor 175 and representer as functions and register them: 176 {{{ 177 #!python 178 def construct_person(constructor, node): 179 # ... 180 def represent_person(representer, person): 181 # ... 182 yaml.Constructor.add_constructor('!Person', construct_person) 183 yaml.Representer.add_representer(Person, represent_person) 148 184 }}} 149 185 150 186 === Loading all documents === 151 187 152 If an input stream contains several documents, you may load all of them using the '''yaml.load ''' function.188 If an input stream contains several documents, you may load all of them using the '''yaml.load_all''' function. 153 189 {{{ 154 190 #!python … … 161 197 ... last: document 162 198 ... """ 163 >>> for document in yaml.load (data): print document199 >>> for document in yaml.load_all(data): print document 164 200 This is the first document 165 201 None … … 167 203 }}} 168 204 205 You may also dump several documents into the same stream using the '''yaml.dump_all''' function. 206 {{{ 207 #!python 208 >>> print yaml.dump_all(["The first document", None, ["The", "last", "document"]]) 209 The first document 210 --- null 211 --- 212 - The 213 - last 214 - document 215 }}} 216 169 217 There are more features, check the source to find out. 170 218 171 219 == Low-level API == 172 220 173 PyYAML 3000 provides low-level event-based and easy-to-use parser API.174 175 Example:221 PyYAML 3000 provides low-level event-based and easy-to-use parser and emitter API. 222 223 Parser example: 176 224 {{{ 177 225 #!python … … 192 240 >>> for event in yaml.parse(data): print event 193 241 242 StreamStartEvent() 243 244 DocumentStartEvent() 194 245 ScalarEvent(anchor=None, tag=u'!tag', value=u'scalar') 195 196 SequenceEvent(anchor=None, tag=u'!') 246 DocumentEndEvent() 247 248 DocumentStartEvent() 249 SequenceStartEvent(anchor=None, tag=None) 197 250 ScalarEvent(anchor=u'anchor', tag=None, value=u'item') 198 251 ScalarEvent(anchor=None, tag=None, value=u'another item') 199 252 AliasEvent(anchor=u'anchor') 200 CollectionEndEvent() 201 202 MappingEvent(anchor=None, tag=u'!') 253 SequenceEndEvent() 254 DocumentEndEvent() 255 256 DocumentStartEvent() 257 MappingStartEvent(anchor=None, tag=None) 203 258 ScalarEvent(anchor=None, tag=None, value=u'key') 204 259 ScalarEvent(anchor=None, tag=None, value=u'value') 205 Sequence Event(anchor=None, tag=u'!')260 SequenceStartEvent(anchor=None, tag=None) 206 261 ScalarEvent(anchor=None, tag=None, value=u'complex') 207 262 ScalarEvent(anchor=None, tag=None, value=u'key') 208 CollectionEndEvent()209 Sequence Event(anchor=None, tag=u'!')263 SequenceEndEvent() 264 SequenceStartEvent(anchor=None, tag=None) 210 265 ScalarEvent(anchor=None, tag=None, value=u'complex') 211 266 ScalarEvent(anchor=None, tag=None, value=u'value') 212 CollectionEndEvent() 213 CollectionEndEvent() 267 SequenceEndEvent() 268 MappingEndEvent() 269 DocumentEndEvent() 214 270 215 271 StreamEndEvent() 272 273 >>> events = [ 274 ... yaml.StreamStartEvent(encoding='utf-8'), 275 ... yaml.DocumentStartEvent(explicit=True), 276 ... yaml.MappingStartEvent(anchor=None, tag=None), 277 ... yaml.ScalarEvent(anchor=None, tag=None, value=u'flow sequence', implicit=True), 278 ... yaml.SequenceStartEvent(anchor=None, tag=None, flow_style=True), 279 ... yaml.ScalarEvent(anchor=None, tag=None, value=u'123', implicit=True), 280 ... yaml.ScalarEvent(anchor=None, tag=None, value=u'456', implicit=True), 281 ... yaml.SequenceEndEvent(), 282 ... yaml.ScalarEvent(anchor=None, tag=None, value=u'block scalar', implicit=True), 283 ... yaml.ScalarEvent(anchor=None, tag=None, value=u'YAML\nis\nfun!\n', style='|'), 284 ... yaml.MappingEndEvent(), 285 ... yaml.DocumentEndEvent(explicit=True), 286 ... yaml.StreamEndEvent(), 287 ... ] 288 289 >>> print yaml.emit(events) 290 --- 291 flow sequence: [123, 456] 292 block scalar: | 293 YAML 294 is 295 fun! 296 ... 216 297 }}} 217 298 218 299 == To Do == 219 300 220 For the initial release we need websiteand documentation.301 For the initial release we need ~~website~~ and documentation. 221 302 222 303 Long-term goals: 223 * fix tabs, i ndentation for flow collections, indentation for scalars (min=1?), 'y' is '''!!bool''',224 * emitter304 * fix tabs, i~~ndentation for flow collections, indentation for scalars (min=1?), 'y' is '''!!bool'''~~, 305 * ~~emitter~~ 225 306 * libyaml3000 226 307 … … 233 314 are considered as parts of the content. It can be fixed, but it's not 234 315 really important now. 235 * Empty plain scalars are not allowed if alias or tag is specified.This316 * ~~Empty plain scalars are not allowed if alias or tag is specified.~~ This 236 317 is done to prevent anomalities like '''[ !tag, value]''', which can be 237 318 interpreted both as '''[ !<!tag,> value ]''' and '''[ !<!tag> "", "value" ]'''.
