| 1 | |
|---|
| 2 | ============================================================ |
|---|
| 3 | PySyck: Python bindings for the Syck YAML parser and emitter |
|---|
| 4 | ============================================================ |
|---|
| 5 | |
|---|
| 6 | :Author: Kirill Simonov |
|---|
| 7 | :Contact: xi@resolvent.net |
|---|
| 8 | :Web site: http://xitology.org/pysyck/ |
|---|
| 9 | |
|---|
| 10 | .. contents:: |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | Overview |
|---|
| 14 | ======== |
|---|
| 15 | |
|---|
| 16 | YAML_ is a data serialization format designed for human readability and |
|---|
| 17 | interaction with scripting languages. |
|---|
| 18 | |
|---|
| 19 | Syck_ is an extension for reading and writing YAML in scripting languages. Syck |
|---|
| 20 | provides bindings to the Python_ programming language, but they are somewhat |
|---|
| 21 | limited and leak memory. |
|---|
| 22 | |
|---|
| 23 | PySyck_ is aimed to update the current Python bindings for Syck. The new |
|---|
| 24 | bindings will provide wrappers for the Syck emitter and give access to the bare |
|---|
| 25 | Parser tree. Hopefully it will not leak memory as well. |
|---|
| 26 | |
|---|
| 27 | PySyck_ may be used for various tasks, in particular, as a replacement of the |
|---|
| 28 | module pickle_. Please be aware that PySyck_ is a beta-quality software and |
|---|
| 29 | is not ready yet for production use. |
|---|
| 30 | |
|---|
| 31 | .. _YAML: http://yaml.org/ |
|---|
| 32 | .. _Syck: http://whytheluckystiff.net/syck/ |
|---|
| 33 | .. _Python: http://python.org/ |
|---|
| 34 | .. _PySyck: http://xitology.org/pysyck/ |
|---|
| 35 | .. _pickle: http://docs.python.org/lib/module-pickle.html |
|---|
| 36 | |
|---|
| 37 | Requirements |
|---|
| 38 | ============ |
|---|
| 39 | |
|---|
| 40 | PySyck requires Syck 0.55 or higher and Python 2.3 or higher. Python 2.2 is |
|---|
| 41 | supported to some extent. |
|---|
| 42 | |
|---|
| 43 | |
|---|
| 44 | Installation |
|---|
| 45 | ============ |
|---|
| 46 | |
|---|
| 47 | PySyck requires Syck version 0.55 or higher. If you install it from source, unpack |
|---|
| 48 | the source tarball and type:: |
|---|
| 49 | |
|---|
| 50 | $ python setup.py install |
|---|
| 51 | |
|---|
| 52 | Windows binaries for Python 2.2, 2.3, and 2.4 are provided. |
|---|
| 53 | |
|---|
| 54 | |
|---|
| 55 | Usage |
|---|
| 56 | ===== |
|---|
| 57 | |
|---|
| 58 | The documentation is still incomplete. See `the source code`_ for more details. |
|---|
| 59 | |
|---|
| 60 | .. _the source code: http://trac.xitology.org/pysyck/browser/ |
|---|
| 61 | |
|---|
| 62 | Quick Example |
|---|
| 63 | ------------- |
|---|
| 64 | |
|---|
| 65 | :: |
|---|
| 66 | |
|---|
| 67 | >>> from syck import * |
|---|
| 68 | >>> print load(""" |
|---|
| 69 | ... - foo |
|---|
| 70 | ... - bar |
|---|
| 71 | ... - baz |
|---|
| 72 | ... """) |
|---|
| 73 | ['foo', 'bar', 'baz'] |
|---|
| 74 | >>> print dump(['foo', 'bar', 'baz']) |
|---|
| 75 | --- |
|---|
| 76 | - foo |
|---|
| 77 | - bar |
|---|
| 78 | - baz |
|---|
| 79 | |
|---|
| 80 | YAML syntax |
|---|
| 81 | ----------- |
|---|
| 82 | |
|---|
| 83 | We do not describe the YAML syntax here. Please check http://yaml.org/ for the |
|---|
| 84 | reference. |
|---|
| 85 | |
|---|
| 86 | In addition to the tags defined in `the YAML types repository`_, PySyck understands |
|---|
| 87 | the following Python-specific tags: |
|---|
| 88 | |
|---|
| 89 | * ``tag:python.yaml.org,2002:none``, |
|---|
| 90 | * ``tag:python.yaml.org,2002:bool``, |
|---|
| 91 | * ``tag:python.yaml.org,2002:int``, |
|---|
| 92 | * ``tag:python.yaml.org,2002:float``, |
|---|
| 93 | * ``tag:python.yaml.org,2002:str``, |
|---|
| 94 | * ``tag:python.yaml.org,2002:unicode``, |
|---|
| 95 | * ``tag:python.yaml.org,2002:list``, |
|---|
| 96 | * ``tag:python.yaml.org,2002:tuple``, |
|---|
| 97 | * ``tag:python.yaml.org,2002:dict``, |
|---|
| 98 | * ``tag:python.yaml.org,2002:name:...``, |
|---|
| 99 | * ``tag:python.yaml.org,2002:object:...``, |
|---|
| 100 | * ``tag:python.yaml.org,2002:new:...``, |
|---|
| 101 | * ``tag:python.yaml.org,2002:apply:...``. |
|---|
| 102 | |
|---|
| 103 | Most of these tags are self-explanatory. The tags ``!python/name:...``, |
|---|
| 104 | ``!python/object:...``, ``!python/new:...``, and ``!python/apply:...`` are used |
|---|
| 105 | for constructing Python functions, classes, and objects. See the sections `Use |
|---|
| 106 | Python-specific tags in a YAML document`_ and `Use Python-specific tags to |
|---|
| 107 | construct Python objects`_ for some examples. |
|---|
| 108 | |
|---|
| 109 | .. _the YAML types repository: http://yaml.org/type/index.html |
|---|
| 110 | |
|---|
| 111 | Common Tasks |
|---|
| 112 | ------------ |
|---|
| 113 | |
|---|
| 114 | Import the module |
|---|
| 115 | ~~~~~~~~~~~~~~~~~ |
|---|
| 116 | |
|---|
| 117 | :: |
|---|
| 118 | |
|---|
| 119 | >>> from syck import * |
|---|
| 120 | |
|---|
| 121 | or |
|---|
| 122 | |
|---|
| 123 | :: |
|---|
| 124 | |
|---|
| 125 | >>> import syck |
|---|
| 126 | |
|---|
| 127 | Load a document from a string |
|---|
| 128 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 129 | |
|---|
| 130 | :: |
|---|
| 131 | |
|---|
| 132 | >>> source = "..." |
|---|
| 133 | >>> object = load(source) |
|---|
| 134 | |
|---|
| 135 | Load a document from a file |
|---|
| 136 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 137 | |
|---|
| 138 | :: |
|---|
| 139 | |
|---|
| 140 | >>> source = file(..., 'r') |
|---|
| 141 | >>> object = load(source) |
|---|
| 142 | |
|---|
| 143 | Convert a Python object to a YAML document |
|---|
| 144 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 145 | |
|---|
| 146 | :: |
|---|
| 147 | |
|---|
| 148 | >>> object = ... |
|---|
| 149 | >>> document = dump(object) |
|---|
| 150 | |
|---|
| 151 | Dump a Python object to a YAML stream |
|---|
| 152 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 153 | |
|---|
| 154 | :: |
|---|
| 155 | |
|---|
| 156 | >>> object = ... |
|---|
| 157 | >>> output = file(..., 'w') |
|---|
| 158 | >>> dump(object, output) |
|---|
| 159 | |
|---|
| 160 | Format the output YAML stream |
|---|
| 161 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 162 | |
|---|
| 163 | :: |
|---|
| 164 | |
|---|
| 165 | >>> object = ... |
|---|
| 166 | >>> output = file(..., 'w') |
|---|
| 167 | >>> dump(object, output, |
|---|
| 168 | ... headless=False, use_header=False, use_version=False, |
|---|
| 169 | ... explicit_typing=True, style=None, best_width=80, indent=2) |
|---|
| 170 | |
|---|
| 171 | Load several documents from a YAML stream |
|---|
| 172 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 173 | |
|---|
| 174 | :: |
|---|
| 175 | |
|---|
| 176 | >>> source = ... |
|---|
| 177 | >>> objects = load_documents(source) |
|---|
| 178 | >>> for object in objects: |
|---|
| 179 | ... # ... |
|---|
| 180 | |
|---|
| 181 | Create several documents in a YAML stream |
|---|
| 182 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 183 | |
|---|
| 184 | :: |
|---|
| 185 | |
|---|
| 186 | >>> objects = [...] |
|---|
| 187 | >>> output = file(..., 'w') |
|---|
| 188 | >>> dump_documents(objects, output) |
|---|
| 189 | |
|---|
| 190 | Get a representation tree of a YAML document |
|---|
| 191 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 192 | |
|---|
| 193 | :: |
|---|
| 194 | |
|---|
| 195 | >>> source = ... |
|---|
| 196 | >>> root_node = parse(source) |
|---|
| 197 | |
|---|
| 198 | Convert a representation tree to a YAML document |
|---|
| 199 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 200 | |
|---|
| 201 | :: |
|---|
| 202 | |
|---|
| 203 | >>> scalar_node = Scalar('...', tag='tag:...', |
|---|
| 204 | ... style='...', indent=.., width=..) |
|---|
| 205 | >>> sequence_node = Seq(list_of_nodes, tag='tag:...', inline=..) |
|---|
| 206 | >>> mapping_node = Map(dictionary_of_nodes, tag='tag:...', inline=..) |
|---|
| 207 | >>> root_node = ... |
|---|
| 208 | >>> output = file(..., 'w') |
|---|
| 209 | >>> emit(root_node, output) |
|---|
| 210 | |
|---|
| 211 | Use PySyck as a pickle replacement |
|---|
| 212 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 213 | |
|---|
| 214 | :: |
|---|
| 215 | |
|---|
| 216 | >>> object = ... |
|---|
| 217 | >>> stream = ... |
|---|
| 218 | >>> dump(object, stream) |
|---|
| 219 | |
|---|
| 220 | >>> stream = ... |
|---|
| 221 | >>> object = load(stream) |
|---|
| 222 | |
|---|
| 223 | Use PySyck to display the structure of a complex object |
|---|
| 224 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 225 | |
|---|
| 226 | :: |
|---|
| 227 | |
|---|
| 228 | >>> object = ... |
|---|
| 229 | >>> print dump(object) |
|---|
| 230 | |
|---|
| 231 | Use PySyck to display a YAML representation graph |
|---|
| 232 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 233 | |
|---|
| 234 | :: |
|---|
| 235 | |
|---|
| 236 | >>> source = ... |
|---|
| 237 | >>> node = parse(source) |
|---|
| 238 | >>> print dump(node) |
|---|
| 239 | |
|---|
| 240 | Use Python-specific tags in a YAML document |
|---|
| 241 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 242 | |
|---|
| 243 | :: |
|---|
| 244 | |
|---|
| 245 | --- %YAML:1.0 |
|---|
| 246 | - !python/none '' # You may also use '!null'. |
|---|
| 247 | - !python/bool 'False' # You may also use '!bool'. |
|---|
| 248 | - !python/int '123' # You may also use '!int'. |
|---|
| 249 | - !python/long '1234567890' |
|---|
| 250 | - !python/float '123.456789' # Also '!float'. |
|---|
| 251 | - !python/str 'a string' # Also '!str'. |
|---|
| 252 | - !python/unicode 'a unicode string encoded in utf-8' |
|---|
| 253 | - !python/list [1, 2, 3] # The same as '!seq' or no tag. |
|---|
| 254 | - !python/tuple [1, 2, 3] |
|---|
| 255 | - !python/dict { 1: foo, 2: bar } # The same as '!map' or no tag. |
|---|
| 256 | |
|---|
| 257 | Use Python-specific tags to construct functions or classes |
|---|
| 258 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 259 | |
|---|
| 260 | :: |
|---|
| 261 | |
|---|
| 262 | --- %YAML:1.0 |
|---|
| 263 | - !python/name:package.module.function_name '' |
|---|
| 264 | - !python/name:package.module.class_name '' |
|---|
| 265 | |
|---|
| 266 | Use Python-specific tags to construct Python objects |
|---|
| 267 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 268 | |
|---|
| 269 | :: |
|---|
| 270 | |
|---|
| 271 | --- %YAML:1.0 |
|---|
| 272 | - !python/object:package.module.type |
|---|
| 273 | attribute1: value1 |
|---|
| 274 | attribute2: value2 |
|---|
| 275 | # ... |
|---|
| 276 | - !python/new:package.module.type |
|---|
| 277 | - parameter1 |
|---|
| 278 | - parameter2 |
|---|
| 279 | # ... |
|---|
| 280 | - !python/new:package.module.type |
|---|
| 281 | args: [parameter1, parameter2, ...] |
|---|
| 282 | kwds: {kwd1: val1, kwd2: val2, ...} |
|---|
| 283 | state: {attr1: val1, attr2: val2, ...} |
|---|
| 284 | # ... |
|---|
| 285 | - !python/apply:package.module.function |
|---|
| 286 | - parameter1 |
|---|
| 287 | - parameter2 |
|---|
| 288 | # ... |
|---|
| 289 | - !python/apply:package.module.function |
|---|
| 290 | args: [parameter1, parameter2, ...] |
|---|
| 291 | kwds: {kwd1: val1, kwd2: val2, ...} |
|---|
| 292 | state: {attr1: val1, attr2: val2, ...} |
|---|
| 293 | # ... |
|---|
| 294 | |
|---|
| 295 | Use application specific tags |
|---|
| 296 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 297 | |
|---|
| 298 | :: |
|---|
| 299 | |
|---|
| 300 | >>> class MyClass: |
|---|
| 301 | ... # ... |
|---|
| 302 | |
|---|
| 303 | >>> class MyLoader(Loader): |
|---|
| 304 | ... def construct_private_my_tag(self, node): |
|---|
| 305 | ... # ... |
|---|
| 306 | ... return MyClass(...) |
|---|
| 307 | |
|---|
| 308 | >>> class MyDumper(Dumper): |
|---|
| 309 | ... def represent_MyDumper(self, object): |
|---|
| 310 | ... # ... |
|---|
| 311 | ... return Map(...) |
|---|
| 312 | |
|---|
| 313 | >>> source = """--- !!my_tag { ... }""" |
|---|
| 314 | >>> my_instance = load(source, Loader=MyLoader) |
|---|
| 315 | |
|---|
| 316 | >>> my_instance = MyClass(...) |
|---|
| 317 | >>> output = dump(my_instance, Dumper=MyDumper) |
|---|
| 318 | |
|---|
| 319 | Reference |
|---|
| 320 | --------- |
|---|
| 321 | |
|---|
| 322 | Functions |
|---|
| 323 | ~~~~~~~~~ |
|---|
| 324 | |
|---|
| 325 | ``load`` : function |
|---|
| 326 | ``load(source, Loader=Loader, **parameters)`` |
|---|
| 327 | |
|---|
| 328 | The function ``load()`` returns a Python object corresponding to the first |
|---|
| 329 | document in the source. If the source is empty, ``load()`` returns ``None``. |
|---|
| 330 | ``source`` must be a string or a file-like object that has the method |
|---|
| 331 | ``read(max_length)``. |
|---|
| 332 | |
|---|
| 333 | By default, the function ``load()`` uses an instance of the class ``Loader`` |
|---|
| 334 | for parsing. You may use another class or pass additional parameters to the |
|---|
| 335 | class constructor. See the section Parser_ for more details. |
|---|
| 336 | |
|---|
| 337 | Example:: |
|---|
| 338 | |
|---|
| 339 | >>> load(""" |
|---|
| 340 | ... - foo |
|---|
| 341 | ... - bar |
|---|
| 342 | ... - baz |
|---|
| 343 | ... """) |
|---|
| 344 | ['foo', 'bar', 'baz'] |
|---|
| 345 | |
|---|
| 346 | ``parse`` : function |
|---|
| 347 | ``parse(source, Loader=Loader, **parameters)`` |
|---|
| 348 | |
|---|
| 349 | The function ``parse()`` parses the source and returns a representation tree |
|---|
| 350 | of the first document. ``source`` must be a string or a file-like object |
|---|
| 351 | that has the method ``read(max_length)``. |
|---|
| 352 | |
|---|
| 353 | By default, the function ``parse()`` uses an instance of the class ``Loader`` |
|---|
| 354 | for parsing. You may use another class or pass additional parameters to the |
|---|
| 355 | class constructor. See the section Parser_ for more details. |
|---|
| 356 | |
|---|
| 357 | Example:: |
|---|
| 358 | |
|---|
| 359 | >>> parse(""" |
|---|
| 360 | ... - foo |
|---|
| 361 | ... - bar |
|---|
| 362 | ... - baz |
|---|
| 363 | ... """) |
|---|
| 364 | <_syck.Seq object at 0xb7a3f2fc> |
|---|
| 365 | |
|---|
| 366 | ``load_documents`` : function |
|---|
| 367 | ``load_documents(source, Loader=Loader, **parameters)`` |
|---|
| 368 | |
|---|
| 369 | The function ``load_documents()`` parses the source and an iterator. The |
|---|
| 370 | iterator produces Python objects corresponding the documents of the source |
|---|
| 371 | stream. ``source`` must be a string or a file-like object that has the method |
|---|
| 372 | ``read(max_length)``. |
|---|
| 373 | |
|---|
| 374 | By default, the function ``load_documents()`` uses an instance of the class |
|---|
| 375 | ``Loader`` for parsing. You may use another class or pass additional |
|---|
| 376 | parameters to the class constructor. See the section Parser_ for more |
|---|
| 377 | details. |
|---|
| 378 | |
|---|
| 379 | Example:: |
|---|
| 380 | |
|---|
| 381 | >>> source = """ |
|---|
| 382 | ... --- > |
|---|
| 383 | ... This is the |
|---|
| 384 | ... first document. |
|---|
| 385 | ... --- > |
|---|
| 386 | ... This is the |
|---|
| 387 | ... next document. |
|---|
| 388 | ... --- > |
|---|
| 389 | ... This is the |
|---|
| 390 | ... last document. |
|---|
| 391 | ... """ |
|---|
| 392 | >>> for object in load_documents(source): print object |
|---|
| 393 | ... |
|---|
| 394 | This is the first document. |
|---|
| 395 | |
|---|
| 396 | This is the next document. |
|---|
| 397 | |
|---|
| 398 | This is the last document. |
|---|
| 399 | |
|---|
| 400 | ``parse_documents`` : function |
|---|
| 401 | ``parse_documents(source, Loader=Loader, **parameters)`` |
|---|
| 402 | |
|---|
| 403 | The function ``parse_documents()`` is similar to ``load_documents()``, but |
|---|
| 404 | produces representation graphs for all documents in the source. |
|---|
| 405 | |
|---|
| 406 | ``dump`` : function |
|---|
| 407 | ``dump(object, output=None, Dumper=Dumper, **parameters)`` |
|---|
| 408 | |
|---|
| 409 | The function ``dump()`` converts ``object`` to a representation graph |
|---|
| 410 | and write it to ``output``. ``output`` must be ``None`` or a file-like |
|---|
| 411 | object that has the method ``write(data)``. If ``output`` is ``None``, |
|---|
| 412 | ``dump()`` returns the generated document. |
|---|
| 413 | |
|---|
| 414 | By default, the function ``dump()`` uses an instance of the class ``Dumper`` |
|---|
| 415 | for emitting. You may use another class or pass additional parameters to the |
|---|
| 416 | class constructor. See the section Emitter_ for more details. |
|---|
| 417 | |
|---|
| 418 | Example:: |
|---|
| 419 | |
|---|
| 420 | >>> object = ['foo', 'bar', ['baz']] |
|---|
| 421 | >>> dump(object, sys.stdout) |
|---|
| 422 | --- |
|---|
| 423 | - foo |
|---|
| 424 | - bar |
|---|
| 425 | - - baz |
|---|
| 426 | >>> print dump(object) |
|---|
| 427 | --- |
|---|
| 428 | - foo |
|---|
| 429 | - bar |
|---|
| 430 | - - baz |
|---|
| 431 | |
|---|
| 432 | >>> print dump(object, use_version=True, indent=5) |
|---|
| 433 | --- %YAML:1.0 |
|---|
| 434 | - foo |
|---|
| 435 | - bar |
|---|
| 436 | - - baz |
|---|
| 437 | |
|---|
| 438 | ``emit`` : function |
|---|
| 439 | ``emit(node, output=None, Dumper=Dumper, **parameters)`` |
|---|
| 440 | |
|---|
| 441 | The function ``emit()`` write the representation graph to the output stream. |
|---|
| 442 | ``output`` must be ``None`` or a file-like object that has the method |
|---|
| 443 | ``write(data)``. If ``output`` is ``None``, ``emit()`` returns the generated |
|---|
| 444 | document. |
|---|
| 445 | |
|---|
| 446 | By default, the function ``emit()`` uses an instance of the class ``Dumper`` |
|---|
| 447 | for emitting. You may use another class or pass additional parameters to the |
|---|
| 448 | class constructor. See the section Emitter_ for more details. |
|---|
| 449 | |
|---|
| 450 | Example:: |
|---|
| 451 | |
|---|
| 452 | >>> foo = Scalar('a string') |
|---|
| 453 | >>> bar = Scalar('a unicode string', tag="tag:python.yaml.org,2002:unicode") |
|---|
| 454 | >>> baz = Scalar('12345', tag="tag:yaml.org,2002:int") |
|---|
| 455 | >>> seq = Seq([foo, bar, baz], tag="tag:python.taml.org,2002:tuple") |
|---|
| 456 | >>> print emit(seq, use_version=True) |
|---|
| 457 | --- %YAML:1.0 !python.taml.org,2002/tuple |
|---|
| 458 | - a string |
|---|
| 459 | - !python/unicode a unicode string |
|---|
| 460 | - 12345 |
|---|
| 461 | |
|---|
| 462 | ``dump_documents`` : function |
|---|
| 463 | ``dump_documents(objects, output=None, Dumper=Dumper, **parameters)`` |
|---|
| 464 | |
|---|
| 465 | The function ``dump_documents()`` takes a list of objects and converts |
|---|
| 466 | each object to a YAML document. If ``output`` is ``None``, it returns |
|---|
| 467 | the produced documents. Otherwise it writes down them to ``output``, |
|---|
| 468 | which must be a file-like object with the method ``write(data)``. |
|---|
| 469 | |
|---|
| 470 | By default, the function ``dump_documents()`` uses an instance of the class |
|---|
| 471 | ``Dumper`` for emitting. You may use another class or pass additional |
|---|
| 472 | parameters to the class constructor. See the section Emitter_ for more |
|---|
| 473 | details. |
|---|
| 474 | |
|---|
| 475 | Example:: |
|---|
| 476 | |
|---|
| 477 | >>> print dump_documents(['foo', 'bar', 'baz']) |
|---|
| 478 | --- foo |
|---|
| 479 | --- bar |
|---|
| 480 | --- baz |
|---|
| 481 | |
|---|
| 482 | ``emit_documents`` : function |
|---|
| 483 | ``emit_documents(nodes, output=None, Dumper=Dumper, **parameters)`` |
|---|
| 484 | |
|---|
| 485 | The function ``emit_documents()`` is similar to ``dump_documents()``, but |
|---|
| 486 | it requires a list of representation graphs. |
|---|
| 487 | |
|---|
| 488 | Exceptions |
|---|
| 489 | ~~~~~~~~~~ |
|---|
| 490 | |
|---|
| 491 | ``error`` : exception |
|---|
| 492 | This exception is raised by the Syck parser when it detects a syntax error. |
|---|
| 493 | |
|---|
| 494 | The attribute ``args`` of the exception is a triple: *message*, *row*, |
|---|
| 495 | *column*. |
|---|
| 496 | |
|---|
| 497 | Example:: |
|---|
| 498 | |
|---|
| 499 | >>> load("""--- |
|---|
| 500 | ... - foo |
|---|
| 501 | ... - ''' |
|---|
| 502 | ... - bar |
|---|
| 503 | ... """) |
|---|
| 504 | Traceback (most recent call last): |
|---|
| 505 | File "<stdin>", line 1, in ? |
|---|
| 506 | File "build/lib.linux-i686-2.3/syck/loaders.py", line 384, in load |
|---|
| 507 | File "build/lib.linux-i686-2.3/syck/loaders.py", line 42, in load |
|---|
| 508 | _syck.error: ('syntax error', 4, 2) |
|---|
| 509 | |
|---|
| 510 | Nodes |
|---|
| 511 | ~~~~~ |
|---|
| 512 | |
|---|
| 513 | The following four classes represents nodes in the YAML representation graph: |
|---|
| 514 | |
|---|
| 515 | ``Node`` : class |
|---|
| 516 | ``Node`` is an abstract class; you cannot create an instance of the class |
|---|
| 517 | ``Node``. ``Node`` is the base class of ``Scalar``, ``Seq``, and ``Map``. |
|---|
| 518 | |
|---|
| 519 | ``Scalar`` : subclass of ``Node`` |
|---|
| 520 | ``Scalar`` represents a scalar node. Its value is a string. |
|---|
| 521 | |
|---|
| 522 | ``Seq`` : subclass of ``Node`` |
|---|
| 523 | ``Seq`` represents a sequence node. Its value is a list of nodes. |
|---|
| 524 | |
|---|
| 525 | ``Map`` : subclass of ``Node`` |
|---|
| 526 | ``Map`` represents a mapping node. Its value is a list of pairs or a |
|---|
| 527 | dictionary. |
|---|
| 528 | |
|---|
| 529 | All instances of ``Scalar``, ``Seq``, and ``Map`` have the following |
|---|
| 530 | attributes: |
|---|
| 531 | |
|---|
| 532 | ``kind`` : string |
|---|
| 533 | ``'scalar'``, ``'seq'``, or ``'map'``; read-only. |
|---|
| 534 | |
|---|
| 535 | ``anchor`` : string or ``None`` |
|---|
| 536 | The node anchor. |
|---|
| 537 | |
|---|
| 538 | ``tag`` : string or ``None`` |
|---|
| 539 | The node tag. |
|---|
| 540 | |
|---|
| 541 | ``value`` |
|---|
| 542 | The node value. For scalar nodes, it should be a string. For sequence nodes, |
|---|
| 543 | it should be a list. For mapping nodes, it should be a list of pairs or a |
|---|
| 544 | dictionary. |
|---|
| 545 | |
|---|
| 546 | ``Scalar`` instances have additional attributes: |
|---|
| 547 | |
|---|
| 548 | ``style`` : string or ``None`` |
|---|
| 549 | The node style. Possible values are ``None`` (means literal or plain), |
|---|
| 550 | ``'1quote'``, ``'2quote'``, ``'fold'``, ``'literal'``, ``'plain'``. |
|---|
| 551 | |
|---|
| 552 | ``indent`` : integer |
|---|
| 553 | The node indentation. ``0`` means the default value. |
|---|
| 554 | |
|---|
| 555 | ``width`` : integer |
|---|
| 556 | The width of the node field. Longer scalars will be broken on several lines |
|---|
| 557 | to fit the field. ``0`` means the default value. |
|---|
| 558 | |
|---|
| 559 | ``chomp`` : string or ``None`` |
|---|
| 560 | The chomping method. Possible values are ``None`` (clip), ``'-'`` (strip), |
|---|
| 561 | ``'+'`` (keep). |
|---|
| 562 | |
|---|
| 563 | ``Seq`` and ``Map`` instances have an additional attribute: |
|---|
| 564 | |
|---|
| 565 | ``inline`` : boolean |
|---|
| 566 | The block/flow flag. |
|---|
| 567 | |
|---|
| 568 | For example, let us create a representation graph and transform it into a YAML |
|---|
| 569 | stream:: |
|---|
| 570 | |
|---|
| 571 | >>> # Create three scalar nodes: |
|---|
| 572 | >>> foo = Scalar('foo', tag="tag:example.com,2005:foo", style='fold', |
|---|
| 573 | ... indent=5) |
|---|
| 574 | >>> bar = Scalar('bar', style='1quote') |
|---|
| 575 | >>> baz = Scalar('baz') |
|---|
| 576 | |
|---|
| 577 | >>> # Create a sequence node: |
|---|
| 578 | >>> seq = Seq([foo, bar, baz], tag="x-private:seq") |
|---|
| 579 | |
|---|
| 580 | >>> # Emit it into a YAML stream: |
|---|
| 581 | >>> print emit(seq) |
|---|
| 582 | --- !!seq |
|---|
| 583 | - !example.com,2005/foo >- |
|---|
| 584 | foo |
|---|
| 585 | - 'bar' |
|---|
| 586 | - baz |
|---|
| 587 | |
|---|
| 588 | Now let us construct a representation graph from a YAML document:: |
|---|
| 589 | |
|---|
| 590 | >>> # The function 'parse' generates a representation graph: |
|---|
| 591 | >>> root = parse(""" |
|---|
| 592 | ... - foo |
|---|
| 593 | ... - bar |
|---|
| 594 | ... - baz |
|---|
| 595 | ... """) |
|---|
| 596 | |
|---|
| 597 | >>> # The object 'root' is a sequence node: |
|---|
| 598 | >>> root |
|---|
| 599 | <_syck.Seq object at 0xb7e124b4> |
|---|
| 600 | |
|---|
| 601 | >>> # We can transform 'root' back into a YAML stream: |
|---|
| 602 | >>> print emit(root) |
|---|
| 603 | --- |
|---|
| 604 | - foo |
|---|
| 605 | - bar |
|---|
| 606 | - baz |
|---|
| 607 | |
|---|
| 608 | >>> # We can also display the structure of the representation tree using a |
|---|
| 609 | >>> # clever trick: |
|---|
| 610 | >>> print dump(root) |
|---|
| 611 | --- !python/object:_syck.Seq |
|---|
| 612 | value: |
|---|
| 613 | - !python/object:_syck.Scalar |
|---|
| 614 | value: foo |
|---|
| 615 | tag: tag:yaml.org,2002:str |
|---|
| 616 | - !python/object:_syck.Scalar |
|---|
| 617 | value: bar |
|---|
| 618 | tag: tag:yaml.org,2002:str |
|---|
| 619 | - !python/object:_syck.Scalar |
|---|
| 620 | value: baz |
|---|
| 621 | tag: tag:yaml.org,2002:str |
|---|
| 622 | |
|---|
| 623 | Parser |
|---|
| 624 | ~~~~~~ |
|---|
| 625 | |
|---|
| 626 | ``Parser`` : class |
|---|
| 627 | The class ``Parser`` is a low-level wrapper of a Syck YAML parser. It can |
|---|
| 628 | generate a representation graph from a YAML stream. |
|---|
| 629 | |
|---|
| 630 | The class constructor has the following arguments: |
|---|
| 631 | |
|---|
| 632 | * ``Parser(source, implicit_typing=True, taguri_expansion=True)``. |
|---|
| 633 | |
|---|
| 634 | The parameter ``source`` is a YAML stream. It must be a string |
|---|
| 635 | or a file-like object. If it is not a string, it should have a |
|---|
| 636 | method named ``read(max_length)`` that returns a string. |
|---|
| 637 | |
|---|
| 638 | It is not recommended to change the default values of the parameters |
|---|
| 639 | ``implicit_typing`` and ``taguri_expansion``. See the Syck documentation |
|---|
| 640 | for more details about them. |
|---|
| 641 | |
|---|
| 642 | The class defines a single method: |
|---|
| 643 | |
|---|
| 644 | * ``Parser.parse()``. |
|---|
| 645 | |
|---|
| 646 | It parses the source and returns the root node of the corresponding |
|---|
| 647 | representation graph. If the stream is finished, it returns ``None`` and |
|---|
| 648 | set the flag ``eof`` on. |
|---|
| 649 | |
|---|
| 650 | ``GenericLoader`` : subclass of ``Parser`` |
|---|
| 651 | The subclass ``GenericLoader`` defines two additional methods: |
|---|
| 652 | |
|---|
| 653 | * ``GenericLoader.load()``, |
|---|
| 654 | |
|---|
| 655 | * ``GenericLoader.construct(node)``. |
|---|
| 656 | |
|---|
| 657 | The method ``load()`` parses the source and constructs the corresponding |
|---|
| 658 | Python object. To generate an object by a node, ``load()`` uses the |
|---|
| 659 | ``construct()`` method. The ``construct()`` method defined in |
|---|
| 660 | ``GenericLoader`` just returns the value of the node: a string, a list, |
|---|
| 661 | or a dictionary. |
|---|
| 662 | |
|---|
| 663 | ``Loader`` : subclass of ``GenericLoader`` |
|---|
| 664 | |
|---|
| 665 | ``Loader`` redefines the method |
|---|
| 666 | |
|---|
| 667 | * ``Loader.construct(node)``, |
|---|
| 668 | |
|---|
| 669 | defines an additional method: |
|---|
| 670 | |
|---|
| 671 | * ``Loader.find_constructor(node)``, |
|---|
| 672 | |
|---|
| 673 | and add many other auxiliary methods for constructing Python objects. |
|---|
| 674 | |
|---|
| 675 | ``Loader.construct()`` calls ``find_constructor()`` for the given node, |
|---|
| 676 | and uses the returned constructor to generate a Python object. |
|---|
| 677 | |
|---|
| 678 | ``Loader.find_constructor()`` determines the constructor of a node by |
|---|
| 679 | the following rules: |
|---|
| 680 | |
|---|
| 681 | * If the node tag has the form ``tag:yaml.org,2002:type_id``, returns the |
|---|
| 682 | method ``Loader.construct_type_id``. |
|---|
| 683 | |
|---|
| 684 | * If the node tag has the form ``tag:python.yaml.org,2002:type_id``, returns |
|---|
| 685 | the method ``Loader.construct_python_type_id``. |
|---|
| 686 | |
|---|
| 687 | * If the node tag has the form ``x-private:type_id``, returns |
|---|
| 688 | ``Loader.construct_private_type_id``. |
|---|
| 689 | |
|---|
| 690 | * If the node tag has the form ``tag:domain.tld,year:type_id``, returns |
|---|
| 691 | ``Loader.construct_domain_tld_year_type_id``. |
|---|
| 692 | |
|---|
| 693 | See the source for more details. |
|---|
| 694 | |
|---|
| 695 | Let us show how ``Parser``, ``GenericLoader``, and ``Loader`` parse the same |
|---|
| 696 | document:: |
|---|
| 697 | |
|---|
| 698 | >>> # The source stream includes PySyck specific tags '!python/tuple' |
|---|
| 699 | >>> # and '!python/unicode'. It also includes implicitly typed integer |
|---|
| 700 | >>> # '12345' |
|---|
| 701 | >>> source = """--- !python/tuple |
|---|
| 702 | ... - a string |
|---|
| 703 | ... - !python/unicode a unicode string |
|---|
| 704 | ... - 12345 |
|---|
| 705 | ... """ |
|---|
| 706 | |
|---|
| 707 | >>> # 'Parser.parse()' returns the root node of the representation tree: |
|---|
| 708 | >>> p = Parser(source) |
|---|
| 709 | >>> print p.parse() |
|---|
| 710 | <_syck.Seq object at 0xb7a33f54> |
|---|
| 711 | |
|---|
| 712 | >>> # 'GenericLoader.load()' returns a Python object, but ignores the tags: |
|---|
| 713 | >>> gl = GenericLoader(source) |
|---|
| 714 | >>> print gl.load() |
|---|
| 715 | ['a string', 'a unicode string', '12345'] |
|---|
| 716 | |
|---|
| 717 | >>> # 'Loader.load()' is aware of the tags: |
|---|
| 718 | >>> l = Loader(source) |
|---|
| 719 | >>> print l.load() |
|---|
| 720 | ('a string', u'a unicode string', 12345) |
|---|
| 721 | |
|---|
| 722 | Emitter |
|---|
| 723 | ~~~~~~~ |
|---|
| 724 | |
|---|
| 725 | ``Emitter`` : class |
|---|
| 726 | The class ``Emitter`` is a low-level wrapper of a Syck YAML emitter. It can |
|---|
| 727 | generate a YAML stream from a representation graph. |
|---|
| 728 | |
|---|
| 729 | The class constructor has the following signature: |
|---|
| 730 | |
|---|
| 731 | * ``Emitter(output, headless=False, use_header=False, use_version=False, |
|---|
| 732 | explicit_typing=True, style=None, best_width=80, indent=2)``. |
|---|
| 733 | |
|---|
| 734 | The parameter ``output`` must be a file-like object that provides a method |
|---|
| 735 | ``write(data)``. The other parameters describe the formatting of the output |
|---|
| 736 | document. |
|---|
| 737 | |
|---|
| 738 | The class defines a single method: |
|---|
| 739 | |
|---|
| 740 | * ``emit(node)``. |
|---|
| 741 | |
|---|
| 742 | The parameter ``node`` must be the root node of a YAML representation graph. |
|---|
| 743 | The method ``emit()`` writes the generated YAML document to the ``output`` |
|---|
| 744 | stream. |
|---|
| 745 | |
|---|
| 746 | ``GenericDumper`` : subclass of ``Emitter`` |
|---|
| 747 | The subclass ``GenericDumper`` adds the following methods: |
|---|
| 748 | |
|---|
| 749 | * ``GenericDumper.dump(object)``, |
|---|
| 750 | |
|---|
| 751 | * ``GenericDumper.represent(object)``, |
|---|
| 752 | |
|---|
| 753 | * ``GenericDumper.allow_aliases(object)``. |
|---|
| 754 | |
|---|
| 755 | The method ``dump()`` converts the given object into a representation graph, |
|---|
| 756 | generates a YAML document, and writes it to the ``output`` stream. It uses |
|---|
| 757 | the method ``represent()`` to convert an object to a representation node. |
|---|
| 758 | The method ``represent()`` defined in ``GenericDumper`` generates a sequence |
|---|
| 759 | node for a list object and a mapping node for a dictionary object. Otherwise |
|---|
| 760 | it generates a scalar node with the value equal to ``str(object)``. |
|---|
| 761 | |
|---|
| 762 | The Syck YAML emitter automatically detects if the same object is reffered |
|---|
| 763 | from different parts of the graph and generates aliases for it. Unfortunately |
|---|
| 764 | it does not work well with immutable Python objects such as strings, numbers, |
|---|
| 765 | and tuples. To prevent generating unnecessary aliases, the method |
|---|
| 766 | ``allow_aliases()`` is used. If ``allow_aliases()`` for a given object |
|---|
| 767 | returns ``False``, the alias will never be generated. |
|---|
| 768 | |
|---|
| 769 | The ``allow_aliases()`` method defined in ``GenericDumper`` always returns |
|---|
| 770 | ``True``. |
|---|
| 771 | |
|---|
| 772 | ``Dumper`` : subclass of ``GenericDumper`` |
|---|
| 773 | The subclass ``Dumpers`` redefines the methods: |
|---|
| 774 | |
|---|
| 775 | * ``Dumper.represent(object)``, |
|---|
| 776 | |
|---|
| 777 | * ``Dumper.allow_aliases(object)``, |
|---|
| 778 | |
|---|
| 779 | defines the method |
|---|
| 780 | |
|---|
| 781 | * ``Dumper.find_representer(object)``, |
|---|
| 782 | |
|---|
| 783 | and add many other auxiliary methods for representing objects as nodes. |
|---|
| 784 | |
|---|
| 785 | ``Dumper.find_representer()`` finds a method that can represent the given |
|---|
| 786 | object as a node in a representation tree. ``find_representer()`` checks the |
|---|
| 787 | class of the object. If the class has the form ``package.module.type``, |
|---|
| 788 | ``find_representer()`` returns the method |
|---|
| 789 | ``Dumper.represent_package_module_type`` if it exists. If this method does |
|---|
| 790 | not exists, ``find_representer()`` consults its base class, and so on. |
|---|
| 791 | |
|---|
| 792 | ``Dumper.represent()`` calls ``Dumper.find_representer()`` for the given |
|---|
| 793 | object and uses the returned method to generate a representation node. |
|---|
| 794 | |
|---|
| 795 | See the source for more details. |
|---|
| 796 | |
|---|
| 797 | Let us show how ``Emitter``, ``GenericDumper``, and ``Dumper`` work:: |
|---|
| 798 | |
|---|
| 799 | >>> # For our demonstration, we define a representation tree named 'seq' |
|---|
| 800 | >>> # and a Python tuple named 'object': |
|---|
| 801 | >>> foo = Scalar('a string') |
|---|
| 802 | >>> bar = Scalar('a unicode string', tag="tag:python.yaml.org,2002:unicode") |
|---|
| 803 | >>> baz = Scalar('12345', tag="tag:yaml.org,2002:int") |
|---|
| 804 | >>> seq = Seq([foo, bar, baz], tag="tag:python.taml.org,2002:tuple") |
|---|
| 805 | >>> object = ('a string', u'a unicode string', 12345) |
|---|
| 806 | |
|---|
| 807 | >>> # An 'Emitter' instance can dump a representation tree into a stream, |
|---|
| 808 | >>> # but obviously failed to dump a Python object: |
|---|
| 809 | >>> e = Emitter(sys.stdout) |
|---|
| 810 | >>> e.emit(seq) |
|---|
| 811 | --- !python.taml.org,2002/tuple |
|---|
| 812 | - a string |
|---|
| 813 | - !python/unicode a unicode string |
|---|
| 814 | - 12345 |
|---|
| 815 | >>> e.emit(object) |
|---|
| 816 | Traceback (most recent call last): |
|---|
| 817 | File "<stdin>", line 1, in ? |
|---|
| 818 | TypeError: Node instance is required |
|---|
| 819 | |
|---|
| 820 | >>> # A 'GenericDumper' instance dumps almost everything as a scalar: |
|---|
| 821 | >>> gd = GenericDumper(sys.stdout) |
|---|
| 822 | >>> gd.dump(seq) |
|---|
| 823 | --- <_syck.Seq object at 0xb7a3c2fc> |
|---|
| 824 | >>> gd.dump(object) |
|---|
| 825 | --- ('a string', u'a unicode string', 12345) |
|---|
| 826 | |
|---|
| 827 | >>> # Finally, a 'Dumper' instance dumps a representation tree as a complex |
|---|
| 828 | >>> # Python object: |
|---|
| 829 | >>> d = Dumper(sys.stdout) |
|---|
| 830 | >>> d.dump(seq) |
|---|
| 831 | --- !python/object:_syck.Seq |
|---|
| 832 | value: |
|---|
| 833 | - !python/object:_syck.Scalar |
|---|
| 834 | value: a string |
|---|
| 835 | - !python/object:_syck.Scalar |
|---|
| 836 | value: a unicode string |
|---|
| 837 | tag: tag:python.yaml.org,2002:unicode |
|---|
| 838 | - !python/object:_syck.Scalar |
|---|
| 839 | value: "12345" |
|---|
| 840 | tag: tag:yaml.org,2002:int |
|---|
| 841 | tag: tag:python.taml.org,2002:tuple |
|---|
| 842 | >>> # It also dumps the 'object' object as expected: |
|---|
| 843 | >>> d.dump(object) |
|---|
| 844 | --- !python/tuple |
|---|
| 845 | - a string |
|---|
| 846 | - !python/unicode a unicode string |
|---|
| 847 | - 12345 |
|---|
| 848 | |
|---|
| 849 | |
|---|
| 850 | Development and Bug Reports |
|---|
| 851 | =========================== |
|---|
| 852 | |
|---|
| 853 | You may check out the PySyck_ source code from `PySyck SVN repository`_. |
|---|
| 854 | |
|---|
| 855 | If you find a bug in PySyck_, please file a bug report to `PySyck BTS`_. You |
|---|
| 856 | may review open bugs on `the list of active tickets`_. |
|---|
| 857 | |
|---|
| 858 | You may use `YAML-core mailing list`_ for discussions of PySyck_. |
|---|
| 859 | |
|---|
| 860 | .. _PySyck SVN repository: http://svn.xitology.org/pysyck/ |
|---|
| 861 | .. _PySyck BTS: http://trac.xitology.org/pysyck/newticket |
|---|
| 862 | .. _the list of active tickets: http://trac.xitology.org/pysyck/report/1 |
|---|
| 863 | .. _YAML-core mailing list: http://lists.sourceforge.net/lists/listinfo/yaml-core |
|---|
| 864 | |
|---|
| 865 | |
|---|
| 866 | Known Bugs |
|---|
| 867 | ========== |
|---|
| 868 | |
|---|
| 869 | To many to list all of them; see `the list of active tickets`_. If you find |
|---|
| 870 | another bug, please submit it via `PySyck BTS`_. |
|---|
| 871 | |
|---|
| 872 | |
|---|
| 873 | History |
|---|
| 874 | ======= |
|---|
| 875 | |
|---|
| 876 | * PySyck-0.55.1 (2005-08-..): Initial release. |
|---|
| 877 | |
|---|
| 878 | |
|---|
| 879 | Author and Copyright |
|---|
| 880 | ==================== |
|---|
| 881 | |
|---|
| 882 | The PySyck_ module was written by `Kirill Simonov`_. |
|---|
| 883 | |
|---|
| 884 | PySyck_ is released under the BSD license as Syck_ itself. |
|---|
| 885 | |
|---|
| 886 | .. _Kirill Simonov: mailto:xi@resolvent.net |
|---|
| 887 | |
|---|
| 888 | .. |
|---|
| 889 | vim: ft=rst: |
|---|