| 75 | | PyYAML 3000 supports many of the types defined in the YAML tags repository: |
| 76 | | {{{ |
| 77 | | >>> data = """ |
| 78 | | ... - ~ |
| 79 | | ... - true |
| 80 | | ... - 3_141_592.653e-6 |
| 81 | | ... - 3000 |
| 82 | | ... - PyYAML3000 birthday: 2006-02-11 |
| 83 | | ... - primes (sort of): !!set { 2, 3, 5, 7, 11, 13 } |
| 84 | | ... - pairs: !!pairs [1: 2, 3: 4, 5: 6] |
| 85 | | ... """ |
| 86 | | >>> for x in yaml.load(data): print x |
| 87 | | None |
| 88 | | True |
| 89 | | 3.141592653 |
| 90 | | 3000 |
| 91 | | {'PyYAML3000 birthday': datetime.datetime(2006, 2, 11, 0, 0)} |
| 92 | | {'primes (sort of)': set([2, 3, 5, 7, 11, 13])} |
| 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 |
| 105 | | }}} |
| | 73 | You may check out the PyYAML source code from |
| | 74 | [http://svn.pyyaml.org/pyyaml PyYAML SVN repository]. |
| 153 | | If you don't want to use metaclass magic, you may define the constructor |
| 154 | | and representer as functions and register them: |
| 155 | | {{{ |
| 156 | | #!python |
| 157 | | def construct_person(constructor, node): |
| 158 | | # ... |
| 159 | | def represent_person(representer, person): |
| 160 | | # ... |
| 161 | | yaml.add_constructor('!Person', construct_person) |
| 162 | | yaml.add_representer(Person, represent_person) |
| 163 | | }}} |
| 164 | | |
| 165 | | === Parsing and emitting multiple documents in a stream === |
| 166 | | |
| 167 | | If an input stream contains several documents, you may load all of them using the '''yaml.load_all''' function. |
| 168 | | {{{ |
| 169 | | #!python |
| 170 | | >>> data = """ |
| 171 | | ... This is the first document |
| 172 | | ... --- # This is an empty document |
| 173 | | ... --- |
| 174 | | ... - this |
| 175 | | ... - is: the |
| 176 | | ... last: document |
| 177 | | ... """ |
| 178 | | >>> for document in yaml.load_all(data): print document |
| 179 | | This is the first document |
| 180 | | None |
| 181 | | ['this', {'is': 'the', 'last': 'document'}] |
| 182 | | }}} |
| 183 | | |
| 184 | | You may also dump several documents into the same stream using the '''yaml.dump_all''' function. |
| 185 | | {{{ |
| 186 | | #!python |
| 187 | | >>> print yaml.dump_all(["The first document", None, ["The", "last", "document"]]) |
| 188 | | The first document |
| 189 | | --- null |
| 190 | | --- |
| 191 | | - The |
| 192 | | - last |
| 193 | | - document |
| 194 | | }}} |
| 195 | | |
| 196 | | There are more features, check the source to find out. |
| 197 | | |
| 198 | | == Low-level API == |
| 199 | | |
| 200 | | PyYAML 3000 provides low-level event-based and easy-to-use parser and emitter API. |
| 201 | | |
| 202 | | Example: |
| 203 | | {{{ |
| 204 | | #!python |
| 205 | | >>> data = """ |
| 206 | | ... --- !tag |
| 207 | | ... scalar |
| 208 | | ... --- |
| 209 | | ... - &anchor item |
| 210 | | ... - another item |
| 211 | | ... - *anchor |
| 212 | | ... --- |
| 213 | | ... key: value |
| 214 | | ... ? - complex |
| 215 | | ... - key |
| 216 | | ... : - complex |
| 217 | | ... - value |
| 218 | | ... """ |
| 219 | | >>> for event in yaml.parse(data): print event |
| 220 | | StreamStartEvent() |
| 221 | | DocumentStartEvent() |
| 222 | | ScalarEvent(anchor=None, tag=u'!tag', implicit=(False, False), value=u'scalar') |
| 223 | | DocumentEndEvent() |
| 224 | | DocumentStartEvent() |
| 225 | | SequenceStartEvent(anchor=None, tag=None, implicit=True) |
| 226 | | ScalarEvent(anchor=u'anchor', tag=None, implicit=(True, False), value=u'item') |
| 227 | | ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'another item') |
| 228 | | AliasEvent(anchor=u'anchor') |
| 229 | | SequenceEndEvent() |
| 230 | | DocumentEndEvent() |
| 231 | | DocumentStartEvent() |
| 232 | | MappingStartEvent(anchor=None, tag=None, implicit=True) |
| 233 | | ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'key') |
| 234 | | ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'value') |
| 235 | | SequenceStartEvent(anchor=None, tag=None, implicit=True) |
| 236 | | ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'complex') |
| 237 | | ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'key') |
| 238 | | SequenceEndEvent() |
| 239 | | SequenceStartEvent(anchor=None, tag=None, implicit=True) |
| 240 | | ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'complex') |
| 241 | | ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'value') |
| 242 | | SequenceEndEvent() |
| 243 | | MappingEndEvent() |
| 244 | | DocumentEndEvent() |
| 245 | | StreamEndEvent() |
| 246 | | >>> events = [ |
| 247 | | ... yaml.StreamStartEvent(encoding='utf-8'), |
| 248 | | ... yaml.DocumentStartEvent(explicit=True), |
| 249 | | ... yaml.MappingStartEvent(anchor=None, tag=None, implicit=True), |
| 250 | | ... yaml.ScalarEvent(anchor=None, tag=None, value=u'flow sequence', implicit=(True, True)), |
| 251 | | ... yaml.SequenceStartEvent(anchor=None, tag=None, flow_style=True, implicit=True), |
| 252 | | ... yaml.ScalarEvent(anchor=None, tag=None, value=u'123', implicit=(True, False)), |
| 253 | | ... yaml.ScalarEvent(anchor=None, tag=None, value=u'456', implicit=(True, False)), |
| 254 | | ... yaml.SequenceEndEvent(), |
| 255 | | ... yaml.ScalarEvent(anchor=None, tag=None, value=u'block scalar', implicit=(True, True)), |
| 256 | | ... yaml.ScalarEvent(anchor=None, tag=None, value=u'YAML\nis\nfun!\n', style='|', implicit=(True, True)), |
| 257 | | ... yaml.MappingEndEvent(), |
| 258 | | ... yaml.DocumentEndEvent(explicit=True), |
| 259 | | ... yaml.StreamEndEvent(), |
| 260 | | ... ] |
| 261 | | |
| 262 | | >>> print yaml.emit(events) |
| 263 | | --- |
| 264 | | flow sequence: [123, 456] |
| 265 | | block scalar: | |
| 266 | | YAML |
| 267 | | is |
| 268 | | fun! |
| 269 | | ... |
| 270 | | }}} |
| 271 | | |
| 272 | | == To Do == |
| 273 | | |
| 274 | | For the initial release we need ~~website~~ and documentation. |
| 275 | | |
| 276 | | Long-term goals: |
| 277 | | * fix tabs, i~~ndentation for flow collections, indentation for scalars (min=1?), 'y' is '''!!bool'''~~, |
| 278 | | * ~~emitter~~ |
| 279 | | * libyaml3000 |
| 280 | | |
| 281 | | == Deviations from the specification == |
| 282 | | |
| 283 | | * rules for tabs in YAML are confusing. We are close, but not there yet. |
| 284 | | Perhaps both the spec and the parser should be fixed. Anyway, the best |
| 285 | | rule for tabs in YAML is to not use them at all. |
| 286 | | * Byte order mark. The initial BOM is stripped, but BOMs inside the stream |
| 287 | | are considered as parts of the content. It can be fixed, but it's not |
| 288 | | really important now. |
| 289 | | * ~~Empty plain scalars are not allowed if alias or tag is specified.~~ This |
| 290 | | is done to prevent anomalities like '''[ !tag, value]''', which can be |
| 291 | | interpreted both as '''[ !<!tag,> value ]''' and '''[ !<!tag> "", "value" ]'''. |
| 292 | | The spec should be fixed. |
| 293 | | * Indentation of flow collections. The spec requires them to be indented |
| 294 | | more then their block parent node. Unfortunately this rule many intuitively |
| 295 | | correct constructs invalid, for instance, |
| 296 | | {{{ |
| 297 | | block: { |
| 298 | | } # this is indentation violation according to the spec. |
| 299 | | }}} |
| 300 | | * ':' is not allowed for plain scalars in the flow mode. '''{1:2}''' is |
| 301 | | interpreted as '''{ 1 : 2 }'''. |
| 302 | | |
| 303 | | == Notes == |
| 304 | | |
| 305 | | * SpecBugs |
| | 89 | PyYAML is released under the MIT license. |