Kirill Simonov avatar Kirill Simonov committed c0be371 Draft

Move pysyck to the new location.

Comments (0)

Files changed (41)

+include README.txt README.html
+recursive-include tests *.py
+
+.PHONY: default build force install test clean	\
+	dist-src dist-win dist-win-2.2 dist-win-2.3 dist-win-2.4
+
+PYTHON=/usr/bin/python
+REST2HTML=/usr/bin/rest2html --embed-stylesheet --stylesheet-path=/usr/share/python-docutils/stylesheets/default.css
+TEST=
+PARAMETERS=
+
+default: build README.html
+
+build:
+	${PYTHON} setup.py build ${PARAMETERS}
+
+force:
+	${PYTHON} setup.py build -f ${PARAMETERS}
+
+install: build
+	${PYTHON} setup.py install ${PARAMETERS}
+
+test: build
+	${PYTHON} tests/test_build.py -v ${TEST}
+
+clean:
+	${PYTHON} setup.py clean -a
+
+dist-src:
+	${PYTHON} setup.py sdist --formats=zip,gztar
+
+dist-win: dist-win-2.2 dist-win-2.3 dist-win-2.4
+
+dist-win-2.2: PYTHON=/c/Python22/python
+dist-win-2.2: PARAMETERS=--compiler=mingw32
+dist-win-2.2:
+	${PYTHON} setup.py build ${PARAMETERS}
+	${PYTHON} setup.py bdist_wininst
+
+dist-win-2.3: PYTHON=/c/Python23/python
+dist-win-2.3: PARAMETERS=--compiler=mingw32
+dist-win-2.3:
+	${PYTHON} setup.py build ${PARAMETERS}
+	${PYTHON} setup.py bdist_wininst --skip-build --target-version=2.3
+
+dist-win-2.4: PYTHON=/c/Python24/python
+dist-win-2.4: PARAMETERS=--compiler=mingw32
+dist-win-2.4:
+	${PYTHON} setup.py build ${PARAMETERS}
+	${PYTHON} setup.py bdist_wininst --skip-build --target-version=2.4
+
+README.html: README.txt
+	${REST2HTML} README.txt README.html
+
+
+============================================================
+PySyck: Python bindings for the Syck YAML parser and emitter
+============================================================
+
+:Author: Kirill Simonov
+:Contact: xi@resolvent.net
+:Web site: http://xitology.org/pysyck/
+
+.. contents::
+
+
+Overview
+========
+
+YAML_ is a data serialization format designed for human readability and
+interaction with scripting languages.
+
+Syck_ is an extension for reading and writing YAML in scripting languages. Syck
+provides bindings to the Python_ programming language, but they are somewhat
+limited and leak memory.
+
+PySyck_ is aimed to update the current Python bindings for Syck. The new
+bindings provide a wrapper for the Syck emitter and give access to YAML
+representation graphs. Hopefully it will not leak memory as well.
+
+PySyck_ may be used for various tasks, in particular, as a replacement of the
+module pickle_. Please be aware that PySyck_ is a beta-quality software and
+is not ready yet for production use.
+
+.. _YAML: http://yaml.org/
+.. _Syck: http://whytheluckystiff.net/syck/
+.. _Python: http://python.org/
+.. _PySyck: http://xitology.org/pysyck/
+.. _pickle: http://docs.python.org/lib/module-pickle.html
+
+Requirements
+============
+
+PySyck requires Syck 0.55 or higher and Python 2.3 or higher. Python 2.2 is
+supported to some extent.
+
+
+Installation
+============
+
+Please note that Syck 0.55 or higher must be installed. If you install PySyck
+from source, unpack the source tarball and type::
+
+  $ python setup.py install
+
+Windows binaries for Python 2.2, 2.3, and 2.4 are provided.
+
+
+Usage
+=====
+
+The documentation is still rough and incomplete. See `the source code`_ for
+more information.
+
+.. _the source code: http://trac.xitology.org/pysyck/browser/
+
+Quick Example
+-------------
+
+::
+
+  >>> from syck import *
+  >>> print load("""
+  ... - foo
+  ... - bar
+  ... - baz
+  ... """)
+  ['foo', 'bar', 'baz']
+  >>> print dump(['foo', 'bar', 'baz'])
+  ---
+  - foo
+  - bar
+  - baz
+
+YAML syntax
+-----------
+
+We do not describe the YAML syntax here. Please check http://yaml.org/ for the
+reference.
+
+In addition to the tags defined in `the YAML types repository`_, PySyck understands
+the following Python-specific tags:
+
+* ``tag:python.yaml.org,2002:none``,
+* ``tag:python.yaml.org,2002:bool``,
+* ``tag:python.yaml.org,2002:int``,
+* ``tag:python.yaml.org,2002:float``,
+* ``tag:python.yaml.org,2002:str``,
+* ``tag:python.yaml.org,2002:unicode``,
+* ``tag:python.yaml.org,2002:list``,
+* ``tag:python.yaml.org,2002:tuple``,
+* ``tag:python.yaml.org,2002:dict``,
+* ``tag:python.yaml.org,2002:name:...``,
+* ``tag:python.yaml.org,2002:object:...``,
+* ``tag:python.yaml.org,2002:new:...``,
+* ``tag:python.yaml.org,2002:apply:...``.
+
+Most of these tags are self-explanatory. The tags ``!python/name:...``,
+``!python/object:...``, ``!python/new:...``, and ``!python/apply:...`` are used
+for constructing Python functions, classes, and objects. See the sections `Use
+Python-specific tags in YAML documents`_ and `Use Python-specific tags to
+construct Python objects`_ for some examples.
+
+.. _the YAML types repository: http://yaml.org/type/index.html
+
+Common Tasks
+------------
+
+Import the module
+~~~~~~~~~~~~~~~~~
+
+::
+
+  >>> from syck import *
+
+or
+
+::
+
+  >>> import syck
+
+Load a document from a string
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  >>> source = "..."
+  >>> object = load(source)
+
+Load a document from a file
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  >>> source = file(..., 'r')
+  >>> object = load(source)
+
+Convert a Python object to a YAML document
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  >>> object = ...
+  >>> document = dump(object)
+
+Dump a Python object to a YAML stream
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  >>> object = ...
+  >>> output = file(..., 'w')
+  >>> dump(object, output)
+
+Format the output YAML stream
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  >>> object = ...
+  >>> output = file(..., 'w')
+  >>> dump(object, output,
+  ...     headless=False, use_header=False, use_version=False,
+  ...     explicit_typing=True, style=None, best_width=80, indent=2)
+
+Load several documents from a YAML stream
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  >>> source = ...
+  >>> objects = load_documents(source)
+  >>> for object in objects:
+  ...     # ...
+
+Create several documents in a YAML stream
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  >>> objects = [...]
+  >>> output = file(..., 'w')
+  >>> dump_documents(objects, output)
+
+Construct a representation tree of a YAML document
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  >>> source = ...
+  >>> root_node = parse(source)
+
+Convert a representation tree to a YAML document
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  >>> scalar_node = Scalar('...', tag='tag:...',
+  ...     style='...', indent=.., width=..)
+  >>> sequence_node = Seq(list_of_nodes, tag='tag:...', inline=..)
+  >>> mapping_node = Map(dictionary_of_nodes, tag='tag:...', inline=..)
+  >>> root_node = ...
+  >>> output = file(..., 'w')
+  >>> emit(root_node, output)
+
+Use PySyck as a pickle replacement
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  >>> object = ...
+  >>> stream = ...
+  >>> dump(object, stream)
+  
+  >>> stream = ...
+  >>> object = load(stream)
+
+Use PySyck to display the structure of a complex object
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  >>> object = ...
+  >>> print dump(object)
+
+Use PySyck to display a YAML representation graph
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  >>> source = ...
+  >>> node = parse(source)
+  >>> print dump(node)
+
+Use Python-specific tags in YAML documents
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  --- %YAML:1.0
+  - !python/none ''       # You may also use '!null'.
+  - !python/bool 'False'  # You may also use '!bool'.
+  - !python/int '123'     # You may also use '!int'.
+  - !python/long '1234567890'
+  - !python/float '123.456789'  # Also '!float'.
+  - !python/str 'a string'      # Also '!str'.
+  - !python/unicode 'a unicode string encoded in utf-8'
+  - !python/list [1, 2, 3]      # The same as '!seq' or no tag.
+  - !python/tuple [1, 2, 3]
+  - !python/dict { 1: foo, 2: bar } # The same as '!map' or no tag.
+
+Use Python-specific tags to construct functions or classes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  --- %YAML:1.0
+  - !python/name:package.module.function_name ''
+  - !python/name:package.module.class_name ''
+
+Use Python-specific tags to construct Python objects
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  --- %YAML:1.0
+  - !python/object:package.module.type
+    attribute1: value1
+    attribute2: value2
+    # ...
+  - !python/new:package.module.type
+    - parameter1
+    - parameter2
+    # ...
+  - !python/new:package.module.type
+    args: [parameter1, parameter2, ...]
+    kwds: {kwd1: val1, kwd2: val2, ...}
+    state: {attr1: val1, attr2: val2, ...}
+    # ...
+  - !python/apply:package.module.function
+    - parameter1
+    - parameter2
+    # ...
+  - !python/apply:package.module.function
+    args: [parameter1, parameter2, ...]
+    kwds: {kwd1: val1, kwd2: val2, ...}
+    state: {attr1: val1, attr2: val2, ...}
+    # ...
+
+Use application specific tags
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  >>> class MyClass:
+  ...   # ...
+
+  >>> class MyLoader(Loader):
+  ...     def construct_private_my_tag(self, node):
+  ...         # ...
+  ...         return MyClass(...)
+
+  >>> class MyDumper(Dumper):
+  ...     def represent_MyDumper(self, object):
+  ...         # ...
+  ...         return Map(...)
+
+  >>> source = """--- !!my_tag { ... }"""
+  >>> my_instance = load(source, Loader=MyLoader)
+
+  >>> my_instance = MyClass(...)
+  >>> output = dump(my_instance, Dumper=MyDumper)
+
+Reference
+---------
+
+Functions
+~~~~~~~~~
+
+``load`` : function
+  ``load(source, Loader=Loader, **parameters)``
+
+  The function ``load()`` returns a Python object corresponding to the first
+  document in the source. If the source is empty, ``load()`` returns ``None``.
+  ``source`` must be a string or a file-like object that has the method
+  ``read(max_length)``.
+
+  By default, the function ``load()`` uses an instance of the class ``Loader``
+  for parsing. You may use another class or pass additional parameters to the
+  class constructor. See the section Parser_ for more details.
+
+  Example::
+
+    >>> load("""
+    ... - foo
+    ... - bar
+    ... - baz
+    ... """)
+    ['foo', 'bar', 'baz']
+
+``parse`` : function
+  ``parse(source, Loader=Loader, **parameters)``
+
+  The function ``parse()`` parses the source and returns a representation tree
+  of the first document. ``source`` must be a string or a file-like object
+  that has the method ``read(max_length)``.
+
+  By default, the function ``parse()`` uses an instance of the class ``Loader``
+  for parsing. You may use another class or pass additional parameters to the
+  class constructor. See the section Parser_ for more details.
+
+  Example::
+
+    >>> parse("""
+    ... - foo
+    ... - bar
+    ... - baz
+    ... """)
+    <_syck.Seq object at 0xb7a3f2fc>
+
+``load_documents`` : function
+  ``load_documents(source, Loader=Loader, **parameters)``
+
+  The function ``load_documents()`` parses the source and an iterator.  The
+  iterator produces Python objects corresponding the documents of the source
+  stream. ``source`` must be a string or a file-like object that has the method
+  ``read(max_length)``.
+
+  By default, the function ``load_documents()`` uses an instance of the class
+  ``Loader`` for parsing. You may use another class or pass additional
+  parameters to the class constructor. See the section Parser_ for more
+  details.
+
+  Example::
+
+    >>> source = """
+    ... --- >
+    ... This is the
+    ... first document.
+    ... --- >
+    ... This is the
+    ... next document.
+    ... --- >
+    ... This is the
+    ... last document.
+    ... """
+    >>> for object in load_documents(source): print object
+    ...
+    This is the first document.
+
+    This is the next document.
+
+    This is the last document.
+
+``parse_documents`` : function
+  ``parse_documents(source, Loader=Loader, **parameters)``
+
+  The function ``parse_documents()`` is similar to ``load_documents()``, but
+  produces representation graphs for all documents in the source.
+  
+``dump`` : function
+  ``dump(object, output=None, Dumper=Dumper, **parameters)``
+
+  The function ``dump()`` converts ``object`` to a representation graph
+  and write it to ``output``. ``output`` must be ``None`` or a file-like
+  object that has the method ``write(data)``. If ``output`` is ``None``,
+  ``dump()`` returns the generated document.
+
+  By default, the function ``dump()`` uses an instance of the class ``Dumper``
+  for emitting. You may use another class or pass additional parameters to the
+  class constructor. See the section Emitter_ for more details.
+
+  Example::
+
+    >>> object = ['foo', 'bar', ['baz']]
+    >>> dump(object, sys.stdout)
+    ---
+    - foo
+    - bar
+    - - baz
+    >>> print dump(object)
+    ---
+    - foo
+    - bar
+    - - baz
+
+    >>> print dump(object, use_version=True, indent=5)
+    --- %YAML:1.0
+    - foo
+    - bar
+    -    - baz
+
+``emit`` : function
+  ``emit(node, output=None, Dumper=Dumper, **parameters)``
+
+  The function ``emit()`` write the representation graph to the output stream.
+  ``output`` must be ``None`` or a file-like object that has the method
+  ``write(data)``. If ``output`` is ``None``, ``emit()`` returns the generated
+  document.
+
+  By default, the function ``emit()`` uses an instance of the class ``Dumper``
+  for emitting. You may use another class or pass additional parameters to the
+  class constructor. See the section Emitter_ for more details.
+
+  Example::
+
+    >>> foo = Scalar('a string')
+    >>> bar = Scalar('a unicode string', tag="tag:python.yaml.org,2002:unicode")
+    >>> baz = Scalar('12345', tag="tag:yaml.org,2002:int")
+    >>> seq = Seq([foo, bar, baz], tag="tag:python.taml.org,2002:tuple")
+    >>> print emit(seq, use_version=True)
+    --- %YAML:1.0 !python.taml.org,2002/tuple
+    - a string
+    - !python/unicode a unicode string
+    - 12345
+
+``dump_documents`` : function
+  ``dump_documents(objects, output=None, Dumper=Dumper, **parameters)``
+
+  The function ``dump_documents()`` takes a list of objects and converts
+  each object to a YAML document. If ``output`` is ``None``, it returns
+  the produced documents. Otherwise it writes down them to ``output``,
+  which must be a file-like object with the method ``write(data)``.
+
+  By default, the function ``dump_documents()`` uses an instance of the class
+  ``Dumper`` for emitting. You may use another class or pass additional
+  parameters to the class constructor. See the section Emitter_ for more
+  details.
+
+  Example::
+
+    >>> print dump_documents(['foo', 'bar', 'baz'])
+    --- foo
+    --- bar
+    --- baz
+
+``emit_documents`` : function
+  ``emit_documents(nodes, output=None, Dumper=Dumper, **parameters)``
+
+  The function ``emit_documents()`` is similar to ``dump_documents()``, but
+  it requires a list of representation graphs.
+
+Exceptions
+~~~~~~~~~~
+
+``error`` : exception
+  This exception is raised by the Syck parser when it detects a syntax error.
+
+  The attribute ``args`` of the exception is a triple: *message*, *row*,
+  *column*.
+
+  Example::
+
+    >>> load("""---
+    ... - foo
+    ... - '''
+    ... - bar
+    ... """)
+    Traceback (most recent call last):
+      File "<stdin>", line 1, in ?
+      File "build/lib.linux-i686-2.3/syck/loaders.py", line 384, in load
+      File "build/lib.linux-i686-2.3/syck/loaders.py", line 42, in load
+    _syck.error: ('syntax error', 4, 2)
+
+Nodes
+~~~~~
+
+The following four classes represents nodes in the YAML representation graph:
+
+``Node`` : class
+  ``Node`` is an abstract class; you cannot create an instance of the class
+  ``Node``. ``Node`` is the base class of ``Scalar``, ``Seq``, and ``Map``.
+
+``Scalar`` : subclass of ``Node``
+  ``Scalar`` represents a scalar node. Its value is a string.
+
+``Seq`` : subclass of ``Node``
+  ``Seq`` represents a sequence node. Its value is a list of nodes.
+
+``Map`` : subclass of ``Node``
+  ``Map`` represents a mapping node. Its value is a list of pairs or a
+  dictionary.
+
+All instances of ``Scalar``, ``Seq``, and ``Map`` have the following
+attributes:
+
+``kind`` : string
+  ``'scalar'``, ``'seq'``, or ``'map'``; read-only.
+
+``anchor`` : string or ``None``
+  The node anchor.
+
+``tag`` : string or ``None``
+  The node tag.
+
+``value``
+  The node value. For scalar nodes, it should be a string. For sequence nodes,
+  it should be a list. For mapping nodes, it should be a list of pairs or a
+  dictionary.
+
+``Scalar`` instances have additional attributes:
+
+``style`` : string or ``None``
+  The node style. Possible values are ``None`` (means literal or plain),
+  ``'1quote'``, ``'2quote'``, ``'fold'``, ``'literal'``, ``'plain'``.
+
+``indent`` : integer
+  The node indentation. ``0`` means the default value.
+
+``width`` : integer
+  The width of the node field. Longer scalars will be broken on several lines
+  to fit the field. ``0`` means the default value.
+
+``chomp`` : string or ``None``
+  The chomping method. Possible values are ``None`` (clip), ``'-'`` (strip),
+  ``'+'`` (keep).
+
+``Seq`` and ``Map`` instances have an additional attribute:
+
+``inline`` : boolean
+  The block/flow flag.
+
+For example, let us create a representation graph and transform it into a YAML
+stream::
+
+  >>> # Create three scalar nodes:
+  >>> foo = Scalar('foo', tag="tag:example.com,2005:foo", style='fold',
+  ...     indent=5)
+  >>> bar = Scalar('bar', style='1quote')
+  >>> baz = Scalar('baz')
+
+  >>> # Create a sequence node:
+  >>> seq = Seq([foo, bar, baz], tag="x-private:seq")
+
+  >>> # Emit it into a YAML stream:
+  >>> print emit(seq)
+  --- !!seq
+  - !example.com,2005/foo >-
+       foo
+  - 'bar'
+  - baz
+
+Now let us construct a representation graph from a YAML document::
+
+  >>> # The function 'parse' generates a representation graph:
+  >>> root = parse("""
+  ... - foo
+  ... - bar
+  ... - baz
+  ... """)
+
+  >>> # The object 'root' is a sequence node:
+  >>> root
+  <_syck.Seq object at 0xb7e124b4>
+
+  >>> # We can transform 'root' back into a YAML stream:
+  >>> print emit(root)
+  ---
+  - foo
+  - bar
+  - baz
+
+  >>> # We can also display the structure of the representation tree using a
+  >>> # clever trick:
+  >>> print dump(root)
+  --- !python/object:_syck.Seq
+  value:
+  - !python/object:_syck.Scalar
+    value: foo
+    tag: tag:yaml.org,2002:str
+  - !python/object:_syck.Scalar
+    value: bar
+    tag: tag:yaml.org,2002:str
+  - !python/object:_syck.Scalar
+    value: baz
+    tag: tag:yaml.org,2002:str
+
+Parser
+~~~~~~
+
+``Parser`` : class
+  The class ``Parser`` is a low-level wrapper of a Syck YAML parser. It can
+  generate a representation graph from a YAML stream.
+
+  The class constructor has the following arguments:
+
+  * ``Parser(source, implicit_typing=True, taguri_expansion=True)``.
+
+  The parameter ``source`` is a YAML stream. It must be a string
+  or a file-like object. If it is not a string, it should have a
+  method named ``read(max_length)`` that returns a string.
+
+  It is not recommended to change the default values of the parameters
+  ``implicit_typing`` and ``taguri_expansion``. See the Syck documentation
+  for more details about them.
+
+  The class defines a single method:
+
+  * ``Parser.parse()``.
+
+  It parses the source and returns the root node of the corresponding
+  representation graph. If the stream is finished, it returns ``None`` and
+  set the flag ``eof`` on.
+
+``GenericLoader`` : subclass of ``Parser``
+  The subclass ``GenericLoader`` defines two additional methods:
+
+  * ``GenericLoader.load()``,
+
+  * ``GenericLoader.construct(node)``.
+
+  The method ``load()`` parses the source and constructs the corresponding
+  Python object. To generate an object by a node, ``load()`` uses the
+  ``construct()`` method. The ``construct()`` method defined in
+  ``GenericLoader`` just returns the value of the node: a string, a list,
+  or a dictionary.
+
+``Loader`` : subclass of ``GenericLoader``
+  
+  ``Loader`` redefines the method
+
+  * ``Loader.construct(node)``,
+
+  defines an additional method:
+
+  * ``Loader.find_constructor(node)``,
+
+  and add many other auxiliary methods for constructing Python objects.
+
+  ``Loader.construct()`` calls ``find_constructor()`` for the given node,
+  and uses the returned constructor to generate a Python object.
+
+  ``Loader.find_constructor()`` determines the constructor of a node by
+  the following rules:
+
+  * If the node tag has the form ``tag:yaml.org,2002:type_id``, returns the
+    method ``Loader.construct_type_id``.
+
+  * If the node tag has the form ``tag:python.yaml.org,2002:type_id``, returns
+    the method ``Loader.construct_python_type_id``.
+
+  * If the node tag has the form ``x-private:type_id``, returns
+    ``Loader.construct_private_type_id``.
+
+  * If the node tag has the form ``tag:domain.tld,year:type_id``, returns
+    ``Loader.construct_domain_tld_year_type_id``.
+
+  See the source for more details.
+
+Let us show how ``Parser``, ``GenericLoader``, and ``Loader`` parse the same
+document::
+
+  >>> # The source stream includes PySyck specific tags '!python/tuple'
+  >>> # and '!python/unicode'. It also includes implicitly typed integer
+  >>> # '12345'
+  >>> source = """--- !python/tuple
+  ... - a string
+  ... - !python/unicode a unicode string
+  ... - 12345
+  ... """
+
+  >>> # 'Parser.parse()' returns the root node of the representation tree:
+  >>> p = Parser(source)
+  >>> print p.parse()
+  <_syck.Seq object at 0xb7a33f54>
+
+  >>> # 'GenericLoader.load()' returns a Python object, but ignores the tags:
+  >>> gl = GenericLoader(source)
+  >>> print gl.load()
+  ['a string', 'a unicode string', '12345']
+
+  >>> # 'Loader.load()' is aware of the tags:
+  >>> l = Loader(source)
+  >>> print l.load()
+  ('a string', u'a unicode string', 12345)
+
+Emitter
+~~~~~~~
+
+``Emitter`` : class
+  The class ``Emitter`` is a low-level wrapper of a Syck YAML emitter. It can
+  generate a YAML stream from a representation graph.
+
+  The class constructor has the following signature:
+
+  * ``Emitter(output, headless=False, use_header=False, use_version=False,
+    explicit_typing=True, style=None, best_width=80, indent=2)``.
+
+  The parameter ``output`` must be a file-like object that provides a method
+  ``write(data)``. The other parameters describe the formatting of the output
+  document.
+
+  The class defines a single method:
+
+  * ``emit(node)``.
+
+  The parameter ``node`` must be the root node of a YAML representation graph.
+  The method ``emit()`` writes the generated YAML document to the ``output``
+  stream.
+
+``GenericDumper`` : subclass of ``Emitter``
+  The subclass ``GenericDumper`` adds the following methods:
+
+  * ``GenericDumper.dump(object)``,
+
+  * ``GenericDumper.represent(object)``,
+
+  * ``GenericDumper.allow_aliases(object)``.
+
+  The method ``dump()`` converts the given object into a representation graph,
+  generates a YAML document, and writes it to the ``output`` stream. It uses
+  the method ``represent()`` to convert an object to a representation node.
+  The method ``represent()`` defined in ``GenericDumper`` generates a sequence
+  node for a list object and a mapping node for a dictionary object. Otherwise
+  it generates a scalar node with the value equal to ``str(object)``.
+
+  The Syck YAML emitter automatically detects if the same object is reffered
+  from different parts of the graph and generates aliases for it. Unfortunately
+  it does not work well with immutable Python objects such as strings, numbers,
+  and tuples. To prevent generating unnecessary aliases, the method
+  ``allow_aliases()`` is used. If ``allow_aliases()`` for a given object
+  returns ``False``, the alias will never be generated.
+
+  The ``allow_aliases()`` method defined in ``GenericDumper`` always returns
+  ``True``.
+
+``Dumper`` : subclass of ``GenericDumper``
+  The subclass ``Dumpers`` redefines the methods:
+
+  * ``Dumper.represent(object)``,
+
+  * ``Dumper.allow_aliases(object)``,
+
+  defines the method
+
+  * ``Dumper.find_representer(object)``,
+
+  and add many other auxiliary methods for representing objects as nodes.
+
+  ``Dumper.find_representer()`` finds a method that can represent the given
+  object as a node in a representation tree. ``find_representer()`` checks the
+  class of the object. If the class has the form ``package.module.type``,
+  ``find_representer()`` returns the method
+  ``Dumper.represent_package_module_type`` if it exists. If this method does
+  not exists, ``find_representer()`` consults its base class, and so on.
+
+  ``Dumper.represent()`` calls ``Dumper.find_representer()`` for the given
+  object and uses the returned method to generate a representation node.
+
+  See the source for more details.
+
+Let us show how ``Emitter``, ``GenericDumper``, and ``Dumper`` work::
+
+  >>> # For our demonstration, we define a representation tree named 'seq'
+  >>> # and a Python tuple named 'object':
+  >>> foo = Scalar('a string')
+  >>> bar = Scalar('a unicode string', tag="tag:python.yaml.org,2002:unicode")
+  >>> baz = Scalar('12345', tag="tag:yaml.org,2002:int")
+  >>> seq = Seq([foo, bar, baz], tag="tag:python.taml.org,2002:tuple")
+  >>> object = ('a string', u'a unicode string', 12345)
+
+  >>> # An 'Emitter' instance can dump a representation tree into a stream,
+  >>> # but obviously failed to dump a Python object:
+  >>> e = Emitter(sys.stdout)
+  >>> e.emit(seq)
+  --- !python.taml.org,2002/tuple
+  - a string
+  - !python/unicode a unicode string
+  - 12345
+  >>> e.emit(object)
+  Traceback (most recent call last):
+    File "<stdin>", line 1, in ?
+  TypeError: Node instance is required
+
+  >>> # A 'GenericDumper' instance dumps almost everything as a scalar:
+  >>> gd = GenericDumper(sys.stdout)
+  >>> gd.dump(seq)
+  --- <_syck.Seq object at 0xb7a3c2fc>
+  >>> gd.dump(object)
+  --- ('a string', u'a unicode string', 12345)
+
+  >>> # Finally, a 'Dumper' instance dumps a representation tree as a complex
+  >>> # Python object:
+  >>> d = Dumper(sys.stdout)
+  >>> d.dump(seq)
+  --- !python/object:_syck.Seq
+  value:
+  - !python/object:_syck.Scalar
+    value: a string
+  - !python/object:_syck.Scalar
+    value: a unicode string
+    tag: tag:python.yaml.org,2002:unicode
+  - !python/object:_syck.Scalar
+    value: "12345"
+    tag: tag:yaml.org,2002:int
+  tag: tag:python.taml.org,2002:tuple
+  >>> # It also dumps the 'object' object as expected:
+  >>> d.dump(object)
+  --- !python/tuple
+  - a string
+  - !python/unicode a unicode string
+  - 12345
+
+
+Development and Bug Reports
+===========================
+
+You may check out the PySyck_ source code from `PySyck SVN repository`_.
+
+If you find a bug in PySyck_, please file a bug report to `PySyck BTS`_. You
+may review open bugs on `the list of active tickets`_.
+
+You may use `YAML-core mailing list`_ for discussions of PySyck_.
+
+.. _PySyck SVN repository: http://svn.xitology.org/pysyck/
+.. _PySyck BTS: http://trac.xitology.org/pysyck/newticket
+.. _the list of active tickets: http://trac.xitology.org/pysyck/report/1
+.. _YAML-core mailing list: http://lists.sourceforge.net/lists/listinfo/yaml-core
+
+
+Known Bugs
+==========
+
+To many to list all of them; see `the list of active tickets`_. If you find
+another bug, please submit it via `PySyck BTS`_.
+
+
+History
+=======
+
+* PySyck-0.55.1 (2005-08-30): Initial release.
+
+
+Author and Copyright
+====================
+
+The PySyck_ module was written by `Kirill Simonov`_.
+
+PySyck_ is released under the BSD license as Syck_ itself.
+
+.. _Kirill Simonov: mailto:xi@resolvent.net
+
+..
+  vim: ft=rst:

