source: trunk/ext/_syckmodule.c @ 34

Revision 34, 67.5 KB checked in by xi, 9 years ago (diff)

Release the GIL before doing blocking calls (fix #35).
Note that this fix makes _syck incompatible with Python 2.2 and earlier.

Line 
1
2#include <Python.h>
3#include <syck.h>
4
5/****************************************************************************
6 * Python 2.2 compatibility.
7 ****************************************************************************/
8
9#ifndef PyDoc_STR
10#define PyDoc_VAR(name)         static char name[]
11#define PyDoc_STR(str)          (str)
12#define PyDoc_STRVAR(name, str) PyDoc_VAR(name) = PyDoc_STR(str)
13#endif
14
15#ifndef PyMODINIT_FUNC
16#define PyMODINIT_FUNC  void
17#endif
18
19/****************************************************************************
20 * Global objects: _syck.error, 'scalar', 'seq', 'map',
21 * '1quote', '2quote', 'fold', 'literal', 'plain', '+', '-'.
22 ****************************************************************************/
23
24static PyObject *PySyck_Error;
25
26static PyObject *PySyck_ScalarKind;
27static PyObject *PySyck_SeqKind;
28static PyObject *PySyck_MapKind;
29
30static PyObject *PySyck_1QuoteStyle;
31static PyObject *PySyck_2QuoteStyle;
32static PyObject *PySyck_FoldStyle;
33static PyObject *PySyck_LiteralStyle;
34static PyObject *PySyck_PlainStyle;
35
36static PyObject *PySyck_StripChomp;
37static PyObject *PySyck_KeepChomp;
38
39/****************************************************************************
40 * The type _syck.Node.
41 ****************************************************************************/
42
43PyDoc_STRVAR(PySyckNode_doc,
44    "_syck.Node() -> TypeError\n\n"
45    "_syck.Node is an abstract type. It is the base type for _syck.Scalar,\n"
46    "_syck.Seq, and _syck.Map. You cannot create an instance of _syck.Node\n"
47    "directly. You may use _syck.Node for type checking or subclassing.\n");
48
49typedef struct {
50    PyObject_HEAD
51    /* Common fields for all Node types: */
52    PyObject *value;    /* always an object */
53    PyObject *tag;      /* a string object or NULL */
54    PyObject *anchor;   /* a string object or NULL */
55} PySyckNodeObject;
56
57
58static int
59PySyckNode_clear(PySyckNodeObject *self)
60{
61    PyObject *tmp;
62
63    tmp = self->value;
64    self->value = NULL;
65    Py_XDECREF(tmp);
66
67    tmp = self->tag;
68    self->tag = NULL;
69    Py_XDECREF(tmp);
70
71    tmp = self->anchor;
72    self->value = NULL;
73    Py_XDECREF(tmp);
74
75    return 0;
76}
77
78static int
79PySyckNode_traverse(PySyckNodeObject *self, visitproc visit, void *arg)
80{
81    int ret;
82
83    if (self->value)
84        if ((ret = visit(self->value, arg)) != 0)
85            return ret;
86
87    if (self->tag)
88        if ((ret = visit(self->tag, arg)) != 0)
89            return ret;
90
91    if (self->anchor)
92        if ((ret = visit(self->anchor, arg)) != 0)
93            return ret;
94
95    return 0;
96}
97
98static void
99PySyckNode_dealloc(PySyckNodeObject *self)
100{
101    PySyckNode_clear(self);
102    self->ob_type->tp_free((PyObject *)self);
103}
104
105static PyObject *
106PySyckNode_getkind(PySyckNodeObject *self, PyObject **closure)
107{
108    Py_INCREF(*closure);
109    return *closure;
110}
111
112static PyObject *
113PySyckNode_getvalue(PySyckNodeObject *self, void *closure)
114{
115    Py_INCREF(self->value);
116    return self->value;
117}
118
119static PyObject *
120PySyckNode_gettag(PySyckNodeObject *self, void *closure)
121{
122    PyObject *value = self->tag ? self->tag : Py_None;
123    Py_INCREF(value);
124    return value;
125}
126
127static int
128PySyckNode_settag(PySyckNodeObject *self, PyObject *value, void *closure)
129{
130    if (!value) {
131        PyErr_SetString(PyExc_TypeError, "cannot delete 'tag'");
132        return -1;
133    }
134
135    if (value == Py_None) {
136        Py_XDECREF(self->tag);
137        self->tag = NULL;
138        return 0;
139    }
140
141    if (!PyString_Check(value)) {
142        PyErr_SetString(PyExc_TypeError, "'tag' must be a string");
143        return -1;
144    }
145
146    Py_XDECREF(self->tag);
147    Py_INCREF(value);
148    self->tag = value;
149
150    return 0;
151}
152
153static PyObject *
154PySyckNode_getanchor(PySyckNodeObject *self, void *closure)
155{
156    PyObject *value = self->anchor ? self->anchor : Py_None;
157    Py_INCREF(value);
158    return value;
159}
160
161static int
162PySyckNode_setanchor(PySyckNodeObject *self, PyObject *value, void *closure)
163{
164    if (!value) {
165        PyErr_SetString(PyExc_TypeError, "cannot delete 'anchor'");
166        return -1;
167    }
168
169    if (value == Py_None) {
170        Py_XDECREF(self->anchor);
171        self->anchor = NULL;
172        return 0;
173    }
174
175    if (!PyString_Check(value)) {
176        PyErr_SetString(PyExc_TypeError, "'anchor' must be a string");
177        return -1;
178    }
179
180    Py_XDECREF(self->anchor);
181    Py_INCREF(value);
182    self->anchor = value;
183
184    return 0;
185}
186
187static PyTypeObject PySyckNode_Type = {
188    PyObject_HEAD_INIT(NULL)
189    0,                                          /* ob_size */
190    "_syck.Node",                               /* tp_name */
191    sizeof(PySyckNodeObject),                   /* tp_basicsize */
192    0,                                          /* tp_itemsize */
193    (destructor)PySyckNode_dealloc,             /* tp_dealloc */
194    0,                                          /* tp_print */
195    0,                                          /* tp_getattr */
196    0,                                          /* tp_setattr */
197    0,                                          /* tp_compare */
198    0,                                          /* tp_repr */
199    0,                                          /* tp_as_number */
200    0,                                          /* tp_as_sequence */
201    0,                                          /* tp_as_mapping */
202    0,                                          /* tp_hash */
203    0,                                          /* tp_call */
204    0,                                          /* tp_str */
205    0,                                          /* tp_getattro */
206    0,                                          /* tp_setattro */
207    0,                                          /* tp_as_buffer */
208    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,  /* tp_flags */
209    PySyckNode_doc,                             /* tp_doc */
210    (traverseproc)PySyckNode_traverse,          /* tp_traverse */
211    (inquiry)PySyckNode_clear,                  /* tp_clear */
212};
213
214/****************************************************************************
215 * The type _syck.Scalar.
216 ****************************************************************************/
217
218PyDoc_STRVAR(PySyckScalar_doc,
219    "Scalar(value='', tag=None, style=None, indent=0, width=0, chomp=None)\n"
220    "      -> a Scalar node\n\n"
221    "_syck.Scalar represents a scalar node in Syck parser and emitter\n"
222    "trees. A scalar node points to a single string value.\n");
223
224typedef struct {
225    PyObject_HEAD
226    /* Common fields for all Node types: */
227    PyObject *value;    /* always a string object */
228    PyObject *tag;      /* a string object or NULL */
229    PyObject *anchor;   /* a string object or NULL */
230    /* Scalar-specific fields: */
231    enum scalar_style style;
232    int indent;
233    int width;
234    char chomp;
235} PySyckScalarObject;
236
237static PyObject *
238PySyckScalar_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
239{
240    PySyckScalarObject *self;
241
242    self = (PySyckScalarObject *)type->tp_alloc(type, 0);
243    if (!self) return NULL;
244
245    self->value = PyString_FromString("");
246    if (!self->value) {
247        Py_DECREF(self);
248        return NULL;
249    }
250
251    self->tag = NULL;
252    self->anchor = NULL;
253    self->style = scalar_none;
254    self->indent = 0;
255    self->width = 0;
256    self->chomp = 0;
257
258    return (PyObject *)self;
259}
260
261static int
262PySyckScalar_setvalue(PySyckScalarObject *self, PyObject *value, void *closure)
263{
264    if (!value) {
265        PyErr_SetString(PyExc_TypeError, "cannot delete 'value'");
266        return -1;
267    }
268    if (!PyString_Check(value)) {
269        PyErr_SetString(PyExc_TypeError, "'value' must be a string");
270        return -1;
271    }
272
273    Py_DECREF(self->value);
274    Py_INCREF(value);
275    self->value = value;
276
277    return 0;
278}
279
280static PyObject *
281PySyckScalar_getstyle(PySyckScalarObject *self, void *closure)
282{
283    PyObject *value;
284
285    switch (self->style) {
286        case scalar_1quote: value = PySyck_1QuoteStyle; break;
287        case scalar_2quote: value = PySyck_2QuoteStyle; break;
288        case scalar_fold: value = PySyck_FoldStyle; break;
289        case scalar_literal: value = PySyck_LiteralStyle; break;
290        case scalar_plain: value = PySyck_PlainStyle; break;
291        default: value = Py_None;
292    }
293
294    Py_INCREF(value);
295    return value;
296}
297
298static int
299PySyckScalar_setstyle(PySyckScalarObject *self, PyObject *value, void *closure)
300{
301    char *str;
302
303    if (!value) {
304        PyErr_SetString(PyExc_TypeError, "cannot delete 'style'");
305        return -1;
306    }
307
308    if (value == Py_None) {
309        self->style = scalar_none;
310        return 0;
311    }
312
313    if (!PyString_Check(value)) {
314        PyErr_SetString(PyExc_TypeError, "'style' must be a string or None");
315        return -1;
316    }
317
318    str = PyString_AsString(value);
319    if (!str) return -1;
320
321    if (strcmp(str, "1quote") == 0)
322        self->style = scalar_1quote;
323    else if (strcmp(str, "2quote") == 0)
324        self->style = scalar_2quote;
325    else if (strcmp(str, "fold") == 0)
326        self->style = scalar_fold;
327    else if (strcmp(str, "literal") == 0)
328        self->style = scalar_literal;
329    else if (strcmp(str, "plain") == 0)
330        self->style = scalar_plain;
331    else {
332        PyErr_SetString(PyExc_ValueError, "unknown 'style'");
333        return -1;
334    }
335
336    return 0;
337}
338
339static PyObject *
340PySyckScalar_getindent(PySyckScalarObject *self, void *closure)
341{
342    return PyInt_FromLong(self->indent);
343}
344
345static int
346PySyckScalar_setindent(PySyckScalarObject *self, PyObject *value, void *closure)
347{
348    if (!value) {
349        PyErr_SetString(PyExc_TypeError, "cannot delete 'indent'");
350        return -1;
351    }
352
353    if (!PyInt_Check(value)) {
354        PyErr_SetString(PyExc_TypeError, "'indent' must be an integer");
355        return -1;
356    }
357
358    self->indent = PyInt_AS_LONG(value);
359
360    return 0;
361}
362
363static PyObject *
364PySyckScalar_getwidth(PySyckScalarObject *self, void *closure)
365{
366    return PyInt_FromLong(self->width);
367}
368
369static int
370PySyckScalar_setwidth(PySyckScalarObject *self, PyObject *value, void *closure)
371{
372    if (!value) {
373        PyErr_SetString(PyExc_TypeError, "cannot delete 'width'");
374        return -1;
375    }
376
377    if (!PyInt_Check(value)) {
378        PyErr_SetString(PyExc_TypeError, "'width' must be an integer");
379        return -1;
380    }
381
382    self->width = PyInt_AS_LONG(value);
383
384    return 0;
385}
386
387static PyObject *
388PySyckScalar_getchomp(PySyckScalarObject *self, void *closure)
389{
390    PyObject *value;
391
392    switch (self->chomp) {
393        case NL_CHOMP: value = PySyck_StripChomp; break;
394        case NL_KEEP: value = PySyck_KeepChomp; break;
395        default: value = Py_None;
396    }
397
398    Py_INCREF(value);
399    return value;
400}
401
402static int
403PySyckScalar_setchomp(PySyckScalarObject *self, PyObject *value, void *closure)
404{
405    char *str;
406
407    if (!value) {
408        PyErr_SetString(PyExc_TypeError, "cannot delete 'chomp'");
409        return -1;
410    }
411
412    if (value == Py_None) {
413        self->chomp = 0;
414        return 0;
415    }
416
417    if (!PyString_Check(value)) {
418        PyErr_SetString(PyExc_TypeError, "'chomp' must be '+', '-', or None");
419        return -1;
420    }
421
422    str = PyString_AsString(value);
423    if (!str) return -1;
424
425    if (strcmp(str, "-") == 0)
426        self->chomp = NL_CHOMP;
427    else if (strcmp(str, "+") == 0)
428        self->chomp = NL_KEEP;
429    else {
430        PyErr_SetString(PyExc_TypeError, "'chomp' must be '+', '-', or None");
431        return -1;
432    }
433
434    return 0;
435}
436
437static int
438PySyckScalar_init(PySyckScalarObject *self, PyObject *args, PyObject *kwds)
439{
440    PyObject *value = NULL;
441    PyObject *tag = NULL;
442    PyObject *anchor = NULL;
443    PyObject *style = NULL;
444    PyObject *indent = NULL;
445    PyObject *width = NULL;
446    PyObject *chomp = NULL;
447
448    static char *kwdlist[] = {"value", "tag", "anchor",
449        "style", "indent", "width", "chomp", NULL};
450
451    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOOOO", kwdlist,
452                &value, &tag, &anchor, &style, &indent, &width, &chomp))
453        return -1;
454
455    if (value && PySyckScalar_setvalue(self, value, NULL) < 0)
456        return -1;
457
458    if (tag && PySyckNode_settag((PySyckNodeObject *)self, tag, NULL) < 0)
459        return -1;
460
461    if (anchor && PySyckNode_setanchor((PySyckNodeObject *)self, anchor, NULL) < 0)
462        return -1;
463
464    if (style && PySyckScalar_setstyle(self, style, NULL) < 0)
465        return -1;
466
467    if (indent && PySyckScalar_setindent(self, indent, NULL) < 0)
468        return -1;
469
470    if (width && PySyckScalar_setwidth(self, width, NULL) < 0)
471        return -1;
472
473    if (chomp && PySyckScalar_setchomp(self, chomp, NULL) < 0)
474        return -1;
475
476    return 0;
477}
478
479static PyGetSetDef PySyckScalar_getsetters[] = {
480    {"kind", (getter)PySyckNode_getkind, NULL,
481        PyDoc_STR("the node kind, always 'scalar', read-only"),
482        &PySyck_ScalarKind},
483    {"value", (getter)PySyckNode_getvalue, (setter)PySyckScalar_setvalue,
484        PyDoc_STR("the node value, a string"), NULL},
485    {"tag", (getter)PySyckNode_gettag, (setter)PySyckNode_settag,
486        PyDoc_STR("the node tag, a string or None"), NULL},
487    {"anchor", (getter)PySyckNode_getanchor, (setter)PySyckNode_setanchor,
488        PyDoc_STR("the node anchor, a string or None"), NULL},
489    {"style", (getter)PySyckScalar_getstyle, (setter)PySyckScalar_setstyle,
490        PyDoc_STR("the node style, values: None (means literal or plain),\n"
491            "'1quote', '2quote', 'fold', 'literal', 'plain'"), NULL},
492    {"indent", (getter)PySyckScalar_getindent, (setter)PySyckScalar_setindent,
493        PyDoc_STR("the node indentation, an integer"), NULL},
494    {"width", (getter)PySyckScalar_getwidth, (setter)PySyckScalar_setwidth,
495        PyDoc_STR("the node width, an integer"), NULL},
496    {"chomp", (getter)PySyckScalar_getchomp, (setter)PySyckScalar_setchomp,
497        PyDoc_STR("the chomping method,\n"
498            "values: None (clip), '-' (strip), or '+' (keep)"), NULL},
499    {NULL}  /* Sentinel */
500};
501
502static PyTypeObject PySyckScalar_Type = {
503    PyObject_HEAD_INIT(NULL)
504    0,                                          /* ob_size */
505    "_syck.Scalar",                             /* tp_name */
506    sizeof(PySyckScalarObject),                 /* tp_basicsize */
507    0,                                          /* tp_itemsize */
508    0,                                          /* tp_dealloc */
509    0,                                          /* tp_print */
510    0,                                          /* tp_getattr */
511    0,                                          /* tp_setattr */
512    0,                                          /* tp_compare */
513    0,                                          /* tp_repr */
514    0,                                          /* tp_as_number */
515    0,                                          /* tp_as_sequence */
516    0,                                          /* tp_as_mapping */
517    0,                                          /* tp_hash */
518    0,                                          /* tp_call */
519    0,                                          /* tp_str */
520    0,                                          /* tp_getattro */
521    0,                                          /* tp_setattro */
522    0,                                          /* tp_as_buffer */
523    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,     /* tp_flags */
524    PySyckScalar_doc,                           /* tp_doc */
525    0,                                          /* tp_traverse */
526    0,                                          /* tp_clear */
527    0,                                          /* tp_richcompare */
528    0,                                          /* tp_weaklistoffset */
529    0,                                          /* tp_iter */
530    0,                                          /* tp_iternext */
531    0,                                          /* tp_methods */
532    0,                                          /* tp_members */
533    PySyckScalar_getsetters,                    /* tp_getset */
534    &PySyckNode_Type,                           /* tp_base */
535    0,                                          /* tp_dict */
536    0,                                          /* tp_descr_get */
537    0,                                          /* tp_descr_set */
538    0,                                          /* tp_dictoffset */
539    (initproc)PySyckScalar_init,                /* tp_init */
540    0,                                          /* tp_alloc */
541    PySyckScalar_new,                           /* tp_new */
542};
543
544/****************************************************************************
545 * The type _syck.Seq.
546 ****************************************************************************/
547
548PyDoc_STRVAR(PySyckSeq_doc,
549    "Seq(value=[], tag=None, inline=False) -> a Seq node\n\n"
550    "_syck.Seq represents a sequence node in Syck parser and emitter\n"
551    "trees. A sequence node points to an ordered set of subnodes.\n");
552
553typedef struct {
554    PyObject_HEAD
555    /* Common fields for all Node types: */
556    PyObject *value;    /* always an object */
557    PyObject *tag;      /* a string object or NULL */
558    PyObject *anchor;   /* a string object or NULL */
559    /* Seq-specific fields: */
560    enum seq_style style;
561} PySyckSeqObject;
562
563static PyObject *
564PySyckSeq_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
565{
566    PySyckSeqObject *self;
567
568    self = (PySyckSeqObject *)type->tp_alloc(type, 0);
569    if (!self) return NULL;
570
571    self->value = PyList_New(0);
572    if (!self->value) {
573        Py_DECREF(self);
574        return NULL;
575    }
576
577    self->tag = NULL;
578    self->anchor = NULL;
579    self->style = seq_none;
580
581    return (PyObject *)self;
582}
583
584static int
585PySyckSeq_setvalue(PySyckSeqObject *self, PyObject *value, void *closure)
586{
587    if (!value) {
588        PyErr_SetString(PyExc_TypeError, "cannot delete 'value'");
589        return -1;
590    }
591    if (!PyList_Check(value)) {
592        PyErr_SetString(PyExc_TypeError, "'value' must be a list");
593        return -1;
594    }
595
596    Py_DECREF(self->value);
597    Py_INCREF(value);
598    self->value = value;
599
600    return 0;
601}
602
603static PyObject *
604PySyckSeq_getinline(PySyckSeqObject *self, void *closure)
605{
606    PyObject *value = (self->style == seq_inline) ? Py_True : Py_False;
607
608    Py_INCREF(value);
609    return value;
610}
611
612static int
613PySyckSeq_setinline(PySyckSeqObject *self, PyObject *value, void *closure)
614{
615    if (!value) {
616        PyErr_SetString(PyExc_TypeError, "cannot delete 'inline'");
617        return -1;
618    }
619
620    if (!PyInt_Check(value)) {
621        PyErr_SetString(PyExc_TypeError, "'inline' must be a Boolean object");
622        return -1;
623    }
624
625    self->style = PyInt_AS_LONG(value) ? seq_inline : seq_none;
626
627    return 0;
628}
629
630static int
631PySyckSeq_init(PySyckSeqObject *self, PyObject *args, PyObject *kwds)
632{
633    PyObject *value = NULL;
634    PyObject *tag = NULL;
635    PyObject *anchor = NULL;
636    PyObject *inline_ = NULL;
637
638    static char *kwdlist[] = {"value", "tag", "anchor", "inline", NULL};
639
640    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwdlist,
641                &value, &tag, &anchor, &inline_))
642        return -1;
643
644    if (value && PySyckSeq_setvalue(self, value, NULL) < 0)
645        return -1;
646
647    if (tag && PySyckNode_settag((PySyckNodeObject *)self, tag, NULL) < 0)
648        return -1;
649
650    if (anchor && PySyckNode_setanchor((PySyckNodeObject *)self, anchor, NULL) < 0)
651        return -1;
652
653    if (inline_ && PySyckSeq_setinline(self, inline_, NULL) < 0)
654        return -1;
655
656    return 0;
657}
658
659static PyGetSetDef PySyckSeq_getsetters[] = {
660    {"kind", (getter)PySyckNode_getkind, NULL,
661        PyDoc_STR("the node kind, always 'seq', read-only"), &PySyck_SeqKind},
662    {"value", (getter)PySyckNode_getvalue, (setter)PySyckSeq_setvalue,
663        PyDoc_STR("the node value, a sequence"), NULL},
664    {"tag", (getter)PySyckNode_gettag, (setter)PySyckNode_settag,
665        PyDoc_STR("the node tag, a string or None"), NULL},
666    {"anchor", (getter)PySyckNode_getanchor, (setter)PySyckNode_setanchor,
667        PyDoc_STR("the node anchor, a string or None"), NULL},
668    {"inline", (getter)PySyckSeq_getinline, (setter)PySyckSeq_setinline,
669        PyDoc_STR("the block/flow flag"), NULL},
670    {NULL}  /* Sentinel */
671};
672
673static PyTypeObject PySyckSeq_Type = {
674    PyObject_HEAD_INIT(NULL)
675    0,                                          /* ob_size */
676    "_syck.Seq",                                /* tp_name */
677    sizeof(PySyckSeqObject),                    /* tp_basicsize */
678    0,                                          /* tp_itemsize */
679    0,                                          /* tp_dealloc */
680    0,                                          /* tp_print */
681    0,                                          /* tp_getattr */
682    0,                                          /* tp_setattr */
683    0,                                          /* tp_compare */
684    0,                                          /* tp_repr */
685    0,                                          /* tp_as_number */
686    0,                                          /* tp_as_sequence */
687    0,                                          /* tp_as_mapping */
688    0,                                          /* tp_hash */
689    0,                                          /* tp_call */
690    0,                                          /* tp_str */
691    0,                                          /* tp_getattro */
692    0,                                          /* tp_setattro */
693    0,                                          /* tp_as_buffer */
694    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,  /* tp_flags */
695    PySyckSeq_doc,                              /* tp_doc */
696    (traverseproc)PySyckNode_traverse,          /* tp_traverse */
697    (inquiry)PySyckNode_clear,                  /* tp_clear */
698    0,                                          /* tp_richcompare */
699    0,                                          /* tp_weaklistoffset */
700    0,                                          /* tp_iter */
701    0,                                          /* tp_iternext */
702    0,                                          /* tp_methods */
703    0,                                          /* tp_members */
704    PySyckSeq_getsetters,                       /* tp_getset */
705    &PySyckNode_Type,                           /* tp_base */
706    0,                                          /* tp_dict */
707    0,                                          /* tp_descr_get */
708    0,                                          /* tp_descr_set */
709    0,                                          /* tp_dictoffset */
710    (initproc)PySyckSeq_init,                   /* tp_init */
711    0,                                          /* tp_alloc */
712    PySyckSeq_new,                              /* tp_new */
713};
714
715/****************************************************************************
716 * The type _syck.Map.
717 ****************************************************************************/
718
719PyDoc_STRVAR(PySyckMap_doc,
720    "Map(value={}, tag=None, inline=False) -> a Map node\n\n"
721    "_syck.Map represents a mapping node in Syck parser and emitter\n"
722    "trees. A mapping node points to an unordered collections of pairs.\n");
723
724typedef struct {
725    PyObject_HEAD
726    /* Common fields for all Node types: */
727    PyObject *value;    /* always an object */
728    PyObject *tag;      /* a string object or NULL */
729    PyObject *anchor;   /* a string object or NULL */
730    /* Map-specific fields: */
731    enum map_style style;
732} PySyckMapObject;
733
734static PyObject *
735PySyckMap_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
736{
737    PySyckMapObject *self;
738
739    self = (PySyckMapObject *)type->tp_alloc(type, 0);
740    if (!self) return NULL;
741
742    self->value = PyDict_New();
743    if (!self->value) {
744        Py_DECREF(self);
745        return NULL;
746    }
747
748    self->tag = NULL;
749    self->anchor = NULL;
750    self->style = seq_none;
751
752    return (PyObject *)self;
753}
754
755static int
756PySyckMap_setvalue(PySyckMapObject *self, PyObject *value, void *closure)
757{
758    if (!value) {
759        PyErr_SetString(PyExc_TypeError, "cannot delete 'value'");
760        return -1;
761    }
762    if (!PyDict_Check(value) && !PyList_Check(value)) {
763        PyErr_SetString(PyExc_TypeError,
764                "'value' must be a list of pairs or a dictionary");
765        return -1;
766    }
767
768    Py_DECREF(self->value);
769    Py_INCREF(value);
770    self->value = value;
771
772    return 0;
773}
774
775static PyObject *
776PySyckMap_getinline(PySyckMapObject *self, void *closure)
777{
778    PyObject *value = (self->style == map_inline) ? Py_True : Py_False;
779
780    Py_INCREF(value);
781    return value;
782}
783
784static int
785PySyckMap_setinline(PySyckMapObject *self, PyObject *value, void *closure)
786{
787    if (!value) {
788        PyErr_SetString(PyExc_TypeError, "cannot delete 'inline'");
789        return -1;
790    }
791
792    if (!PyInt_Check(value)) {
793        PyErr_SetString(PyExc_TypeError, "'inline' must be a Boolean object");
794        return -1;
795    }
796
797    self->style = PyInt_AS_LONG(value) ? map_inline : map_none;
798
799    return 0;
800}
801
802static int
803PySyckMap_init(PySyckMapObject *self, PyObject *args, PyObject *kwds)
804{
805    PyObject *value = NULL;
806    PyObject *tag = NULL;
807    PyObject *anchor = NULL;
808    PyObject *inline_ = NULL;
809
810    static char *kwdlist[] = {"value", "tag", "anchor", "inline", NULL};
811
812    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwdlist,
813                &value, &tag, &anchor, &inline_))
814        return -1;
815
816    if (value && PySyckMap_setvalue(self, value, NULL) < 0)
817        return -1;
818
819    if (tag && PySyckNode_settag((PySyckNodeObject *)self, tag, NULL) < 0)
820        return -1;
821
822    if (anchor && PySyckNode_setanchor((PySyckNodeObject *)self, anchor, NULL) < 0)
823        return -1;
824
825    if (inline_ && PySyckMap_setinline(self, inline_, NULL) < 0)
826        return -1;
827
828    return 0;
829}
830
831static PyGetSetDef PySyckMap_getsetters[] = {
832    {"kind", (getter)PySyckNode_getkind, NULL,
833        PyDoc_STR("the node kind, always 'map', read-only"), &PySyck_MapKind},
834    {"value", (getter)PySyckNode_getvalue, (setter)PySyckMap_setvalue,
835        PyDoc_STR("the node value, a list of pairs or a dictionary"), NULL},
836    {"tag", (getter)PySyckNode_gettag, (setter)PySyckNode_settag,
837        PyDoc_STR("the node tag, a string or None"), NULL},
838    {"anchor", (getter)PySyckNode_getanchor, (setter)PySyckNode_setanchor,
839        PyDoc_STR("the node anchor, a string or None"), NULL},
840    {"inline", (getter)PySyckMap_getinline, (setter)PySyckMap_setinline,
841        PyDoc_STR("the block/flow flag"), NULL},
842    {NULL}  /* Sentinel */
843};
844
845static PyTypeObject PySyckMap_Type = {
846    PyObject_HEAD_INIT(NULL)
847    0,                                          /* ob_size */
848    "_syck.Map",                                /* tp_name */
849    sizeof(PySyckMapObject),                    /* tp_basicsize */
850    0,                                          /* tp_itemsize */
851    0,                                          /* tp_dealloc */
852    0,                                          /* tp_print */
853    0,                                          /* tp_getattr */
854    0,                                          /* tp_setattr */
855    0,                                          /* tp_compare */
856    0,                                          /* tp_repr */
857    0,                                          /* tp_as_number */
858    0,                                          /* tp_as_sequence */
859    0,                                          /* tp_as_mapping */
860    0,                                          /* tp_hash */
861    0,                                          /* tp_call */
862    0,                                          /* tp_str */
863    0,                                          /* tp_getattro */
864    0,                                          /* tp_setattro */
865    0,                                          /* tp_as_buffer */
866    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,  /* tp_flags */
867    PySyckMap_doc,                              /* tp_doc */
868    (traverseproc)PySyckNode_traverse,          /* tp_traverse */
869    (inquiry)PySyckNode_clear,                  /* tp_clear */
870    0,                                          /* tp_richcompare */
871    0,                                          /* tp_weaklistoffset */
872    0,                                          /* tp_iter */
873    0,                                          /* tp_iternext */
874    0,                                          /* tp_methods */
875    0,                                          /* tp_members */
876    PySyckMap_getsetters,                       /* tp_getset */
877    &PySyckNode_Type,                           /* tp_base */
878    0,                                          /* tp_dict */
879    0,                                          /* tp_descr_get */
880    0,                                          /* tp_descr_set */
881    0,                                          /* tp_dictoffset */
882    (initproc)PySyckMap_init,                   /* tp_init */
883    0,                                          /* tp_alloc */
884    PySyckMap_new,                              /* tp_new */
885};
886
887/****************************************************************************
888 * The type _syck.Parser.
889 ****************************************************************************/
890
891PyDoc_STRVAR(PySyckParser_doc,
892    "Parser(source, implicit_typing=True, taguri_expansion=True)\n"
893    "      -> a Parser object\n\n"
894    "_syck.Parser is a low-lever wrapper of the Syck parser. It parses\n"
895    "a YAML stream and produces a tree of Nodes.\n");
896
897typedef struct {
898    PyObject_HEAD
899    /* Attributes: */
900    PyObject *source;       /* a string or file-like object */
901    int implicit_typing;
902    int taguri_expansion;
903    /* Internal fields: */
904    PyObject *symbols;      /* symbol table, a list, NULL outside parse() */
905    SyckParser *parser;
906    int parsing;
907    int halt;
908} PySyckParserObject;
909
910static PyObject *
911PySyckParser_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
912{
913    PySyckParserObject *self;
914
915    self = (PySyckParserObject *)type->tp_alloc(type, 0);
916    if (!self) return NULL;
917
918    self->source = NULL;
919    self->implicit_typing = 0;
920    self->taguri_expansion = 0;
921    self->symbols = NULL;
922    self->parser = NULL;
923    self->parsing = 0;
924    self->halt = 1;
925
926    /*
927    self->symbols = PyList_New(0);
928    if (!self->symbols) {
929        Py_DECREF(self);
930        return NULL;
931    }
932    */
933
934    return (PyObject *)self;
935}
936
937static int
938PySyckParser_clear(PySyckParserObject *self)
939{
940    PyObject *tmp;
941
942    if (self->parser) {
943        syck_free_parser(self->parser);
944        self->parser = NULL;
945    }
946
947    tmp = self->source;
948    self->source = NULL;
949    Py_XDECREF(tmp);
950
951    tmp = self->symbols;
952    self->symbols = NULL;
953    Py_XDECREF(tmp);
954
955    return 0;
956}
957
958static int
959PySyckParser_traverse(PySyckParserObject *self, visitproc visit, void *arg)
960{
961    int ret;
962
963    if (self->source)
964        if ((ret = visit(self->source, arg)) != 0)
965            return ret;
966
967    if (self->symbols)
968        if ((ret = visit(self->symbols, arg)) != 0)
969            return ret;
970
971    return 0;
972}
973
974static void
975PySyckParser_dealloc(PySyckParserObject *self)
976{
977    PySyckParser_clear(self);
978    self->ob_type->tp_free((PyObject *)self);
979}
980
981static PyObject *
982PySyckParser_getsource(PySyckParserObject *self, void *closure)
983{
984    PyObject *value = self->source ? self->source : Py_None;
985
986    Py_INCREF(value);
987    return value;
988}
989
990static PyObject *
991PySyckParser_getimplicit_typing(PySyckParserObject *self, void *closure)
992{
993    PyObject *value = self->implicit_typing ? Py_True : Py_False;
994
995    Py_INCREF(value);
996    return value;
997}
998
999static PyObject *
1000PySyckParser_gettaguri_expansion(PySyckParserObject *self, void *closure)
1001{
1002    PyObject *value = self->taguri_expansion ? Py_True : Py_False;
1003
1004    Py_INCREF(value);
1005    return value;
1006}
1007
1008static PyObject *
1009PySyckParser_geteof(PySyckParserObject *self, void *closure)
1010{
1011    PyObject *value = self->halt ? Py_True : Py_False;
1012
1013    Py_INCREF(value);
1014    return value;
1015}
1016
1017static PyGetSetDef PySyckParser_getsetters[] = {
1018    {"source", (getter)PySyckParser_getsource, NULL,
1019        PyDoc_STR("IO source, a string or a file-like object"), NULL},
1020    {"implicit_typing", (getter)PySyckParser_getimplicit_typing, NULL,
1021        PyDoc_STR("implicit typing of builtin YAML types"), NULL},
1022    {"taguri_expansion", (getter)PySyckParser_gettaguri_expansion, NULL,
1023        PyDoc_STR("expansion of types in full taguri"), NULL},
1024    {"eof", (getter)PySyckParser_geteof, NULL,
1025        PyDoc_STR("EOF flag"), NULL},
1026    {NULL}  /* Sentinel */
1027};
1028
1029static SYMID
1030PySyckParser_node_handler(SyckParser *parser, SyckNode *node)
1031{
1032    PyGILState_STATE gs;
1033
1034    PySyckParserObject *self = (PySyckParserObject *)parser->bonus;
1035
1036    SYMID index;
1037    PySyckNodeObject *object = NULL;
1038
1039    PyObject *key, *value;
1040    int k;
1041
1042    if (self->halt)
1043        return -1;
1044
1045    gs = PyGILState_Ensure();
1046
1047    switch (node->kind) {
1048
1049        case syck_str_kind:
1050            object = (PySyckNodeObject *)
1051                PySyckScalar_new(&PySyckScalar_Type, NULL, NULL);
1052            if (!object) goto error;
1053            value = PyString_FromStringAndSize(node->data.str->ptr,
1054                    node->data.str->len);
1055            if (!value) goto error;
1056            Py_DECREF(object->value);
1057            object->value = value;
1058            break;
1059
1060        case syck_seq_kind:
1061            object = (PySyckNodeObject *)
1062                PySyckSeq_new(&PySyckSeq_Type, NULL, NULL);
1063            if (!object) goto error;
1064            for (k = 0; k < node->data.list->idx; k++) {
1065                index = syck_seq_read(node, k)-1;
1066                value = PyList_GetItem(self->symbols, index);
1067                if (!value) goto error;
1068                if (PyList_Append(object->value, value) < 0)
1069                    goto error;
1070            }
1071            break;
1072
1073        case syck_map_kind:
1074            object = (PySyckNodeObject *)
1075                PySyckMap_new(&PySyckMap_Type, NULL, NULL);
1076            if (!object) goto error;
1077            for (k = 0; k < node->data.pairs->idx; k++)
1078            {
1079                index = syck_map_read(node, map_key, k)-1;
1080                key = PyList_GetItem(self->symbols, index);
1081                if (!key) goto error;
1082                index = syck_map_read(node, map_value, k)-1;
1083                value = PyList_GetItem(self->symbols, index);
1084                if (!value) goto error;
1085                if (PyDict_SetItem(object->value, key, value) < 0)
1086                    goto error;
1087            }
1088            break;
1089    }
1090
1091    if (node->type_id) {
1092        object->tag = PyString_FromString(node->type_id);
1093        if (!object->tag) goto error;
1094    }
1095
1096    if (node->anchor) {
1097        object->anchor = PyString_FromString(node->anchor);
1098        if (!object->anchor) goto error;
1099    }
1100
1101    if (PyList_Append(self->symbols, (PyObject *)object) < 0)
1102        goto error;
1103
1104    index = PyList_GET_SIZE(self->symbols);
1105    PyGILState_Release(gs);
1106    return index;
1107
1108error:
1109    Py_XDECREF(object);
1110    PyGILState_Release(gs);
1111    self->halt = 1;
1112    return -1;
1113}
1114
1115static void
1116PySyckParser_error_handler(SyckParser *parser, char *str)
1117{
1118    PyGILState_STATE gs;
1119
1120    PySyckParserObject *self = (PySyckParserObject *)parser->bonus;
1121    PyObject *value;
1122
1123    if (self->halt) return;
1124
1125    gs = PyGILState_Ensure();
1126
1127    self->halt = 1;
1128
1129    value = Py_BuildValue("(sii)", str,
1130            parser->linect, parser->cursor - parser->lineptr);
1131    if (value) {
1132        PyErr_SetObject(PySyck_Error, value);
1133    }
1134
1135    PyGILState_Release(gs);
1136}
1137
1138SyckNode *
1139PySyckParser_bad_anchor_handler(SyckParser *parser, char *anchor)
1140{
1141    PyGILState_STATE gs;
1142
1143    PySyckParserObject *self = (PySyckParserObject *)parser->bonus;
1144
1145    if (!self->halt) {
1146        gs = PyGILState_Ensure();
1147
1148        self->halt = 1;
1149        PyErr_SetString(PyExc_TypeError, "recursive anchors are not implemented");
1150
1151        PyGILState_Release(gs);
1152    }
1153
1154    return syck_alloc_str();
1155}
1156
1157static long
1158PySyckParser_read_handler(char *buf, SyckIoFile *file, long max_size, long skip)
1159{
1160    PyGILState_STATE gs;
1161
1162    PySyckParserObject *self = (PySyckParserObject *)file->ptr;
1163
1164    PyObject *value;
1165
1166    char *str;
1167    int length;
1168
1169    buf[skip] = '\0';
1170
1171    if (self->halt) {
1172        return skip;
1173    }
1174   
1175    max_size -= skip;
1176
1177    gs = PyGILState_Ensure();
1178
1179    value = PyObject_CallMethod(self->source, "read", "(i)", max_size);
1180    if (!value) {
1181        self->halt = 1;
1182
1183        PyGILState_Release(gs);
1184
1185        return skip;
1186    }
1187
1188    if (!PyString_CheckExact(value)) {
1189        Py_DECREF(value);
1190        PyErr_SetString(PyExc_TypeError, "file-like object should return a string");
1191        self->halt = 1;
1192       
1193        PyGILState_Release(gs);
1194
1195        return skip;
1196    }
1197
1198    str = PyString_AS_STRING(value);
1199    length = PyString_GET_SIZE(value);
1200    if (!length) {
1201        Py_DECREF(value);
1202
1203        PyGILState_Release(gs);
1204
1205        return skip;
1206    }
1207
1208    if (length > max_size) {
1209        Py_DECREF(value);
1210        PyErr_SetString(PyExc_ValueError, "read returns an overly long string");
1211        self->halt = 1;
1212
1213        PyGILState_Release(gs);
1214
1215        return skip;
1216    }
1217
1218    memcpy(buf+skip, str, length);
1219    length += skip;
1220    buf[length] = '\0';
1221
1222    Py_DECREF(value);
1223
1224    PyGILState_Release(gs);
1225
1226    return length;
1227}
1228
1229static int
1230PySyckParser_init(PySyckParserObject *self, PyObject *args, PyObject *kwds)
1231{
1232    PyObject *source = NULL;
1233    int implicit_typing = 1;
1234    int taguri_expansion = 1;
1235
1236    static char *kwdlist[] = {"source", "implicit_typing", "taguri_expansion",
1237        NULL};
1238
1239    PySyckParser_clear(self);
1240
1241    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|ii", kwdlist,
1242                &source, &implicit_typing, &taguri_expansion))
1243        return -1;
1244
1245    Py_INCREF(source);
1246    self->source = source;
1247
1248    self->implicit_typing = implicit_typing;
1249    self->taguri_expansion = taguri_expansion;
1250
1251    self->parser = syck_new_parser();
1252    self->parser->bonus = self;
1253
1254    if (PyString_CheckExact(self->source)) {
1255        syck_parser_str(self->parser,
1256                PyString_AS_STRING(self->source),
1257                PyString_GET_SIZE(self->source), NULL);
1258    }
1259    /*
1260    else if (PyUnicode_CheckExact(self->source)) {
1261        syck_parser_str(self->parser,
1262                PyUnicode_AS_DATA(self->source),
1263                PyString_GET_DATA_SIZE(self->source), NULL);
1264    }
1265    */
1266    else {
1267        syck_parser_file(self->parser, (FILE *)self, PySyckParser_read_handler);
1268    }
1269
1270    syck_parser_implicit_typing(self->parser, self->implicit_typing);
1271    syck_parser_taguri_expansion(self->parser, self->taguri_expansion);
1272
1273    syck_parser_handler(self->parser, PySyckParser_node_handler);
1274    syck_parser_error_handler(self->parser, PySyckParser_error_handler);
1275    syck_parser_bad_anchor_handler(self->parser, PySyckParser_bad_anchor_handler);
1276
1277    self->parsing = 0;
1278    self->halt = 0;
1279
1280    return 0;
1281}
1282
1283static PyObject *
1284PySyckParser_parse(PySyckParserObject *self)
1285{
1286    SYMID index;
1287    PyObject *value;
1288
1289    if (self->parsing) {
1290        PyErr_SetString(PyExc_RuntimeError,
1291                "do not call Parser.parse while it is already running");
1292        return NULL;
1293    }
1294
1295    if (self->halt) {
1296        Py_INCREF(Py_None);
1297        return Py_None;
1298    }
1299
1300    self->symbols = PyList_New(0);
1301    if (!self->symbols) {
1302        return NULL;
1303    }
1304
1305    self->parsing = 1;
1306    Py_BEGIN_ALLOW_THREADS
1307    index = syck_parse(self->parser)-1;
1308    Py_END_ALLOW_THREADS
1309    self->parsing = 0;
1310
1311    if (self->halt || self->parser->eof) {
1312        Py_DECREF(self->symbols);
1313        self->symbols = NULL;
1314
1315        if (self->halt) return NULL;
1316
1317        self->halt = 1;
1318        Py_INCREF(Py_None);
1319        return Py_None;
1320    }
1321
1322    value = PyList_GetItem(self->symbols, index);
1323
1324    Py_DECREF(self->symbols);
1325    self->symbols = NULL;
1326
1327    return value;
1328}
1329
1330PyDoc_STRVAR(PySyckParser_parse_doc,
1331    "parse() -> the root Node object\n\n"
1332    "Parses the source and returns the root of the Node tree. Call it\n"
1333    "several times to retrieve all documents from the source. On EOF,\n"
1334    "returns None and sets the 'eof' attribute on.\n");
1335
1336static PyMethodDef PySyckParser_methods[] = {
1337    {"parse",  (PyCFunction)PySyckParser_parse,
1338        METH_NOARGS, PySyckParser_parse_doc},
1339    {NULL}  /* Sentinel */
1340};
1341
1342static PyTypeObject PySyckParser_Type = {
1343    PyObject_HEAD_INIT(NULL)
1344    0,                                          /* ob_size */
1345    "_syck.Parser",                             /* tp_name */
1346    sizeof(PySyckParserObject),                 /* tp_basicsize */
1347    0,                                          /* tp_itemsize */
1348    (destructor)PySyckParser_dealloc,           /* tp_dealloc */
1349    0,                                          /* tp_print */
1350    0,                                          /* tp_getattr */
1351    0,                                          /* tp_setattr */
1352    0,                                          /* tp_compare */
1353    0,                                          /* tp_repr */
1354    0,                                          /* tp_as_number */
1355    0,                                          /* tp_as_sequence */
1356    0,                                          /* tp_as_mapping */
1357    0,                                          /* tp_hash */
1358    0,                                          /* tp_call */
1359    0,                                          /* tp_str */
1360    0,                                          /* tp_getattro */
1361    0,                                          /* tp_setattro */
1362    0,                                          /* tp_as_buffer */
1363    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,  /* tp_flags */
1364    PySyckParser_doc,                           /* tp_doc */
1365    (traverseproc)PySyckParser_traverse,        /* tp_traverse */
1366    (inquiry)PySyckParser_clear,                /* tp_clear */
1367    0,                                          /* tp_richcompare */
1368    0,                                          /* tp_weaklistoffset */
1369    0,                                          /* tp_iter */
1370    0,                                          /* tp_iternext */
1371    PySyckParser_methods,                       /* tp_methods */
1372    0,                                          /* tp_members */
1373    PySyckParser_getsetters,                    /* tp_getset */
1374    0,                                          /* tp_base */
1375    0,                                          /* tp_dict */
1376    0,                                          /* tp_descr_get */
1377    0,                                          /* tp_descr_set */
1378    0,                                          /* tp_dictoffset */
1379    (initproc)PySyckParser_init,                /* tp_init */
1380    0,                                          /* tp_alloc */
1381    PySyckParser_new,                           /* tp_new */
1382};
1383
1384/****************************************************************************
1385 * The type _syck.Emitter.
1386 ****************************************************************************/
1387
1388PyDoc_STRVAR(PySyckEmitter_doc,
1389    "Emitter(output, headless=False, use_header=False, use_version=False,\n"
1390    "        explicit_typing=True, style=None, best_width=80, indent=2)\n"
1391    "                -> an Emitter object\n\n"
1392    "_syck.Emitter is a low-lever wrapper of the Syck emitter. It emits\n"
1393    "a tree of Nodes into a YAML stream.\n");
1394
1395typedef struct {
1396    PyObject_HEAD
1397    /* Attributes: */
1398    PyObject *output;       /* a file-like object */
1399    int headless;
1400    int use_header;
1401    int use_version;
1402    int explicit_typing;
1403    enum scalar_style style;
1404    int best_width;
1405    int indent;
1406    /* Internal fields: */
1407    PyObject *symbols;      /* symbol table, a list, NULL outside emit() */
1408    PyObject *nodes;        /* node -> symbol, a dict, NULL outside emit() */
1409    SyckEmitter *emitter;
1410    int emitting;
1411    int halt;
1412} PySyckEmitterObject;
1413
1414static PyObject *
1415PySyckEmitter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1416{
1417    PySyckEmitterObject *self;
1418
1419    self = (PySyckEmitterObject *)type->tp_alloc(type, 0);
1420    if (!self) return NULL;
1421
1422    self->output = NULL;
1423    self->headless = 0;
1424    self->use_header = 0;
1425    self->use_version = 0;
1426    self->explicit_typing = 0;
1427    self->style = scalar_none;
1428    self->best_width = 0;
1429    self->indent = 0;
1430    self->symbols = NULL;
1431    self->nodes = NULL;
1432    self->emitter = NULL;
1433    self->emitting = 0;
1434    self->halt = 1;
1435
1436    return (PyObject *)self;
1437}
1438
1439static int
1440PySyckEmitter_clear(PySyckEmitterObject *self)
1441{
1442    PyObject *tmp;
1443
1444    if (self->emitter) {
1445        syck_free_emitter(self->emitter);
1446        self->emitter = NULL;
1447    }
1448
1449    tmp = self->output;
1450    self->output = NULL;
1451    Py_XDECREF(tmp);
1452
1453    tmp = self->symbols;
1454    self->symbols = NULL;
1455    Py_XDECREF(tmp);
1456
1457    tmp = self->nodes;
1458    self->nodes = NULL;
1459    Py_XDECREF(tmp);
1460
1461    return 0;
1462}
1463
1464static int
1465PySyckEmitter_traverse(PySyckEmitterObject *self, visitproc visit, void *arg)
1466{
1467    int ret;
1468
1469    if (self->output)
1470        if ((ret = visit(self->output, arg)) != 0)
1471            return ret;
1472
1473    if (self->symbols)
1474        if ((ret = visit(self->symbols, arg)) != 0)
1475            return ret;
1476
1477    if (self->nodes)
1478        if ((ret = visit(self->nodes, arg)) != 0)
1479            return ret;
1480
1481    return 0;
1482}
1483
1484static void
1485PySyckEmitter_dealloc(PySyckEmitterObject *self)
1486{
1487    PySyckEmitter_clear(self);
1488    self->ob_type->tp_free((PyObject *)self);
1489}
1490
1491static PyObject *
1492PySyckEmitter_getoutput(PySyckEmitterObject *self, void *closure)
1493{
1494    PyObject *value = self->output ? self->output : Py_None;
1495
1496    Py_INCREF(value);
1497    return value;
1498}
1499
1500static PyObject *
1501PySyckEmitter_getheadless(PySyckEmitterObject *self, void *closure)
1502{
1503    PyObject *value = self->headless ? Py_True : Py_False;
1504
1505    Py_INCREF(value);
1506    return value;
1507}
1508
1509static PyObject *
1510PySyckEmitter_getuse_header(PySyckEmitterObject *self, void *closure)
1511{
1512    PyObject *value = self->use_header ? Py_True : Py_False;
1513
1514    Py_INCREF(value);
1515    return value;
1516}
1517
1518static PyObject *
1519PySyckEmitter_getuse_version(PySyckEmitterObject *self, void *closure)
1520{
1521    PyObject *value = self->use_version ? Py_True : Py_False;
1522
1523    Py_INCREF(value);
1524    return value;
1525}
1526
1527static PyObject *
1528PySyckEmitter_getexplicit_typing(PySyckEmitterObject *self, void *closure)
1529{
1530    PyObject *value = self->explicit_typing ? Py_True : Py_False;
1531
1532    Py_INCREF(value);
1533    return value;
1534}
1535
1536static PyObject *
1537PySyckEmitter_getstyle(PySyckEmitterObject *self, void *closure)
1538{
1539    PyObject *value;
1540
1541    switch (self->style) {
1542        case scalar_1quote: value = PySyck_1QuoteStyle; break;
1543        case scalar_2quote: value = PySyck_2QuoteStyle; break;
1544        case scalar_fold: value = PySyck_FoldStyle; break;
1545        case scalar_literal: value = PySyck_LiteralStyle; break;
1546        case scalar_plain: value = PySyck_PlainStyle; break;
1547        default: value = Py_None;
1548    }
1549
1550    Py_INCREF(value);
1551    return value;
1552}
1553
1554static PyObject *
1555PySyckEmitter_getbest_width(PySyckEmitterObject *self, void *closure)
1556{
1557    return PyInt_FromLong(self->best_width);
1558}
1559
1560static PyObject *
1561PySyckEmitter_getindent(PySyckEmitterObject *self, void *closure)
1562{
1563    return PyInt_FromLong(self->indent);
1564}
1565
1566static PyGetSetDef PySyckEmitter_getsetters[] = {
1567    {"output", (getter)PySyckEmitter_getoutput, NULL,
1568        PyDoc_STR("output stream, a file-like object"), NULL},
1569    {"headless", (getter)PySyckEmitter_getheadless, NULL,
1570        PyDoc_STR("headerless document flag"), NULL},
1571    {"use_header", (getter)PySyckEmitter_getuse_header, NULL,
1572        PyDoc_STR("force header flag"), NULL},
1573    {"use_version", (getter)PySyckEmitter_getuse_version, NULL,
1574        PyDoc_STR("force version flag"), NULL},
1575    {"explicit_typing", (getter)PySyckEmitter_getexplicit_typing, NULL,
1576        PyDoc_STR("explicit typing for all collections"), NULL},
1577    {"style", (getter)PySyckEmitter_getstyle, NULL,
1578        PyDoc_STR("use literal or folded blocks on all text"), NULL},
1579    {"best_width", (getter)PySyckEmitter_getbest_width, NULL,
1580        PyDoc_STR("best width for folded scalars"), NULL},
1581    {"indent", (getter)PySyckEmitter_getindent, NULL,
1582        PyDoc_STR("default indentation"), NULL},
1583    {NULL}  /* Sentinel */
1584};
1585
1586static void
1587PySyckEmitter_node_handler(SyckEmitter *emitter, st_data_t id)
1588{
1589    PyGILState_STATE gs;
1590
1591    PySyckEmitterObject *self = (PySyckEmitterObject *)emitter->bonus;
1592
1593    PySyckNodeObject *node;
1594    char *tag = NULL;
1595    PyObject *index;
1596    PyObject *key, *value, *item, *pair;
1597    int j, k, l;
1598    char *str;
1599    int len;
1600    int dict_pos;
1601
1602    if (self->halt) return;
1603
1604    gs = PyGILState_Ensure();
1605
1606    node = (PySyckNodeObject *)PyList_GetItem(self->symbols, id);
1607    if (!node) {
1608        PyErr_SetString(PyExc_RuntimeError, "unknown data id");
1609        self->halt = 1;
1610        PyGILState_Release(gs);
1611        return;
1612    }
1613
1614    if (node->tag) {
1615        tag = PyString_AsString(node->tag);
1616        if (!tag) {
1617            self->halt = 1;
1618            PyGILState_Release(gs);
1619            return;
1620        }
1621    }
1622
1623    if (PyObject_TypeCheck((PyObject *)node, &PySyckSeq_Type)) {
1624
1625        syck_emit_seq(emitter, tag, ((PySyckSeqObject *)node)->style);
1626
1627        if (!PyList_Check(node->value)) {
1628            PyErr_SetString(PyExc_TypeError, "value of _syck.Seq must be a list");
1629            self->halt = 1;
1630            PyGILState_Release(gs);
1631            return;
1632        }
1633        l = PyList_GET_SIZE(node->value);
1634        for (k = 0; k < l; k ++) {
1635            item = PyList_GET_ITEM(node->value, k);
1636            if ((index = PyDict_GetItem(self->nodes, item))) {
1637                syck_emit_item(emitter, PyInt_AS_LONG(index));
1638                if (self->halt) {
1639                    PyGILState_Release(gs);
1640                    return;
1641                }
1642            }
1643            else {
1644                PyErr_SetString(PyExc_RuntimeError, "sequence item is not marked");
1645                self->halt = 1;
1646                PyGILState_Release(gs);
1647                return;
1648            }
1649        }
1650        syck_emit_end(emitter);
1651    }
1652
1653    else if (PyObject_TypeCheck((PyObject *)node, &PySyckMap_Type)) {
1654
1655        syck_emit_map(emitter, tag, ((PySyckMapObject *)node)->style);
1656       
1657        if (PyList_Check(node->value)) {
1658            l = PyList_GET_SIZE(node->value);
1659            for (k = 0; k < l; k ++) {
1660                pair = PyList_GET_ITEM(node->value, k);
1661                if (!PyTuple_Check(pair) || PyTuple_GET_SIZE(pair) != 2) {
1662                    PyErr_SetString(PyExc_TypeError,
1663                            "value of _syck.Map must be a list of pairs or a dictionary");
1664                    self->halt = 1;
1665                    PyGILState_Release(gs);
1666                    return;
1667                }
1668                for (j = 0; j < 2; j++) {
1669                    item = PyTuple_GET_ITEM(pair, j);
1670                    if ((index = PyDict_GetItem(self->nodes, item))) {
1671                        syck_emit_item(emitter, PyInt_AS_LONG(index));
1672                        if (self->halt) {
1673                            PyGILState_Release(gs);
1674                            return;
1675                        }
1676                    }
1677                    else {
1678                        PyErr_SetString(PyExc_RuntimeError, "mapping item is not marked");
1679                        self->halt = 1;
1680                        PyGILState_Release(gs);
1681                        return;
1682                    }
1683                }
1684            }
1685        }
1686        else if (PyDict_Check(node->value)) {
1687            dict_pos = 0;
1688            while (PyDict_Next(node->value, &dict_pos, &key, &value)) {
1689                for (j = 0; j < 2; j++) {
1690                    item = j ? value : key;
1691                    if ((index = PyDict_GetItem(self->nodes, item))) {
1692                        syck_emit_item(emitter, PyInt_AS_LONG(index));
1693                        if (self->halt) {
1694                            PyGILState_Release(gs);
1695                            return;
1696                        }
1697                    }
1698                    else {
1699                        PyErr_SetString(PyExc_RuntimeError, "mapping item is not marked");
1700                        self->halt = 1;
1701                        PyGILState_Release(gs);
1702                        return;
1703                    }
1704                }
1705            }
1706        }
1707        else {
1708            PyErr_SetString(PyExc_TypeError,
1709                    "value of _syck.Map must be a list of pairs or a dictionary");
1710            self->halt = 1;
1711            PyGILState_Release(gs);
1712            return;
1713        }
1714
1715        syck_emit_end(emitter);
1716    }
1717
1718    else if (PyObject_TypeCheck((PyObject *)node, &PySyckScalar_Type)) {
1719        if (PyString_AsStringAndSize(node->value, &str, &len) < 0) {
1720            self->halt = 1;
1721            PyGILState_Release(gs);
1722            return;
1723        }
1724        syck_emit_scalar(emitter, tag, ((PySyckScalarObject *)node)->style,
1725                ((PySyckScalarObject *)node)->indent,
1726                ((PySyckScalarObject *)node)->width,
1727                ((PySyckScalarObject *)node)->chomp, str, len);
1728    }
1729
1730    else {
1731        PyErr_SetString(PyExc_TypeError, "Node instance is required");
1732        self->halt = 1;
1733        PyGILState_Release(gs);
1734        return;
1735    }   
1736    PyGILState_Release(gs);
1737}
1738
1739static void
1740PySyckEmitter_write_handler(SyckEmitter *emitter, char *buf, long len)
1741{
1742    PyGILState_STATE gs;
1743
1744    PySyckEmitterObject *self = (PySyckEmitterObject *)emitter->bonus;
1745
1746    gs = PyGILState_Ensure();
1747
1748    if (!PyObject_CallMethod(self->output, "write", "(s#)", buf, len))
1749        self->halt = 1;
1750
1751    PyGILState_Release(gs);
1752}
1753
1754static int
1755PySyckEmitter_init(PySyckEmitterObject *self, PyObject *args, PyObject *kwds)
1756{
1757    PyObject *output = NULL;
1758    int headless = 0;
1759    int use_header = 0;
1760    int use_version = 0;
1761    int explicit_typing = 0;
1762    PyObject *style = NULL;
1763    int best_width = 80;
1764    int indent = 2;
1765
1766    char *str;
1767
1768    static char *kwdlist[] = {"output", "headless", "use_header",
1769        "use_version", "explicit_typing", "style",
1770        "best_width", "indent", NULL};
1771
1772    PySyckEmitter_clear(self);
1773
1774    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|iiiiOii", kwdlist,
1775                &output, &headless, &use_header, &use_version,
1776                &explicit_typing, &style, &best_width, &indent))
1777        return -1;
1778
1779    if (best_width <= 0) {
1780        PyErr_SetString(PyExc_ValueError, "'best_width' must be positive");
1781        return -1;
1782    }
1783    if (indent <= 0) {
1784        PyErr_SetString(PyExc_ValueError, "'indent' must be positive");
1785        return -1;
1786    }
1787
1788    if (!style || style == Py_None) {
1789        self->style = scalar_none;
1790    }
1791    else {
1792        if (!PyString_Check(style)) {
1793            PyErr_SetString(PyExc_TypeError, "'style' must be a string or None");
1794            return -1;
1795        }
1796
1797        str = PyString_AsString(style);
1798        if (!str) return -1;
1799
1800        if (strcmp(str, "1quote") == 0)
1801            self->style = scalar_1quote;
1802        else if (strcmp(str, "2quote") == 0)
1803            self->style = scalar_2quote;
1804        else if (strcmp(str, "fold") == 0)
1805            self->style = scalar_fold;
1806        else if (strcmp(str, "literal") == 0)
1807            self->style = scalar_literal;
1808        else if (strcmp(str, "plain") == 0)
1809            self->style = scalar_plain;
1810        else {
1811            PyErr_SetString(PyExc_ValueError, "unknown 'style'");
1812            return -1;
1813        }
1814    }
1815
1816    self->headless = headless;
1817    self->use_header = use_header;
1818    self->use_version = use_version;
1819    self->explicit_typing = explicit_typing;
1820    self->best_width = best_width;
1821    self->indent = indent;
1822
1823    Py_INCREF(output);
1824    self->output = output;
1825
1826    self->emitting = 0;
1827    self->halt = 0;
1828
1829    return 0;
1830}
1831
1832static int
1833PySyckEmitter_mark(PySyckEmitterObject *self, PyObject *root_node)
1834{
1835    int current, last;
1836    int j, k, l;
1837    PySyckNodeObject *node;
1838    PyObject *item, *key, *value, *pair;
1839    PyObject *index;
1840    int dict_pos;
1841
1842    last = 0;
1843    syck_emitter_mark_node(self->emitter, last);
1844    if (PyList_Append(self->symbols, root_node) < 0)
1845        return -1;
1846    index = PyInt_FromLong(last);
1847    if (!index) return -1;
1848    if (PyDict_SetItem(self->nodes, root_node, index) < 0) {
1849        Py_DECREF(index);
1850        return -1;
1851    }
1852    Py_DECREF(index);
1853
1854    for (current = 0; current < PyList_GET_SIZE(self->symbols); current++) {
1855
1856        node = (PySyckNodeObject *)PyList_GET_ITEM(self->symbols, current);
1857
1858        if (PyObject_TypeCheck((PyObject *)node, &PySyckSeq_Type)) {
1859            if (!PyList_Check(node->value)) {
1860                PyErr_SetString(PyExc_TypeError, "value of _syck.Seq must be a list");
1861                return -1;
1862            }
1863            l = PyList_GET_SIZE(node->value);
1864            for (k = 0; k < l; k ++) {
1865                item = PyList_GET_ITEM(node->value, k);
1866                if ((index = PyDict_GetItem(self->nodes, item))) {
1867                    syck_emitter_mark_node(self->emitter, PyInt_AS_LONG(index));
1868                }
1869                else {
1870                    syck_emitter_mark_node(self->emitter, ++last);
1871                    if (PyList_Append(self->symbols, item) < 0)
1872                        return -1;
1873                    index = PyInt_FromLong(last);
1874                    if (!index) return -1;
1875                    if (PyDict_SetItem(self->nodes, item, index) < 0) {
1876                        Py_DECREF(index);
1877                        return -1;
1878                    }
1879                    Py_DECREF(index);
1880                }
1881            }
1882        }
1883
1884        else if (PyObject_TypeCheck((PyObject *)node, &PySyckMap_Type)) {
1885           
1886            if (PyList_Check(node->value)) {
1887                l = PyList_GET_SIZE(node->value);
1888                for (k = 0; k < l; k ++) {
1889                    pair = PyList_GET_ITEM(node->value, k);
1890                    if (!PyTuple_Check(pair) || PyTuple_GET_SIZE(pair) != 2) {
1891                        PyErr_SetString(PyExc_TypeError,
1892                                "value of _syck.Map must be a list of pairs or a dictionary");
1893                        return -1;
1894                    }
1895                    for (j = 0; j < 2; j++) {
1896                        item = PyTuple_GET_ITEM(pair, j);
1897                        if ((index = PyDict_GetItem(self->nodes, item))) {
1898                            syck_emitter_mark_node(self->emitter, PyInt_AS_LONG(index));
1899                        }
1900                        else {
1901                            syck_emitter_mark_node(self->emitter, ++last);
1902                            if (PyList_Append(self->symbols, item) < 0)
1903                                return -1;
1904                            index = PyInt_FromLong(last);
1905                            if (!index) return -1;
1906                            if (PyDict_SetItem(self->nodes, item, index) < 0) {
1907                                Py_DECREF(index);
1908                                return -1;
1909                            }
1910                            Py_DECREF(index);
1911                        }
1912                    }
1913                }
1914               
1915            }
1916            else if (PyDict_Check(node->value)) {
1917                dict_pos = 0;
1918                while (PyDict_Next(node->value, &dict_pos, &key, &value)) {
1919                    for (j = 0; j < 2; j++) {
1920                        item = j ? value : key;
1921                        if ((index = PyDict_GetItem(self->nodes, item))) {
1922                            syck_emitter_mark_node(self->emitter, PyInt_AS_LONG(index));
1923                        }
1924                        else {
1925                            syck_emitter_mark_node(self->emitter, ++last);
1926                            if (PyList_Append(self->symbols, item) < 0)
1927                                return -1;
1928                            index = PyInt_FromLong(last);
1929                            if (!index) return -1;
1930                            if (PyDict_SetItem(self->nodes, item, index) < 0) {
1931                                Py_DECREF(index);
1932                                return -1;
1933                            }
1934                            Py_DECREF(index);
1935                        }
1936                    }
1937                }
1938            }
1939            else {
1940                PyErr_SetString(PyExc_TypeError,
1941                        "value of _syck.Map must be a list of pairs or a dictionary");
1942                return -1;
1943            }
1944        }
1945
1946        else if (!PyObject_TypeCheck((PyObject *)node, &PySyckScalar_Type)) {
1947            PyErr_SetString(PyExc_TypeError, "Node instance is required");
1948            return -1;
1949        }   
1950    }
1951    return 0;
1952}
1953
1954static PyObject *
1955PySyckEmitter_emit(PySyckEmitterObject *self, PyObject *args)
1956{
1957    PyObject *node;
1958
1959    if (self->emitting) {
1960        PyErr_SetString(PyExc_RuntimeError, "do not call Emitter.emit while it is already emitting");
1961        return NULL;
1962    }
1963
1964    if (self->halt) {
1965        Py_INCREF(Py_None);
1966        return Py_None;
1967    }
1968
1969    if (!PyArg_ParseTuple(args, "O", &node))
1970        return NULL;
1971
1972    self->emitting = 1;
1973
1974
1975    self->symbols = PyList_New(0);
1976    if (!self->symbols) {
1977        return NULL;
1978    }
1979    self->nodes = PyDict_New();
1980    if (!self->nodes) {
1981        Py_DECREF(self->symbols);
1982        self->symbols = NULL;
1983        return NULL;
1984    }
1985
1986    self->emitter = syck_new_emitter();
1987    self->emitter->bonus = self;
1988    self->emitter->headless = self->headless;
1989    self->emitter->use_header = self->use_header;
1990    self->emitter->use_version = self->use_version;
1991    self->emitter->explicit_typing = self->explicit_typing;
1992    self->emitter->style = self->style;
1993    self->emitter->best_width = self->best_width;
1994    self->emitter->indent = self->indent;
1995
1996    syck_emitter_handler(self->emitter, PySyckEmitter_node_handler);
1997    syck_output_handler(self->emitter, PySyckEmitter_write_handler);
1998
1999    if (PySyckEmitter_mark(self, node) < 0) {
2000        Py_DECREF(self->symbols);
2001        self->symbols = NULL;
2002        Py_DECREF(self->nodes);
2003        self->nodes = NULL;
2004        self->emitting = 0;
2005        self->halt = 1;
2006        syck_free_emitter(self->emitter);
2007        self->emitter = NULL;
2008        return NULL;
2009    }
2010
2011    Py_BEGIN_ALLOW_THREADS
2012    syck_emit(self->emitter, 0);
2013    syck_emitter_flush(self->emitter, 0);
2014    Py_END_ALLOW_THREADS
2015
2016    syck_free_emitter(self->emitter);
2017    self->emitter = NULL;
2018
2019    self->emitting = 0;
2020
2021    Py_DECREF(self->symbols);
2022    self->symbols = NULL;
2023    Py_DECREF(self->nodes);
2024    self->nodes = NULL;
2025
2026    if (self->halt) return NULL;
2027
2028    Py_INCREF(Py_None);
2029    return Py_None;
2030}
2031
2032PyDoc_STRVAR(PySyckEmitter_emit_doc,
2033    "emit(root_node) -> None\n\n"
2034    "Emits the Node tree to the output.\n");
2035
2036static PyMethodDef PySyckEmitter_methods[] = {
2037    {"emit",  (PyCFunction)PySyckEmitter_emit,
2038        METH_VARARGS, PySyckEmitter_emit_doc},
2039    {NULL}  /* Sentinel */
2040};
2041
2042static PyTypeObject PySyckEmitter_Type = {
2043    PyObject_HEAD_INIT(NULL)
2044    0,                                          /* ob_size */
2045    "_syck.Emitter",                            /* tp_name */
2046    sizeof(PySyckEmitterObject),                /* tp_basicsize */
2047    0,                                          /* tp_itemsize */
2048    (destructor)PySyckEmitter_dealloc,          /* tp_dealloc */
2049    0,                                          /* tp_print */
2050    0,                                          /* tp_getattr */
2051    0,                                          /* tp_setattr */
2052    0,                                          /* tp_compare */
2053    0,                                          /* tp_repr */
2054    0,                                          /* tp_as_number */
2055    0,                                          /* tp_as_sequence */
2056    0,                                          /* tp_as_mapping */
2057    0,                                          /* tp_hash */
2058    0,                                          /* tp_call */
2059    0,                                          /* tp_str */
2060    0,                                          /* tp_getattro */
2061    0,                                          /* tp_setattro */
2062    0,                                          /* tp_as_buffer */
2063    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,  /* tp_flags */
2064    PySyckEmitter_doc,                          /* tp_doc */
2065    (traverseproc)PySyckEmitter_traverse,       /* tp_traverse */
2066    (inquiry)PySyckEmitter_clear,               /* tp_clear */
2067    0,                                          /* tp_richcompare */
2068    0,                                          /* tp_weaklistoffset */
2069    0,                                          /* tp_iter */
2070    0,                                          /* tp_iternext */
2071    PySyckEmitter_methods,                      /* tp_methods */
2072    0,                                          /* tp_members */
2073    PySyckEmitter_getsetters,                   /* tp_getset */
2074    0,                                          /* tp_base */
2075    0,                                          /* tp_dict */
2076    0,                                          /* tp_descr_get */
2077    0,                                          /* tp_descr_set */
2078    0,                                          /* tp_dictoffset */
2079    (initproc)PySyckEmitter_init,               /* tp_init */
2080    0,                                          /* tp_alloc */
2081    PySyckEmitter_new,                          /* tp_new */
2082};
2083
2084/****************************************************************************
2085 * The module _syck.
2086 ****************************************************************************/
2087
2088static PyMethodDef PySyck_methods[] = {
2089    {NULL}  /* Sentinel */
2090};
2091
2092PyDoc_STRVAR(PySyck_doc,
2093    "_syck is a low-level wrapper for the Syck YAML parser and emitter.\n"
2094    "Do not use it directly, use the module 'syck' instead.\n");
2095
2096static int
2097add_slotnames(PyTypeObject *type)
2098{
2099    PyObject *slotnames;
2100    PyObject *name;
2101    PyGetSetDef *getsetter;
2102
2103    if (!type->tp_getset) return 0;
2104    if (!type->tp_dict) return 0;
2105
2106    slotnames = PyList_New(0);
2107    if (!slotnames) return -1;
2108
2109    for (getsetter = type->tp_getset; getsetter->name; getsetter++) {
2110        if (!getsetter->set) continue;
2111        name = PyString_FromString(getsetter->name);
2112        if (!name) {
2113           Py_DECREF(slotnames);
2114           return -1;
2115        }
2116        if (PyList_Append(slotnames, name) < 0) {
2117            Py_DECREF(name);
2118            Py_DECREF(slotnames);
2119            return -1;
2120        }
2121        Py_DECREF(name);
2122    }
2123
2124    if (PyDict_SetItemString(type->tp_dict, "__slotnames__", slotnames) < 0) {
2125        Py_DECREF(slotnames);
2126        return -1;
2127    }
2128
2129    Py_DECREF(slotnames);
2130    return 0;
2131}
2132
2133PyMODINIT_FUNC
2134init_syck(void)
2135{
2136    PyObject *m;
2137
2138    if (PyType_Ready(&PySyckNode_Type) < 0)
2139        return;
2140    if (PyType_Ready(&PySyckScalar_Type) < 0)
2141        return;
2142    if (add_slotnames(&PySyckScalar_Type) < 0)
2143        return;
2144    if (PyType_Ready(&PySyckSeq_Type) < 0)
2145        return;
2146    if (add_slotnames(&PySyckSeq_Type) < 0)
2147        return;
2148    if (PyType_Ready(&PySyckMap_Type) < 0)
2149        return;
2150    if (add_slotnames(&PySyckMap_Type) < 0)
2151        return;
2152    if (PyType_Ready(&PySyckParser_Type) < 0)
2153        return;
2154    if (PyType_Ready(&PySyckEmitter_Type) < 0)
2155        return;
2156   
2157    PySyck_Error = PyErr_NewException("_syck.error", NULL, NULL);
2158    if (!PySyck_Error) return;
2159
2160    PySyck_ScalarKind = PyString_FromString("scalar");
2161    if (!PySyck_ScalarKind) return;
2162    PySyck_SeqKind = PyString_FromString("seq");
2163    if (!PySyck_SeqKind) return;
2164    PySyck_MapKind = PyString_FromString("map");
2165    if (!PySyck_MapKind) return;
2166
2167    PySyck_1QuoteStyle = PyString_FromString("1quote");
2168    if (!PySyck_1QuoteStyle) return;
2169    PySyck_2QuoteStyle = PyString_FromString("2quote");
2170    if (!PySyck_2QuoteStyle) return;
2171    PySyck_FoldStyle = PyString_FromString("fold");
2172    if (!PySyck_FoldStyle) return;
2173    PySyck_LiteralStyle = PyString_FromString("literal");
2174    if (!PySyck_LiteralStyle) return;
2175    PySyck_PlainStyle = PyString_FromString("plain");
2176    if (!PySyck_PlainStyle) return;
2177
2178    PySyck_StripChomp = PyString_FromString("-");
2179    if (!PySyck_StripChomp) return;
2180    PySyck_KeepChomp = PyString_FromString("+");
2181    if (!PySyck_KeepChomp) return;
2182
2183    m = Py_InitModule3("_syck", PySyck_methods, PySyck_doc);
2184
2185    Py_INCREF(PySyck_Error);
2186    if (PyModule_AddObject(m, "error", (PyObject *)PySyck_Error) < 0)
2187        return;
2188    Py_INCREF(&PySyckNode_Type);
2189    if (PyModule_AddObject(m, "Node", (PyObject *)&PySyckNode_Type) < 0)
2190        return;
2191    Py_INCREF(&PySyckScalar_Type);
2192    if (PyModule_AddObject(m, "Scalar", (PyObject *)&PySyckScalar_Type) < 0)
2193        return;
2194    Py_INCREF(&PySyckSeq_Type);
2195    if (PyModule_AddObject(m, "Seq", (PyObject *)&PySyckSeq_Type) < 0)
2196        return;
2197    Py_INCREF(&PySyckMap_Type);
2198    if (PyModule_AddObject(m, "Map", (PyObject *)&PySyckMap_Type) < 0)
2199        return;
2200    Py_INCREF(&PySyckParser_Type);
2201    if (PyModule_AddObject(m, "Parser", (PyObject *)&PySyckParser_Type) < 0)
2202        return;
2203    Py_INCREF(&PySyckEmitter_Type);
2204    if (PyModule_AddObject(m, "Emitter", (PyObject *)&PySyckEmitter_Type) < 0)
2205        return;
2206}
2207
Note: See TracBrowser for help on using the repository browser.