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