ext/_syckmodule.c

+
+#include <Python.h>
+#include <syck.h>
+
+/****************************************************************************
+ * Python 2.2 compatibility.
+ ****************************************************************************/
+
+#ifndef PyDoc_STR
+#define PyDoc_VAR(name)         static char name[]
+#define PyDoc_STR(str)          (str)
+#define PyDoc_STRVAR(name, str) PyDoc_VAR(name) = PyDoc_STR(str)
+#endif
+
+#ifndef PyMODINIT_FUNC
+#define PyMODINIT_FUNC  void
+#endif
+
+/****************************************************************************
+ * Global objects: _syck.error, 'scalar', 'seq', 'map',
+ * '1quote', '2quote', 'fold', 'literal', 'plain', '+', '-'.
+ ****************************************************************************/
+
+static PyObject *PySyck_Error;
+
+static PyObject *PySyck_ScalarKind;
+static PyObject *PySyck_SeqKind;
+static PyObject *PySyck_MapKind;
+
+static PyObject *PySyck_1QuoteStyle;
+static PyObject *PySyck_2QuoteStyle;
+static PyObject *PySyck_FoldStyle;
+static PyObject *PySyck_LiteralStyle;
+static PyObject *PySyck_PlainStyle;
+
+static PyObject *PySyck_StripChomp;
+static PyObject *PySyck_KeepChomp;
+
+/****************************************************************************
+ * The type _syck.Node.
+ ****************************************************************************/
+
+PyDoc_STRVAR(PySyckNode_doc,
+    "_syck.Node() -> TypeError\n\n"
+    "_syck.Node is an abstract type. It is the base type for _syck.Scalar,\n"
+    "_syck.Seq, and _syck.Map. You cannot create an instance of _syck.Node\n"
+    "directly. You may use _syck.Node for type checking or subclassing.\n");
+
+typedef struct {
+    PyObject_HEAD
+    /* Common fields for all Node types: */
+    PyObject *value;    /* always an object */
+    PyObject *tag;      /* a string object or NULL */
+    PyObject *anchor;   /* a string object or NULL */
+} PySyckNodeObject;
+
+
+static int
+PySyckNode_clear(PySyckNodeObject *self)
+{
+    PyObject *tmp;
+
+    tmp = self->value;
+    self->value = NULL;
+    Py_XDECREF(tmp);
+
+    tmp = self->tag;
+    self->tag = NULL;
+    Py_XDECREF(tmp);
+
+    tmp = self->anchor;
+    self->value = NULL;
+    Py_XDECREF(tmp);
+
+    return 0;
+}
+
+static int
+PySyckNode_traverse(PySyckNodeObject *self, visitproc visit, void *arg)
+{
+    int ret;
+
+    if (self->value)
+        if ((ret = visit(self->value, arg)) != 0)
+            return ret;
+
+    if (self->tag)
+        if ((ret = visit(self->tag, arg)) != 0)
+            return ret;
+
+    if (self->anchor)
+        if ((ret = visit(self->anchor, arg)) != 0)
+            return ret;
+
+    return 0;
+}
+
+static void
+PySyckNode_dealloc(PySyckNodeObject *self)
+{
+    PySyckNode_clear(self);
+    self->ob_type->tp_free((PyObject *)self);
+}
+
+static PyObject *
+PySyckNode_getkind(PySyckNodeObject *self, PyObject **closure)
+{
+    Py_INCREF(*closure);
+    return *closure;
+}
+
+static PyObject *
+PySyckNode_getvalue(PySyckNodeObject *self, void *closure)
+{
+    Py_INCREF(self->value);
+    return self->value;
+}
+
+static PyObject *
+PySyckNode_gettag(PySyckNodeObject *self, void *closure)
+{
+    PyObject *value = self->tag ? self->tag : Py_None;
+    Py_INCREF(value);
+    return value;
+}
+
+static int
+PySyckNode_settag(PySyckNodeObject *self, PyObject *value, void *closure)
+{
+    if (!value) {
+        PyErr_SetString(PyExc_TypeError, "cannot delete 'tag'");
+        return -1;
+    }
+
+    if (value == Py_None) {
+        Py_XDECREF(self->tag);
+        self->tag = NULL;
+        return 0;
+    }
+
+    if (!PyString_Check(value)) {
+        PyErr_SetString(PyExc_TypeError, "'tag' must be a string");
+        return -1;
+    }
+
+    Py_XDECREF(self->tag);
+    Py_INCREF(value);
+    self->tag = value;
+
+    return 0;
+}
+
+static PyObject *
+PySyckNode_getanchor(PySyckNodeObject *self, void *closure)
+{
+    PyObject *value = self->anchor ? self->anchor : Py_None;
+    Py_INCREF(value);
+    return value;
+}
+
+static int
+PySyckNode_setanchor(PySyckNodeObject *self, PyObject *value, void *closure)
+{
+    if (!value) {
+        PyErr_SetString(PyExc_TypeError, "cannot delete 'anchor'");
+        return -1;
+    }
+
+    if (value == Py_None) {
+        Py_XDECREF(self->anchor);
+        self->anchor = NULL;
+        return 0;
+    }
+
+    if (!PyString_Check(value)) {
+        PyErr_SetString(PyExc_TypeError, "'anchor' must be a string");
+        return -1;
+    }
+
+    Py_XDECREF(self->anchor);
+    Py_INCREF(value);
+    self->anchor = value;
+
+    return 0;
+}
+
+static PyTypeObject PySyckNode_Type = {
+    PyObject_HEAD_INIT(NULL)
+    0,                                          /* ob_size */
+    "_syck.Node",                               /* tp_name */
+    sizeof(PySyckNodeObject),                   /* tp_basicsize */
+    0,                                          /* tp_itemsize */
+    (destructor)PySyckNode_dealloc,             /* tp_dealloc */
+    0,                                          /* tp_print */
+    0,                                          /* tp_getattr */
+    0,                                          /* tp_setattr */
+    0,                                          /* tp_compare */
+    0,                                          /* tp_repr */
+    0,                                          /* tp_as_number */
+    0,                                          /* tp_as_sequence */
+    0,                                          /* tp_as_mapping */
+    0,                                          /* tp_hash */
+    0,                                          /* tp_call */
+    0,                                          /* tp_str */
+    0,                                          /* tp_getattro */
+    0,                                          /* tp_setattro */
+    0,                                          /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,  /* tp_flags */
+    PySyckNode_doc,                             /* tp_doc */
+    (traverseproc)PySyckNode_traverse,          /* tp_traverse */
+    (inquiry)PySyckNode_clear,                  /* tp_clear */
+};
+
+/****************************************************************************
+ * The type _syck.Scalar.
+ ****************************************************************************/
+
+PyDoc_STRVAR(PySyckScalar_doc,
+    "Scalar(value='', tag=None, style=None, indent=0, width=0, chomp=None)\n"
+    "      -> a Scalar node\n\n"
+    "_syck.Scalar represents a scalar node in Syck parser and emitter\n"
+    "trees. A scalar node points to a single string value.\n");
+
+typedef struct {
+    PyObject_HEAD
+    /* Common fields for all Node types: */
+    PyObject *value;    /* always a string object */
+    PyObject *tag;      /* a string object or NULL */
+    PyObject *anchor;   /* a string object or NULL */
+    /* Scalar-specific fields: */
+    enum scalar_style style;
+    int indent;
+    int width;
+    char chomp;
+} PySyckScalarObject;
+
+static PyObject *
+PySyckScalar_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    PySyckScalarObject *self;
+
+    self = (PySyckScalarObject *)type->tp_alloc(type, 0);
+    if (!self) return NULL;
+
+    self->value = PyString_FromString("");
+    if (!self->value) {
+        Py_DECREF(self);
+        return NULL;
+    }
+
+    self->tag = NULL;
+    self->anchor = NULL;
+    self->style = scalar_none;
+    self->indent = 0;
+    self->width = 0;
+    self->chomp = 0;
+
+    return (PyObject *)self;
+}
+
+static int
+PySyckScalar_setvalue(PySyckScalarObject *self, PyObject *value, void *closure)
+{
+    if (!value) {
+        PyErr_SetString(PyExc_TypeError, "cannot delete 'value'");
+        return -1;
+    }
+    if (!PyString_Check(value)) {
+        PyErr_SetString(PyExc_TypeError, "'value' must be a string");
+        return -1;
+    }
+
+    Py_DECREF(self->value);
+    Py_INCREF(value);
+    self->value = value;
+
+    return 0;
+}
+
+static PyObject *
+PySyckScalar_getstyle(PySyckScalarObject *self, void *closure)
+{
+    PyObject *value;
+
+    switch (self->style) {
+        case scalar_1quote: value = PySyck_1QuoteStyle; break;
+        case scalar_2quote: value = PySyck_2QuoteStyle; break;
+        case scalar_fold: value = PySyck_FoldStyle; break;
+        case scalar_literal: value = PySyck_LiteralStyle; break;
+        case scalar_plain: value = PySyck_PlainStyle; break;
+        default: value = Py_None;
+    }
+
+    Py_INCREF(value);
+    return value;
+}
+
+static int
+PySyckScalar_setstyle(PySyckScalarObject *self, PyObject *value, void *closure)
+{
+    char *str;
+
+    if (!value) {
+        PyErr_SetString(PyExc_TypeError, "cannot delete 'style'");
+        return -1;
+    }
+
+    if (value == Py_None) {
+        self->style = scalar_none;
+        return 0;
+    }
+
+    if (!PyString_Check(value)) {
+        PyErr_SetString(PyExc_TypeError, "'style' must be a string or None");
+        return -1;
+    }
+
+    str = PyString_AsString(value);
+    if (!str) return -1;
+
+    if (strcmp(str, "1quote") == 0)
+        self->style = scalar_1quote;
+    else if (strcmp(str, "2quote") == 0)
+        self->style = scalar_2quote;
+    else if (strcmp(str, "fold") == 0)
+        self->style = scalar_fold;
+    else if (strcmp(str, "literal") == 0)
+        self->style = scalar_literal;
+    else if (strcmp(str, "plain") == 0)
+        self->style = scalar_plain;
+    else {
+        PyErr_SetString(PyExc_ValueError, "unknown 'style'");
+        return -1;
+    }
+
+    return 0;
+}
+
+static PyObject *
+PySyckScalar_getindent(PySyckScalarObject *self, void *closure)
+{
+    return PyInt_FromLong(self->indent);
+}
+
+static int
+PySyckScalar_setindent(PySyckScalarObject *self, PyObject *value, void *closure)
+{
+    if (!value) {
+        PyErr_SetString(PyExc_TypeError, "cannot delete 'indent'");
+        return -1;
+    }
+
+    if (!PyInt_Check(value)) {
+        PyErr_SetString(PyExc_TypeError, "'indent' must be an integer");
+        return -1;
+    }
+
+    self->indent = PyInt_AS_LONG(value);
+
+    return 0;
+}
+
+static PyObject *
+PySyckScalar_getwidth(PySyckScalarObject *self, void *closure)
+{
+    return PyInt_FromLong(self->width);
+}
+
+static int
+PySyckScalar_setwidth(PySyckScalarObject *self, PyObject *value, void *closure)
+{
+    if (!value) {
+        PyErr_SetString(PyExc_TypeError, "cannot delete 'width'");
+        return -1;
+    }
+
+    if (!PyInt_Check(value)) {
+        PyErr_SetString(PyExc_TypeError, "'width' must be an integer");
+        return -1;
+    }
+
+    self->width = PyInt_AS_LONG(value);
+
+    return 0;
+}
+
+static PyObject *
+PySyckScalar_getchomp(PySyckScalarObject *self, void *closure)
+{
+    PyObject *value;
+
+    switch (self->chomp) {
+        case NL_CHOMP: value = PySyck_StripChomp; break;
+        case NL_KEEP: value = PySyck_KeepChomp; break;
+        default: value = Py_None;
+    }
+
+    Py_INCREF(value);
+    return value;
+}
+
+static int
+PySyckScalar_setchomp(PySyckScalarObject *self, PyObject *value, void *closure)
+{
+    char *str;
+
+    if (!value) {
+        PyErr_SetString(PyExc_TypeError, "cannot delete 'chomp'");
+        return -1;
+    }
+
+    if (value == Py_None) {
+        self->chomp = 0;
+        return 0;
+    }
+
+    if (!PyString_Check(value)) {
+        PyErr_SetString(PyExc_TypeError, "'chomp' must be '+', '-', or None");
+        return -1;
+    }
+
+    str = PyString_AsString(value);
+    if (!str) return -1;
+
+    if (strcmp(str, "-") == 0)
+        self->chomp = NL_CHOMP;
+    else if (strcmp(str, "+") == 0)
+        self->chomp = NL_KEEP;
+    else {
+        PyErr_SetString(PyExc_TypeError, "'chomp' must be '+', '-', or None");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int
+PySyckScalar_init(PySyckScalarObject *self, PyObject *args, PyObject *kwds)
+{
+    PyObject *value = NULL;
+    PyObject *tag = NULL;
+    PyObject *anchor = NULL;
+    PyObject *style = NULL;
+    PyObject *indent = NULL;
+    PyObject *width = NULL;
+    PyObject *chomp = NULL;
+
+    static char *kwdlist[] = {"value", "tag", "anchor",
+        "style", "indent", "width", "chomp", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOOOO", kwdlist,
+                &value, &tag, &anchor, &style, &indent, &width, &chomp))
+        return -1;
+
+    if (value && PySyckScalar_setvalue(self, value, NULL) < 0)
+        return -1;
+
+    if (tag && PySyckNode_settag((PySyckNodeObject *)self, tag, NULL) < 0)
+        return -1;
+
+    if (anchor && PySyckNode_setanchor((PySyckNodeObject *)self, anchor, NULL) < 0)
+        return -1;
+
+    if (style && PySyckScalar_setstyle(self, style, NULL) < 0)
+        return -1;
+
+    if (indent && PySyckScalar_setindent(self, indent, NULL) < 0)
+        return -1;
+
+    if (width && PySyckScalar_setwidth(self, width, NULL) < 0)
+        return -1;
+
+    if (chomp && PySyckScalar_setchomp(self, chomp, NULL) < 0)
+        return -1;
+
+    return 0;
+}
+
+static PyGetSetDef PySyckScalar_getsetters[] = {
+    {"kind", (getter)PySyckNode_getkind, NULL,
+        PyDoc_STR("the node kind, always 'scalar', read-only"),
+        &PySyck_ScalarKind},
+    {"value", (getter)PySyckNode_getvalue, (setter)PySyckScalar_setvalue,
+        PyDoc_STR("the node value, a string"), NULL},
+    {"tag", (getter)PySyckNode_gettag, (setter)PySyckNode_settag,
+        PyDoc_STR("the node tag, a string or None"), NULL},
+    {"anchor", (getter)PySyckNode_getanchor, (setter)PySyckNode_setanchor,
+        PyDoc_STR("the node anchor, a string or None"), NULL},
+    {"style", (getter)PySyckScalar_getstyle, (setter)PySyckScalar_setstyle,
+        PyDoc_STR("the node style, values: None (means literal or plain),\n"
+            "'1quote', '2quote', 'fold', 'literal', 'plain'"), NULL},
+    {"indent", (getter)PySyckScalar_getindent, (setter)PySyckScalar_setindent,
+        PyDoc_STR("the node indentation, an integer"), NULL},
+    {"width", (getter)PySyckScalar_getwidth, (setter)PySyckScalar_setwidth,
+        PyDoc_STR("the node width, an integer"), NULL},
+    {"chomp", (getter)PySyckScalar_getchomp, (setter)PySyckScalar_setchomp,
+        PyDoc_STR("the chomping method,\n"
+            "values: None (clip), '-' (strip), or '+' (keep)"), NULL},
+    {NULL}  /* Sentinel */
+};
+
+static PyTypeObject PySyckScalar_Type = {
+    PyObject_HEAD_INIT(NULL)
+    0,                                          /* ob_size */
+    "_syck.Scalar",                             /* tp_name */
+    sizeof(PySyckScalarObject),                 /* tp_basicsize */
+    0,                                          /* tp_itemsize */
+    0,                                          /* tp_dealloc */
+    0,                                          /* tp_print */
+    0,                                          /* tp_getattr */
+    0,                                          /* tp_setattr */
+    0,                                          /* tp_compare */
+    0,                                          /* tp_repr */
+    0,                                          /* tp_as_number */
+    0,                                          /* tp_as_sequence */
+    0,                                          /* tp_as_mapping */
+    0,                                          /* tp_hash */
+    0,                                          /* tp_call */
+    0,                                          /* tp_str */
+    0,                                          /* tp_getattro */
+    0,                                          /* tp_setattro */
+    0,                                          /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,     /* tp_flags */
+    PySyckScalar_doc,                           /* tp_doc */
+    0,                                          /* tp_traverse */
+    0,                                          /* tp_clear */
+    0,                                          /* tp_richcompare */
+    0,                                          /* tp_weaklistoffset */
+    0,                                          /* tp_iter */
+    0,                                          /* tp_iternext */
+    0,                                          /* tp_methods */
+    0,                                          /* tp_members */
+    PySyckScalar_getsetters,                    /* tp_getset */
+    &PySyckNode_Type,                           /* tp_base */
+    0,                                          /* tp_dict */
+    0,                                          /* tp_descr_get */
+    0,                                          /* tp_descr_set */
+    0,                                          /* tp_dictoffset */
+    (initproc)PySyckScalar_init,                /* tp_init */
+    0,                                          /* tp_alloc */
+    PySyckScalar_new,                           /* tp_new */
+};
+
+/****************************************************************************
+ * The type _syck.Seq.
+ ****************************************************************************/
+
+PyDoc_STRVAR(PySyckSeq_doc,
+    "Seq(value=[], tag=None, inline=False) -> a Seq node\n\n"
+    "_syck.Seq represents a sequence node in Syck parser and emitter\n"
+    "trees. A sequence node points to an ordered set of subnodes.\n");
+
+typedef struct {
+    PyObject_HEAD
+    /* Common fields for all Node types: */
+    PyObject *value;    /* always an object */
+    PyObject *tag;      /* a string object or NULL */
+    PyObject *anchor;   /* a string object or NULL */
+    /* Seq-specific fields: */
+    enum seq_style style;
+} PySyckSeqObject;
+
+static PyObject *
+PySyckSeq_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    PySyckSeqObject *self;
+
+    self = (PySyckSeqObject *)type->tp_alloc(type, 0);
+    if (!self) return NULL;
+
+    self->value = PyList_New(0);
+    if (!self->value) {
+        Py_DECREF(self);
+        return NULL;
+    }
+
+    self->tag = NULL;
+    self->anchor = NULL;
+    self->style = seq_none;
+
+    return (PyObject *)self;
+}
+
+static int
+PySyckSeq_setvalue(PySyckSeqObject *self, PyObject *value, void *closure)
+{
+    if (!value) {
+        PyErr_SetString(PyExc_TypeError, "cannot delete 'value'");
+        return -1;
+    }
+    if (!PyList_Check(value)) {
+        PyErr_SetString(PyExc_TypeError, "'value' must be a list");
+        return -1;
+    }
+
+    Py_DECREF(self->value);
+    Py_INCREF(value);
+    self->value = value;
+
+    return 0;
+}
+
+static PyObject *
+PySyckSeq_getinline(PySyckSeqObject *self, void *closure)
+{
+    PyObject *value = (self->style == seq_inline) ? Py_True : Py_False;
+
+    Py_INCREF(value);
+    return value;
+}
+
+static int
+PySyckSeq_setinline(PySyckSeqObject *self, PyObject *value, void *closure)
+{
+    if (!value) {
+        PyErr_SetString(PyExc_TypeError, "cannot delete 'inline'");
+        return -1;
+    }
+
+    if (!PyInt_Check(value)) {
+        PyErr_SetString(PyExc_TypeError, "'inline' must be a Boolean object");
+        return -1;
+    }
+
+    self->style = PyInt_AS_LONG(value) ? seq_inline : seq_none;
+
+    return 0;
+}
+
+static int
+PySyckSeq_init(PySyckSeqObject *self, PyObject *args, PyObject *kwds)
+{
+    PyObject *value = NULL;
+    PyObject *tag = NULL;
+    PyObject *anchor = NULL;
+    PyObject *inline_ = NULL;
+
+    static char *kwdlist[] = {"value", "tag", "anchor", "inline", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwdlist,
+                &value, &tag, &anchor, &inline_))
+        return -1;
+
+    if (value && PySyckSeq_setvalue(self, value, NULL) < 0)
+        return -1;
+
+    if (tag && PySyckNode_settag((PySyckNodeObject *)self, tag, NULL) < 0)
+        return -1;
+
+    if (anchor && PySyckNode_setanchor((PySyckNodeObject *)self, anchor, NULL) < 0)
+        return -1;
+
+    if (inline_ && PySyckSeq_setinline(self, inline_, NULL) < 0)
+        return -1;
+
+    return 0;
+}
+
+static PyGetSetDef PySyckSeq_getsetters[] = {
+    {"kind", (getter)PySyckNode_getkind, NULL,
+        PyDoc_STR("the node kind, always 'seq', read-only"), &PySyck_SeqKind},
+    {"value", (getter)PySyckNode_getvalue, (setter)PySyckSeq_setvalue,
+        PyDoc_STR("the node value, a sequence"), NULL},
+    {"tag", (getter)PySyckNode_gettag, (setter)PySyckNode_settag,
+        PyDoc_STR("the node tag, a string or None"), NULL},
+    {"anchor", (getter)PySyckNode_getanchor, (setter)PySyckNode_setanchor,
+        PyDoc_STR("the node anchor, a string or None"), NULL},
+    {"inline", (getter)PySyckSeq_getinline, (setter)PySyckSeq_setinline,
+        PyDoc_STR("the block/flow flag"), NULL},
+    {NULL}  /* Sentinel */
+};
+
+static PyTypeObject PySyckSeq_Type = {
+    PyObject_HEAD_INIT(NULL)
+    0,                                          /* ob_size */
+    "_syck.Seq",                                /* tp_name */
+    sizeof(PySyckSeqObject),                    /* tp_basicsize */
+    0,                                          /* tp_itemsize */
+    0,                                          /* tp_dealloc */
+    0,                                          /* tp_print */
+    0,                                          /* tp_getattr */
+    0,                                          /* tp_setattr */
+    0,                                          /* tp_compare */
+    0,                                          /* tp_repr */
+    0,                                          /* tp_as_number */
+    0,                                          /* tp_as_sequence */
+    0,                                          /* tp_as_mapping */
+    0,                                          /* tp_hash */
+    0,                                          /* tp_call */
+    0,                                          /* tp_str */
+    0,                                          /* tp_getattro */
+    0,                                          /* tp_setattro */
+    0,                                          /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,  /* tp_flags */
+    PySyckSeq_doc,                              /* tp_doc */
+    (traverseproc)PySyckNode_traverse,          /* tp_traverse */
+    (inquiry)PySyckNode_clear,                  /* tp_clear */
+    0,                                          /* tp_richcompare */
+    0,                                          /* tp_weaklistoffset */
+    0,                                          /* tp_iter */
+    0,                                          /* tp_iternext */
+    0,                                          /* tp_methods */
+    0,                                          /* tp_members */
+    PySyckSeq_getsetters,                       /* tp_getset */
+    &PySyckNode_Type,                           /* tp_base */
+    0,                                          /* tp_dict */
+    0,                                          /* tp_descr_get */
+    0,                                          /* tp_descr_set */
+    0,                                          /* tp_dictoffset */
+    (initproc)PySyckSeq_init,                   /* tp_init */
+    0,                                          /* tp_alloc */
+    PySyckSeq_new,                              /* tp_new */
+};
+
+/****************************************************************************
+ * The type _syck.Map.
+ ****************************************************************************/
+
+PyDoc_STRVAR(PySyckMap_doc,
+    "Map(value={}, tag=None, inline=False) -> a Map node\n\n"
+    "_syck.Map represents a mapping node in Syck parser and emitter\n"
+    "trees. A mapping node points to an unordered collections of pairs.\n");
+
+typedef struct {
+    PyObject_HEAD
+    /* Common fields for all Node types: */
+    PyObject *value;    /* always an object */
+    PyObject *tag;      /* a string object or NULL */
+    PyObject *anchor;   /* a string object or NULL */
+    /* Map-specific fields: */
+    enum map_style style;
+} PySyckMapObject;
+
+static PyObject *
+PySyckMap_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    PySyckMapObject *self;
+
+    self = (PySyckMapObject *)type->tp_alloc(type, 0);
+    if (!self) return NULL;
+
+    self->value = PyDict_New();
+    if (!self->value) {
+        Py_DECREF(self);
+        return NULL;
+    }
+
+    self->tag = NULL;
+    self->anchor = NULL;
+    self->style = seq_none;
+
+    return (PyObject *)self;
+}
+
+static int
+PySyckMap_setvalue(PySyckMapObject *self, PyObject *value, void *closure)
+{
+    if (!value) {
+        PyErr_SetString(PyExc_TypeError, "cannot delete 'value'");
+        return -1;
+    }
+    if (!PyDict_Check(value) && !PyList_Check(value)) {
+        PyErr_SetString(PyExc_TypeError,
+                "'value' must be a list of pairs or a dictionary");
+        return -1;
+    }
+
+    Py_DECREF(self->value);
+    Py_INCREF(value);
+    self->value = value;
+
+    return 0;
+}
+
+static PyObject *
+PySyckMap_getinline(PySyckMapObject *self, void *closure)
+{
+    PyObject *value = (self->style == map_inline) ? Py_True : Py_False;
+
+    Py_INCREF(value);
+    return value;
+}
+
+static int
+PySyckMap_setinline(PySyckMapObject *self, PyObject *value, void *closure)
+{
+    if (!value) {
+        PyErr_SetString(PyExc_TypeError, "cannot delete 'inline'");
+        return -1;
+    }
+
+    if (!PyInt_Check(value)) {
+        PyErr_SetString(PyExc_TypeError, "'inline' must be a Boolean object");
+        return -1;
+    }
+
+    self->style = PyInt_AS_LONG(value) ? map_inline : map_none;
+
+    return 0;
+}
+
+static int
+PySyckMap_init(PySyckMapObject *self, PyObject *args, PyObject *kwds)
+{
+    PyObject *value = NULL;
+    PyObject *tag = NULL;
+    PyObject *anchor = NULL;
+    PyObject *inline_ = NULL;
+
+    static char *kwdlist[] = {"value", "tag", "anchor", "inline", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwdlist,
+                &value, &tag, &anchor, &inline_))
+        return -1;
+
+    if (value && PySyckMap_setvalue(self, value, NULL) < 0)
+        return -1;
+
+    if (tag && PySyckNode_settag((PySyckNodeObject *)self, tag, NULL) < 0)
+        return -1;
+
+    if (anchor && PySyckNode_setanchor((PySyckNodeObject *)self, anchor, NULL) < 0)
+        return -1;
+
+    if (inline_ && PySyckMap_setinline(self, inline_, NULL) < 0)
+        return -1;
+
+    return 0;
+}
+
+static PyGetSetDef PySyckMap_getsetters[] = {
+    {"kind", (getter)PySyckNode_getkind, NULL,
+        PyDoc_STR("the node kind, always 'map', read-only"), &PySyck_MapKind},
+    {"value", (getter)PySyckNode_getvalue, (setter)PySyckMap_setvalue,
+        PyDoc_STR("the node value, a list of pairs or a dictionary"), NULL},
+    {"tag", (getter)PySyckNode_gettag, (setter)PySyckNode_settag,
+        PyDoc_STR("the node tag, a string or None"), NULL},
+    {"anchor", (getter)PySyckNode_getanchor, (setter)PySyckNode_setanchor,
+        PyDoc_STR("the node anchor, a string or None"), NULL},
+    {"inline", (getter)PySyckMap_getinline, (setter)PySyckMap_setinline,
+        PyDoc_STR("the block/flow flag"), NULL},
+    {NULL}  /* Sentinel */
+};
+
+static PyTypeObject PySyckMap_Type = {
+    PyObject_HEAD_INIT(NULL)
+    0,                                          /* ob_size */
+    "_syck.Map",                                /* tp_name */
+    sizeof(PySyckMapObject),                    /* tp_basicsize */
+    0,                                          /* tp_itemsize */
+    0,                                          /* tp_dealloc */
+    0,                                          /* tp_print */
+    0,                                          /* tp_getattr */
+    0,                                          /* tp_setattr */
+    0,                                          /* tp_compare */
+    0,                                          /* tp_repr */
+    0,                                          /* tp_as_number */
+    0,                                          /* tp_as_sequence */
+    0,                                          /* tp_as_mapping */
+    0,                                          /* tp_hash */
+    0,                                          /* tp_call */
+    0,                                          /* tp_str */
+    0,                                          /* tp_getattro */
+    0,                                          /* tp_setattro */
+    0,                                          /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,  /* tp_flags */
+    PySyckMap_doc,                              /* tp_doc */
+    (traverseproc)PySyckNode_traverse,          /* tp_traverse */
+    (inquiry)PySyckNode_clear,                  /* tp_clear */
+    0,                                          /* tp_richcompare */
+    0,                                          /* tp_weaklistoffset */
+    0,                                          /* tp_iter */
+    0,                                          /* tp_iternext */
+    0,                                          /* tp_methods */
+    0,                                          /* tp_members */
+    PySyckMap_getsetters,                       /* tp_getset */
+    &PySyckNode_Type,                           /* tp_base */
+    0,                                          /* tp_dict */
+    0,                                          /* tp_descr_get */
+    0,                                          /* tp_descr_set */
+    0,                                          /* tp_dictoffset */
+    (initproc)PySyckMap_init,                   /* tp_init */
+    0,                                          /* tp_alloc */
+    PySyckMap_new,                              /* tp_new */
+};
+
+/****************************************************************************
+ * The type _syck.Parser.
+ ****************************************************************************/
+
+PyDoc_STRVAR(PySyckParser_doc,
+    "Parser(source, implicit_typing=True, taguri_expansion=True)\n"
+    "      -> a Parser object\n\n"
+    "_syck.Parser is a low-lever wrapper of the Syck parser. It parses\n"
+    "a YAML stream and produces a tree of Nodes.\n");
+
+typedef struct {
+    PyObject_HEAD
+    /* Attributes: */
+    PyObject *source;       /* a string or file-like object */
+    int implicit_typing;
+    int taguri_expansion;
+    /* Internal fields: */
+    PyObject *symbols;      /* symbol table, a list, NULL outside parse() */
+    SyckParser *parser;
+    int parsing;
+    int halt;
+} PySyckParserObject;
+
+static PyObject *
+PySyckParser_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    PySyckParserObject *self;
+
+    self = (PySyckParserObject *)type->tp_alloc(type, 0);
+    if (!self) return NULL;
+
+    self->source = NULL;
+    self->implicit_typing = 0;
+    self->taguri_expansion = 0;
+    self->symbols = NULL;
+    self->parser = NULL;
+    self->parsing = 0;
+    self->halt = 1;
+
+    /*
+    self->symbols = PyList_New(0);
+    if (!self->symbols) {
+        Py_DECREF(self);
+        return NULL;
+    }
+    */
+
+    return (PyObject *)self;
+}
+
+static int
+PySyckParser_clear(PySyckParserObject *self)
+{
+    PyObject *tmp;
+
+    if (self->parser) {
+        syck_free_parser(self->parser);
+        self->parser = NULL;
+    }
+
+    tmp = self->source;
+    self->source = NULL;
+    Py_XDECREF(tmp);
+
+    tmp = self->symbols;
+    self->symbols = NULL;
+    Py_XDECREF(tmp);
+
+    return 0;
+}
+
+static int
+PySyckParser_traverse(PySyckParserObject *self, visitproc visit, void *arg)
+{
+    int ret;
+
+    if (self->source)
+        if ((ret = visit(self->source, arg)) != 0)
+            return ret;
+
+    if (self->symbols)
+        if ((ret = visit(self->symbols, arg)) != 0)
+            return ret;
+
+    return 0;
+}
+
+static void
+PySyckParser_dealloc(PySyckParserObject *self)
+{
+    PySyckParser_clear(self);
+    self->ob_type->tp_free((PyObject *)self);
+}
+
+static PyObject *
+PySyckParser_getsource(PySyckParserObject *self, void *closure)
+{
+    PyObject *value = self->source ? self->source : Py_None;
+
+    Py_INCREF(value);
+    return value;
+}
+
+static PyObject *
+PySyckParser_getimplicit_typing(PySyckParserObject *self, void *closure)
+{
+    PyObject *value = self->implicit_typing ? Py_True : Py_False;
+
+    Py_INCREF(value);
+    return value;
+}
+
+static PyObject *
+PySyckParser_gettaguri_expansion(PySyckParserObject *self, void *closure)
+{
+    PyObject *value = self->taguri_expansion ? Py_True : Py_False;
+
+    Py_INCREF(value);
+    return value;
+}
+
+static PyObject *
+PySyckParser_geteof(PySyckParserObject *self, void *closure)
+{
+    PyObject *value = self->halt ? Py_True : Py_False;
+
+    Py_INCREF(value);
+    return value;
+}
+
+static PyGetSetDef PySyckParser_getsetters[] = {
+    {"source", (getter)PySyckParser_getsource, NULL,
+        PyDoc_STR("IO source, a string or a file-like object"), NULL},
+    {"implicit_typing", (getter)PySyckParser_getimplicit_typing, NULL,
+        PyDoc_STR("implicit typing of builtin YAML types"), NULL},
+    {"taguri_expansion", (getter)PySyckParser_gettaguri_expansion, NULL,
+        PyDoc_STR("expansion of types in full taguri"), NULL},
+    {"eof", (getter)PySyckParser_geteof, NULL,
+        PyDoc_STR("EOF flag"), NULL},
+    {NULL}  /* Sentinel */
+};
+
+static SYMID
+PySyckParser_node_handler(SyckParser *parser, SyckNode *node)
+{
+    PyGILState_STATE gs;
+
+    PySyckParserObject *self = (PySyckParserObject *)parser->bonus;
+
+    SYMID index;
+    PySyckNodeObject *object = NULL;
+
+    PyObject *key, *value;
+    int k;
+
+    if (self->halt)
+        return -1;
+
+    gs = PyGILState_Ensure();
+
+    switch (node->kind) {
+
+        case syck_str_kind:
+            object = (PySyckNodeObject *)
+                PySyckScalar_new(&PySyckScalar_Type, NULL, NULL);
+            if (!object) goto error;
+            value = PyString_FromStringAndSize(node->data.str->ptr,
+                    node->data.str->len);
+            if (!value) goto error;
+            Py_DECREF(object->value);
+            object->value = value;
+            break;
+
+        case syck_seq_kind:
+            object = (PySyckNodeObject *)
+                PySyckSeq_new(&PySyckSeq_Type, NULL, NULL);
+            if (!object) goto error;
+            for (k = 0; k < node->data.list->idx; k++) {
+                index = syck_seq_read(node, k)-1;
+                value = PyList_GetItem(self->symbols, index);
+                if (!value) goto error;
+                if (PyList_Append(object->value, value) < 0)
+                    goto error;
+            }
+            break;
+
+        case syck_map_kind:
+            object = (PySyckNodeObject *)
+                PySyckMap_new(&PySyckMap_Type, NULL, NULL);
+            if (!object) goto error;
+            for (k = 0; k < node->data.pairs->idx; k++)
+            {
+                index = syck_map_read(node, map_key, k)-1;
+                key = PyList_GetItem(self->symbols, index);
+                if (!key) goto error;
+                index = syck_map_read(node, map_value, k)-1;
+                value = PyList_GetItem(self->symbols, index);
+                if (!value) goto error;
+                if (PyDict_SetItem(object->value, key, value) < 0)
+                    goto error;
+            }
+            break;
+    }
+
+    if (node->type_id) {
+        object->tag = PyString_FromString(node->type_id);
+        if (!object->tag) goto error;
+    }
+
+    if (node->anchor) {
+        object->anchor = PyString_FromString(node->anchor);
+        if (!object->anchor) goto error;
+    }
+
+    if (PyList_Append(self->symbols, (PyObject *)object) < 0)
+        goto error;
+
+    index = PyList_GET_SIZE(self->symbols);
+    PyGILState_Release(gs);
+    return index;
+
+error:
+    Py_XDECREF(object);
+    PyGILState_Release(gs);
+    self->halt = 1;
+    return -1;
+}
+
+static void
+PySyckParser_error_handler(SyckParser *parser, char *str)
+{
+    PyGILState_STATE gs;
+
+    PySyckParserObject *self = (PySyckParserObject *)parser->bonus;
+    PyObject *value;
+
+    if (self->halt) return;
+
+    gs = PyGILState_Ensure();
+
+    self->halt = 1;
+
+    value = Py_BuildValue("(sii)", str,
+            parser->linect, parser->cursor - parser->lineptr);
+    if (value) {
+        PyErr_SetObject(PySyck_Error, value);
+    }
+
+    PyGILState_Release(gs);
+}
+
+SyckNode *
+PySyckParser_bad_anchor_handler(SyckParser *parser, char *anchor)
+{
+    PyGILState_STATE gs;
+
+    PySyckParserObject *self = (PySyckParserObject *)parser->bonus;
+
+    if (!self->halt) {
+        gs = PyGILState_Ensure();
+
+        self->halt = 1;
+        PyErr_SetString(PyExc_TypeError, "recursive anchors are not implemented");
+
+        PyGILState_Release(gs);
+    }
+
+    return syck_alloc_str();
+}
+
+static long
+PySyckParser_read_handler(char *buf, SyckIoFile *file, long max_size, long skip)
+{
+    PyGILState_STATE gs;
+
+    PySyckParserObject *self = (PySyckParserObject *)file->ptr;
+
+    PyObject *value;
+
+    char *str;
+    int length;
+
+    buf[skip] = '\0';
+
+    if (self->halt) {
+        return skip;
+    }
+    
+    max_size -= skip;
+
+    gs = PyGILState_Ensure();
+
+    value = PyObject_CallMethod(self->source, "read", "(i)", max_size);
+    if (!value) {
+        self->halt = 1;
+
+        PyGILState_Release(gs);
+
+        return skip;
+    }
+
+    if (!PyString_CheckExact(value)) {
+        Py_DECREF(value);
+        PyErr_SetString(PyExc_TypeError, "file-like object should return a string");
+        self->halt = 1;
+        
+        PyGILState_Release(gs);
+
+        return skip;
+    }
+
+    str = PyString_AS_STRING(value);
+    length = PyString_GET_SIZE(value);
+    if (!length) {
+        Py_DECREF(value);
+
+        PyGILState_Release(gs);
+
+        return skip;
+    }
+
+    if (length > max_size) {
+        Py_DECREF(value);
+        PyErr_SetString(PyExc_ValueError, "read returns an overly long string");
+        self->halt = 1;
+
+        PyGILState_Release(gs);
+
+        return skip;
+    }
+
+    memcpy(buf+skip, str, length);
+    length += skip;
+    buf[length] = '\0';
+
+    Py_DECREF(value);
+
+    PyGILState_Release(gs);
+
+    return length;
+}
+
+static int
+PySyckParser_init(PySyckParserObject *self, PyObject *args, PyObject *kwds)
+{
+    PyObject *source = NULL;
+    int implicit_typing = 1;
+    int taguri_expansion = 1;
+
+    static char *kwdlist[] = {"source", "implicit_typing", "taguri_expansion",
+        NULL};
+
+    PySyckParser_clear(self);
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|ii", kwdlist,
+                &source, &implicit_typing, &taguri_expansion))
+        return -1;
+
+    Py_INCREF(source);
+    self->source = source;
+
+    self->implicit_typing = implicit_typing;
+    self->taguri_expansion = taguri_expansion;
+
+    self->parser = syck_new_parser();
+    self->parser->bonus = self;
+
+    if (PyString_CheckExact(self->source)) {
+        syck_parser_str(self->parser,
+                PyString_AS_STRING(self->source),
+                PyString_GET_SIZE(self->source), NULL);
+    }
+    /*
+    else if (PyUnicode_CheckExact(self->source)) {
+        syck_parser_str(self->parser,
+                PyUnicode_AS_DATA(self->source),
+                PyString_GET_DATA_SIZE(self->source), NULL);
+    }
+    */
+    else {
+        syck_parser_file(self->parser, (FILE *)self, PySyckParser_read_handler);
+    }
+
+    syck_parser_implicit_typing(self->parser, self->implicit_typing);
+    syck_parser_taguri_expansion(self->parser, self->taguri_expansion);
+
+    syck_parser_handler(self->parser, PySyckParser_node_handler);
+    syck_parser_error_handler(self->parser, PySyckParser_error_handler);
+    syck_parser_bad_anchor_handler(self->parser, PySyckParser_bad_anchor_handler);
+
+    self->parsing = 0;
+    self->halt = 0;
+
+    return 0;
+}
+
+static PyObject *
+PySyckParser_parse(PySyckParserObject *self)
+{
+    SYMID index;
+    PyObject *value;
+
+    if (self->parsing) {
+        PyErr_SetString(PyExc_RuntimeError,
+                "do not call Parser.parse while it is already running");
+        return NULL;
+    }
+
+    if (self->halt) {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+
+    self->symbols = PyList_New(0);
+    if (!self->symbols) {
+        return NULL;
+    }
+
+    self->parsing = 1;
+    Py_BEGIN_ALLOW_THREADS
+    index = syck_parse(self->parser)-1;
+    Py_END_ALLOW_THREADS
+    self->parsing = 0;
+
+    if (self->halt || self->parser->eof) {
+        Py_DECREF(self->symbols);
+        self->symbols = NULL;
+
+        if (self->halt) return NULL;
+
+        self->halt = 1;
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+
+    value = PyList_GetItem(self->symbols, index);
+
+    Py_DECREF(self->symbols);
+    self->symbols = NULL;
+
+    return value;
+}
+
+PyDoc_STRVAR(PySyckParser_parse_doc,
+    "parse() -> the root Node object\n\n"
+    "Parses the source and returns the root of the Node tree. Call it\n"
+    "several times to retrieve all documents from the source. On EOF,\n"
+    "returns None and sets the 'eof' attribute on.\n");
+
+static PyMethodDef PySyckParser_methods[] = {
+    {"parse",  (PyCFunction)PySyckParser_parse,
+        METH_NOARGS, PySyckParser_parse_doc},
+    {NULL}  /* Sentinel */
+};
+
+static PyTypeObject PySyckParser_Type = {
+    PyObject_HEAD_INIT(NULL)
+    0,                                          /* ob_size */
+    "_syck.Parser",                             /* tp_name */
+    sizeof(PySyckParserObject),                 /* tp_basicsize */
+    0,                                          /* tp_itemsize */
+    (destructor)PySyckParser_dealloc,           /* tp_dealloc */
+    0,                                          /* tp_print */
+    0,                                          /* tp_getattr */
+    0,                                          /* tp_setattr */
+    0,                                          /* tp_compare */
+    0,                                          /* tp_repr */
+    0,                                          /* tp_as_number */
+    0,                                          /* tp_as_sequence */
+    0,                                          /* tp_as_mapping */
+    0,                                          /* tp_hash */
+    0,                                          /* tp_call */
+    0,                                          /* tp_str */
+    0,                                          /* tp_getattro */
+    0,                                          /* tp_setattro */
+    0,                                          /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,  /* tp_flags */
+    PySyckParser_doc,                           /* tp_doc */
+    (traverseproc)PySyckParser_traverse,        /* tp_traverse */
+    (inquiry)PySyckParser_clear,                /* tp_clear */
+    0,                                          /* tp_richcompare */
+    0,                                          /* tp_weaklistoffset */
+    0,                                          /* tp_iter */
+    0,                                          /* tp_iternext */
+    PySyckParser_methods,                       /* tp_methods */
+    0,                                          /* tp_members */
+    PySyckParser_getsetters,                    /* tp_getset */
+    0,                                          /* tp_base */
+    0,                                          /* tp_dict */
+    0,                                          /* tp_descr_get */
+    0,                                          /* tp_descr_set */
+    0,                                          /* tp_dictoffset */
+    (initproc)PySyckParser_init,                /* tp_init */
+    0,                                          /* tp_alloc */