Changeset 4 for trunk


Ignore:
Timestamp:
07/16/05 15:14:11 (9 years ago)
Author:
xi
Message:

Add the module _syck and test suite.

Location:
trunk
Files:
4 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Makefile

    r3 r4  
    11 
    2 .PHONY: default build install test clean 
     2.PHONY: default build force install test clean 
    33 
    44PYTHON=/usr/bin/python 
     
    1010        ${PYTHON} setup.py build 
    1111 
     12force: 
     13        ${PYTHON} setup.py build -f 
     14 
    1215install: build 
    1316        ${PYTHON} setup.py install 
    1417 
    1518test: build 
    16         ${PYTHON} tests/test_build.py ${TEST} 
     19        ${PYTHON} tests/test_build.py -v ${TEST} 
    1720 
    1821clean: 
  • trunk/ext/_syckmodule.c

    r3 r4  
    33#include <syck.h> 
    44 
    5 static PyMethodDef _syck_methods[] = { 
     5/* Global objects. */ 
     6 
     7static PyObject *_syck_Error; 
     8 
     9static PyObject *_syck_ScalarKind; 
     10static PyObject *_syck_SeqKind; 
     11static PyObject *_syck_MapKind; 
     12 
     13/* Node type. */ 
     14 
     15typedef struct { 
     16    PyObject_HEAD 
     17    PyObject *kind; 
     18    PyObject *type_id; 
     19    PyObject *value; 
     20} _syck_Node; 
     21 
     22static void 
     23_syck_Node_dealloc(_syck_Node *self) 
     24{ 
     25    Py_XDECREF(self->kind); 
     26    Py_XDECREF(self->type_id); 
     27    Py_XDECREF(self->value); 
     28    PyObject_Del(self); 
     29} 
     30 
     31static PyObject * 
     32_syck_Node_getattr(_syck_Node *self, char *name) 
     33{ 
     34    PyObject *value; 
     35 
     36    if (strcmp(name, "kind") == 0) 
     37        value = self->kind; 
     38    else if (strcmp(name, "type_id") == 0) 
     39        value = self->type_id; 
     40    else if (strcmp(name, "value") == 0) 
     41        value = self->value; 
     42    else { 
     43        PyErr_SetString(PyExc_AttributeError, name); 
     44        return NULL; 
     45    } 
     46 
     47    Py_INCREF(value); 
     48    return value; 
     49} 
     50 
     51static char _syck_Node_doc[] = 
     52    "Node object\n" 
     53    "\n" 
     54    "Attributes of the Node object:\n\n" 
     55    "kind -- 'scalar', 'seq', or 'map'.\n" 
     56    "type_id -- the tag of the node.\n" 
     57    "value -- the value of the node, a string, list or dict object.\n"; 
     58 
     59static PyTypeObject _syck_NodeType = { 
     60    PyObject_HEAD_INIT(NULL) 
     61    0,                                  /* ob_size */ 
     62    "_syck.Node",                       /* tp_name */ 
     63    sizeof(_syck_Node),                 /* tp_basicsize */ 
     64    0,                                  /* tp_itemsize */ 
     65    (destructor)_syck_Node_dealloc,     /* tp_dealloc */ 
     66    0,                                  /* tp_print */ 
     67    (getattrfunc)_syck_Node_getattr,    /* tp_getattr */ 
     68    0,                                  /* tp_setattr */ 
     69    0,                                  /* tp_compare */ 
     70    0,                                  /* tp_repr */ 
     71    0,                                  /* tp_as_number */ 
     72    0,                                  /* tp_as_sequence */ 
     73    0,                                  /* tp_as_mapping */ 
     74    0,                                  /* tp_hash */ 
     75    0,                                  /* tp_call */ 
     76    0,                                  /* tp_str */ 
     77    0,                                  /* tp_getattro */ 
     78    0,                                  /* tp_setattro */ 
     79    0,                                  /* tp_as_buffer */ 
     80    Py_TPFLAGS_DEFAULT,                 /* tp_flags */ 
     81    _syck_Node_doc,                     /* tp_doc */ 
     82}; 
     83 
     84static PyObject * 
     85_syck_NewNode(PyObject *self, PyObject *args) 
     86{ 
     87    if (!PyArg_ParseTuple(args, ":_syck.Node")) 
     88        return NULL; 
     89 
     90    PyErr_SetString(PyExc_TypeError, "Node object cannot be created explicitly. Use _syck.Parser.parse() instead."); 
     91    return NULL; 
     92} 
     93 
     94static char _syck_NewNode_doc[] = 
     95    "Node object cannot be created explicitly. Use _syck.Parser.parse() instead."; 
     96 
     97static PyObject * 
     98_syck_NewNode_FromValue(char *type_id, PyObject *value) /* Note: steals the reference to the value. */ 
     99{ 
     100    _syck_Node *self; 
     101    PyObject *kind; 
     102 
     103    self = PyObject_NEW(_syck_Node, &_syck_NodeType); 
     104    if (!self) { 
     105        Py_XDECREF(value); 
     106        return NULL; 
     107    } 
     108 
     109    self->value = value; 
     110 
     111    if (PyList_Check(value)) 
     112        kind = _syck_SeqKind; 
     113    else if (PyDict_Check(value)) 
     114        kind = _syck_MapKind; 
     115    else 
     116        kind = _syck_ScalarKind; 
     117    Py_INCREF(kind); 
     118    self->kind = kind; 
     119 
     120    if (type_id) { 
     121        self->type_id = PyString_FromString(type_id); 
     122        if (!self->type_id) { 
     123            Py_DECREF(self); 
     124            return NULL; 
     125        } 
     126    } 
     127    else { 
     128        Py_INCREF(Py_None); 
     129        self->type_id = Py_None; 
     130    } 
     131 
     132    return (PyObject *)self; 
     133} 
     134 
     135/* Parser type. */ 
     136 
     137typedef struct { 
     138    PyObject_HEAD 
     139    PyObject *source; 
     140    PyObject *resolver; 
     141    PyObject *symbols; 
     142    int error_state; 
     143    int mark; 
     144    SyckParser *parser; 
     145} _syck_Parser; 
     146 
     147static PyObject * 
     148_syck_Parser_parse(_syck_Parser *self, PyObject *args) 
     149{ 
     150    SYMID index; 
     151    PyObject *value; 
     152 
     153    if (!PyArg_ParseTuple(args, ":parse")) 
     154        return NULL; 
     155 
     156    if (!self->parser) { 
     157        PyErr_SetString(PyExc_TypeError, "Parser object is closed"); 
     158        return NULL; 
     159    } 
     160 
     161    self->symbols = PyList_New(0); 
     162    if (!self->symbols) { 
     163        return NULL; 
     164    } 
     165 
     166    index = syck_parse(self->parser); 
     167    if (!self->error_state && !self->parser->eof) { 
     168        value = PyList_GetItem(self->symbols, index-1); 
     169    } 
     170 
     171    Py_DECREF(self->symbols); 
     172 
     173    if (self->error_state) { 
     174        self->error_state = 0; 
     175        return NULL; 
     176    } 
     177 
     178    if (self->parser->eof) { 
     179        Py_INCREF(Py_None); 
     180        return Py_None; 
     181    } 
     182     
     183    return value; 
     184} 
     185 
     186static char _syck_Parser_parse_doc[] = 
     187    "Parses the next document in the YAML stream, return the root Node object or None on EOF."; 
     188 
     189static PyObject * 
     190_syck_Parser_parse_documents(_syck_Parser *self, PyObject *args) 
     191{ 
     192    SYMID index; 
     193    PyObject *value = NULL; 
     194    PyObject *result = NULL; 
     195 
     196    if (!PyArg_ParseTuple(args, ":parse_document")) 
     197        return NULL; 
     198 
     199    if (!self->parser) { 
     200        PyErr_SetString(PyExc_TypeError, "Parser object is closed"); 
     201        return NULL; 
     202    } 
     203 
     204    result = PyList_New(0); 
     205    if (!result) return NULL; 
     206 
     207    while (1) { 
     208 
     209        self->symbols = PyList_New(0); 
     210        if (!self->symbols) { 
     211            Py_DECREF(result); 
     212            return NULL; 
     213        }; 
     214 
     215        index = syck_parse(self->parser); 
     216 
     217        if (!self->error_state && !self->parser->eof) { 
     218            value = PyList_GetItem(self->symbols, index-1); 
     219            if (!value) { 
     220                Py_DECREF(self->symbols); 
     221                Py_DECREF(result); 
     222                return NULL; 
     223            } 
     224            if (PyList_Append(result, value) < 0) { 
     225                Py_DECREF(self->symbols); 
     226                Py_DECREF(value); 
     227                Py_DECREF(result); 
     228                return NULL; 
     229            } 
     230            Py_DECREF(value); 
     231        } 
     232 
     233        Py_DECREF(self->symbols); 
     234 
     235        if (self->error_state) { 
     236            self->error_state = 0; 
     237            Py_DECREF(result); 
     238            return NULL; 
     239        } 
     240 
     241        if (self->parser->eof) break; 
     242    } 
     243 
     244    return result; 
     245} 
     246 
     247static char _syck_Parser_parse_documents_doc[] = 
     248    "Parses the entire YAML stream and returns list of documents."; 
     249 
     250static PyObject * 
     251_syck_Parser_close(_syck_Parser *self, PyObject *args) 
     252{ 
     253    if (!PyArg_ParseTuple(args, ":close")) 
     254        return NULL; 
     255 
     256    Py_XDECREF(self->source); 
     257    self->source = NULL; 
     258 
     259    if (self->parser) { 
     260        syck_free_parser(self->parser); 
     261    } 
     262    self->parser = NULL; 
     263 
     264    Py_INCREF(Py_None); 
     265    return Py_None; 
     266} 
     267 
     268static char _syck_Parser_close_doc[] = 
     269    "Closes the parser and frees memory"; 
     270 
     271static PyMethodDef _syck_Parser_methods[] = { 
     272    {"parse",  (PyCFunction)_syck_Parser_parse, METH_VARARGS, _syck_Parser_parse_doc}, 
     273    {"parse_documents",  (PyCFunction)_syck_Parser_parse_documents, METH_VARARGS, _syck_Parser_parse_documents_doc}, 
     274    {"close",  (PyCFunction)_syck_Parser_close, METH_VARARGS, _syck_Parser_close_doc}, 
    6275    {NULL}  /* Sentinel */ 
    7276}; 
    8277 
     278static void 
     279_syck_Parser_dealloc(_syck_Parser *self) 
     280{ 
     281    Py_XDECREF(self->source); 
     282    if (self->parser) { 
     283        syck_free_parser(self->parser); 
     284    } 
     285    PyObject_Del(self); 
     286} 
     287 
     288static PyObject * 
     289_syck_Parser_getattr(_syck_Parser *self, char *name) 
     290{ 
     291    return Py_FindMethod(_syck_Parser_methods, (PyObject *)self, name); 
     292} 
     293 
     294static char _syck_Parser_doc[] = 
     295    "_syck.Parser(yaml_string_or_file, implicit_typing=True, taguri_expansion=True) -> Parser object\n" 
     296    "\n" 
     297    "Methods of the Parser object:\n\n" 
     298    "parse() -- Parses the next document in the YAML stream, return the root Node object or None on EOF.\n" 
     299    "parse_documents() -- Parses the entire YAML stream and returns list of documents.\n" 
     300    "close() -- Closes the parser and frees memory.\n"; 
     301 
     302static PyTypeObject _syck_ParserType = { 
     303    PyObject_HEAD_INIT(NULL) 
     304    0,                                  /* ob_size */ 
     305    "_syck.Parser",                     /* tp_name */ 
     306    sizeof(_syck_Parser),               /* tp_basicsize */ 
     307    0,                                  /* tp_itemsize */ 
     308    (destructor)_syck_Parser_dealloc,   /* tp_dealloc */ 
     309    0,                                  /* tp_print */ 
     310    (getattrfunc)_syck_Parser_getattr,  /* tp_getattr */ 
     311    0,                                  /* tp_setattr */ 
     312    0,                                  /* tp_compare */ 
     313    0,                                  /* tp_repr */ 
     314    0,                                  /* tp_as_number */ 
     315    0,                                  /* tp_as_sequence */ 
     316    0,                                  /* tp_as_mapping */ 
     317    0,                                  /* tp_hash */ 
     318    0,                                  /* tp_call */ 
     319    0,                                  /* tp_str */ 
     320    0,                                  /* tp_getattro */ 
     321    0,                                  /* tp_setattro */ 
     322    0,                                  /* tp_as_buffer */ 
     323    Py_TPFLAGS_DEFAULT,                 /* tp_flags */ 
     324    _syck_Parser_doc,                   /* tp_doc */ 
     325}; 
     326 
     327static long 
     328_syck_Parser_io_file_read(char *buf, SyckIoFile *file, long max_size, long skip) 
     329{ 
     330    _syck_Parser *runtime = (_syck_Parser *)file->ptr; 
     331 
     332    PyObject *value; 
     333 
     334    char *str; 
     335    int length; 
     336 
     337    buf[skip] = '\0'; 
     338 
     339    if (runtime->error_state) { 
     340        return skip; 
     341    } 
     342     
     343    max_size -= skip; 
     344 
     345    value = PyObject_CallMethod(runtime->source, "read", "(i)", max_size); 
     346    if (!value) { 
     347        runtime->error_state = 1; 
     348        return skip; 
     349    } 
     350 
     351    if (!PyString_Check(value)) { 
     352        Py_DECREF(value); 
     353        PyErr_SetString(PyExc_TypeError, "file-like object should return a string"); 
     354        runtime->error_state = 1; 
     355         
     356        return skip; 
     357    } 
     358 
     359    str = PyString_AS_STRING(value); 
     360    length = PyString_GET_SIZE(value); 
     361    if (!length) { 
     362        Py_DECREF(value); 
     363        return skip; 
     364    } 
     365 
     366    if (length > max_size) { 
     367        Py_DECREF(value); 
     368        PyErr_SetString(PyExc_ValueError, "read returns an overly long string"); 
     369        runtime->error_state = 1; 
     370        return skip; 
     371    } 
     372 
     373    memcpy(buf+skip, str, length); 
     374    length += skip; 
     375    buf[length] = '\0'; 
     376 
     377    Py_DECREF(value); 
     378 
     379    return length; 
     380} 
     381 
     382static SYMID 
     383_syck_Parser_node_handler(SyckParser *parser, SyckNode *node) 
     384{ 
     385    _syck_Parser *runtime = (_syck_Parser *)parser->bonus; 
     386 
     387    SYMID index; 
     388    PyObject *object = NULL; 
     389 
     390    PyObject *key, *value, *item; 
     391    int k; 
     392 
     393    if (runtime->error_state) 
     394        return 0; 
     395 
     396    switch (node->kind) { 
     397 
     398        case syck_str_kind: 
     399            object = PyString_FromStringAndSize(node->data.str->ptr, 
     400                    node->data.str->len); 
     401            if (!object) goto error; 
     402            break; 
     403 
     404        case syck_seq_kind: 
     405            object = PyList_New(node->data.list->idx); 
     406            if (!object) goto error; 
     407            for (k = 0; k < node->data.list->idx; k++) { 
     408                index = syck_seq_read(node, k); 
     409                item = PyList_GetItem(runtime->symbols, index-1); 
     410                if (!item) goto error; 
     411                Py_INCREF(item); 
     412                PyList_SET_ITEM(object, k, item); 
     413            } 
     414            break; 
     415 
     416        case syck_map_kind: 
     417            object = PyDict_New(); 
     418            if (!object) goto error; 
     419            for (k = 0; k < node->data.pairs->idx; k++) 
     420            { 
     421                index = syck_map_read(node, map_key, k); 
     422                key = PyList_GetItem(runtime->symbols, index-1); 
     423                if (!key) goto error; 
     424                index = syck_map_read(node, map_value, k); 
     425                value = PyList_GetItem(runtime->symbols, index-1); 
     426                if (!value) goto error; 
     427                if (PyDict_SetItem(object, key, value) < 0) 
     428                    goto error; 
     429            } 
     430            break; 
     431    } 
     432 
     433    object = _syck_NewNode_FromValue(node->type_id, object); 
     434    if (!object) goto error; 
     435 
     436    if (PyList_Append(runtime->symbols, object) < 0) 
     437        goto error; 
     438 
     439    index = PyList_Size(runtime->symbols); 
     440    return index; 
     441 
     442error: 
     443    Py_XDECREF(object); 
     444    runtime->error_state = 1; 
     445    return 0; 
     446} 
     447 
     448static void 
     449_syck_Parser_error_handler(SyckParser *parser, char *str) 
     450{ 
     451    _syck_Parser *runtime = (_syck_Parser *)parser->bonus; 
     452    PyObject *value; 
     453 
     454    if (runtime->error_state) return; 
     455 
     456    runtime->error_state = 1; 
     457 
     458    value = Py_BuildValue("(sii)", str, parser->linect, parser->cursor-parser->lineptr); 
     459    if (value) { 
     460        PyErr_SetObject(_syck_Error, value); 
     461    } 
     462} 
     463 
     464static PyObject * 
     465_syck_NewParser(PyObject *self, PyObject *args, PyObject *kwds) 
     466{ 
     467    _syck_Parser *parser; 
     468    PyObject *source; 
     469    int implicit_typing = 1; 
     470    int taguri_expansion = 1; 
     471 
     472    static char *kwdlist[] = {"source", "implicit_typing", "taguri_expansion", NULL}; 
     473 
     474    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|ii", kwdlist, 
     475                &source, &implicit_typing, &taguri_expansion)) 
     476        return NULL; 
     477 
     478    parser = PyObject_NEW(_syck_Parser, &_syck_ParserType); 
     479    if (!parser) 
     480        return NULL; 
     481 
     482    Py_INCREF(source); 
     483    parser->source = source; 
     484    parser->error_state = 0; 
     485 
     486    parser->parser = syck_new_parser(); 
     487    parser->parser->bonus = parser; 
     488 
     489    if (PyString_Check(source)) { 
     490        syck_parser_str_auto(parser->parser, PyString_AS_STRING(source), NULL); 
     491    } 
     492    else { 
     493        syck_parser_file(parser->parser, (FILE *)parser, _syck_Parser_io_file_read); 
     494    } 
     495    syck_parser_implicit_typing(parser->parser, implicit_typing); 
     496    syck_parser_taguri_expansion(parser->parser, taguri_expansion); 
     497 
     498    syck_parser_handler(parser->parser, _syck_Parser_node_handler); 
     499    syck_parser_error_handler(parser->parser, _syck_Parser_error_handler); 
     500    /* 
     501    syck_parser_bad_anchor_handler(parser, _syck_Parser_bad_anchor_handler); 
     502    */ 
     503 
     504    return (PyObject *)parser; 
     505} 
     506 
     507static char _syck_NewParser_doc[] = 
     508    "Creates a new Parser object."; 
     509 
     510/* The module definitions. */ 
     511 
     512static PyMethodDef _syck_methods[] = { 
     513    {"Node",  (PyCFunction)_syck_NewNode, METH_VARARGS, _syck_NewNode_doc}, 
     514    {"Parser",  (PyCFunction)_syck_NewParser, METH_VARARGS|METH_KEYWORDS, _syck_NewParser_doc}, 
     515    {NULL}  /* Sentinel */ 
     516}; 
     517 
    9518static char _syck_doc[] = 
    10519    "This module provides low-level access to the Syck parser and emitter.\n" 
    11     "Do not use this module directly, use the module 'syck' instead.\n"; 
     520    "Do not use this module directly, use the package 'syck' instead.\n"; 
    12521 
    13522PyMODINIT_FUNC 
    14523init_syck(void) 
    15524{ 
    16     Py_InitModule3("_syck", _syck_methods, _syck_doc); 
    17 } 
    18  
     525    PyObject *m; 
     526 
     527    _syck_NodeType.ob_type = &PyType_Type; 
     528    _syck_ParserType.ob_type = &PyType_Type; 
     529 
     530    _syck_Error = PyErr_NewException("_syck.error", NULL, NULL); 
     531    if (!_syck_Error) 
     532        return; 
     533 
     534    _syck_ScalarKind = PyString_FromString("scalar"); 
     535    if (!_syck_ScalarKind) 
     536        return; 
     537    _syck_SeqKind = PyString_FromString("seq"); 
     538    if (!_syck_SeqKind) 
     539        return; 
     540    _syck_MapKind = PyString_FromString("map"); 
     541    if (!_syck_MapKind) 
     542        return; 
     543 
     544    m = Py_InitModule3("_syck", _syck_methods, _syck_doc); 
     545 
     546    Py_INCREF(_syck_Error); 
     547    if (!PyModule_AddObject(m, "error", _syck_Error) < 0) 
     548        return; 
     549 
     550    Py_INCREF(&_syck_NodeType); 
     551    if (PyModule_AddObject(m, "NodeType", (PyObject *)&_syck_NodeType) < 0) 
     552        return; 
     553 
     554    Py_INCREF(&_syck_ParserType); 
     555    if (PyModule_AddObject(m, "ParserType", (PyObject *)&_syck_ParserType) < 0) 
     556        return; 
     557} 
     558 
  • trunk/sandbox/syck-parser/syck-parser.c

    r2 r4  
    4141        m->type_id = strdup(n->type_id); 
    4242    } 
    43     else { 
     43/*    else { 
    4444        m->type_id = strdup(""); 
    45     } 
     45    }*/ 
    4646    if (n->anchor) { 
    4747        m->anchor = strdup(n->anchor); 
    4848    } 
    49     else { 
     49/*    else { 
    5050        m->anchor = strdup(""); 
    51     } 
     51    }*/ 
    5252 
    5353    return m; 
     
    173173 
    174174    syck_parser_handler(p, node_handler); 
    175     syck_parser_error_handler(p, error_handler); 
     175//    syck_parser_error_handler(p, error_handler); 
    176176    syck_parser_bad_anchor_handler(p, bad_anchor_handler); 
    177177 
  • trunk/tests/test_syck.py

    r3 r4  
    11 
    22import unittest 
    3  
    43import _syck, syck 
    5  
    6  
    7 class Test1(unittest.TestCase): 
    8  
    9     def testme(self): 
    10         pass 
    11  
    12 class Test2(unittest.TestCase): 
    13  
    14     def testmetoo(self): 
    15         pass 
     4import StringIO 
     5 
     6EXAMPLE = """ 
     7- 
     8  avg: 0.278 
     9  hr: 65 
     10  name: Mark McGwire 
     11- 
     12  avg: 0.288 
     13  hr: 63 
     14  name: Sammy Sosa 
     15""" 
     16 
     17INVALID = """ 
     18 - invalid 
     19- document 
     20""", 2, 0 
     21 
     22COMPARE1 = """ 
     23one: foo 
     24two: bar 
     25three: baz 
     26""", { 
     27    'one': 'foo', 
     28    'two': 'bar', 
     29    'three': 'baz', 
     30} 
     31 
     32COMPARE2 = """ 
     33- Mark McGwire 
     34- Sammy Sosa 
     35- Ken Griffey 
     36""", [ 
     37    'Mark McGwire', 
     38    'Sammy Sosa', 
     39    'Ken Griffey', 
     40] 
     41 
     42COMPARE3 = """ 
     43american: 
     44  - Boston Red Sox 
     45  - Detroit Tigers 
     46  - New York Yankees 
     47national: 
     48  - New York Mets 
     49  - Chicago Cubs 
     50  - Atlanta Braves 
     51""", { 
     52    'american': [ 
     53        'Boston Red Sox', 
     54        'Detroit Tigers', 
     55        'New York Yankees', 
     56    ], 
     57    'national': [ 
     58        'New York Mets', 
     59        'Chicago Cubs', 
     60        'Atlanta Braves', 
     61    ], 
     62} 
     63 
     64DOCUMENTS0 = "" 
     65 
     66DOCUMENTS1 = """ 
     67--- 
     68Time: 2001-11-23 15:01:42 -05:00 
     69User: ed 
     70Warning: > 
     71  This is an error message 
     72  for the log file 
     73""" 
     74 
     75DOCUMENTS2 = """ 
     76--- 
     77Time: 2001-11-23 15:01:42 -05:00 
     78User: ed 
     79Warning: > 
     80  This is an error message 
     81  for the log file 
     82--- 
     83Time: 2001-11-23 15:02:31 -05:00 
     84User: ed 
     85Warning: > 
     86  A slightly different error 
     87  message. 
     88""" 
     89 
     90DOCUMENTS3 = """ 
     91--- 
     92Time: 2001-11-23 15:01:42 -05:00 
     93User: ed 
     94Warning: > 
     95  This is an error message 
     96  for the log file 
     97--- 
     98Time: 2001-11-23 15:02:31 -05:00 
     99User: ed 
     100Warning: > 
     101  A slightly different error 
     102  message. 
     103--- 
     104Date: 2001-11-23 15:03:17 -05:00 
     105User: ed 
     106Fatal: > 
     107  Unknown variable "bar" 
     108Stack: 
     109  - file: TopClass.py 
     110    line: 23 
     111    code: | 
     112      x = MoreObject("345\\n") 
     113  - file: MoreClass.py 
     114    line: 58 
     115    code: |- 
     116      foo = bar 
     117""" 
     118 
     119IMPLICIT_TYPING = """ 
     120- 'foo' 
     121- >- 
     122  bar 
     123- baz 
     124- 123 
     125- 3.14 
     126- true 
     127- false 
     128- [] 
     129- {} 
     130""", [ 
     131    ('str', True), 
     132    ('str', True), 
     133    ('str', False), 
     134    ('int', False), 
     135    ('float#fix', False), 
     136    ('bool#yes', False), 
     137    ('bool#no', False), 
     138    (None, False), 
     139    (None, False), 
     140] 
     141 
     142EXPLICIT_TYPING = """ 
     143- !int '123' 
     144- !yamltype 'foo' 
     145- !python/type 'bar' 
     146- !domain.tld,2002/type 'baz' 
     147- !!private 'private' 
     148- !map {} 
     149- !seq [] 
     150""", [ 
     151    'tag:yaml.org,2002:int', 
     152    'tag:yaml.org,2002:yamltype', 
     153    'tag:python.yaml.org,2002:type', 
     154    'tag:domain.tld,2002:type', 
     155    'x-private:private', 
     156    'tag:yaml.org,2002:map', 
     157    'tag:yaml.org,2002:seq', 
     158] 
     159 
     160class TestTypes(unittest.TestCase): 
     161 
     162    def testParserType(self): 
     163        parser = _syck.Parser(EXAMPLE) 
     164        self.assertEqual(type(parser), _syck.ParserType) 
     165        parser.close() 
     166 
     167    def testNodeType(self): 
     168        parser = _syck.Parser(EXAMPLE) 
     169        document = parser.parse() 
     170        self.assertEqual(type(document), _syck.NodeType) 
     171        parser.close() 
     172 
     173    def testNodeType2(self): 
     174        self.assertRaises(TypeError, (lambda: _syck.Node())) 
     175 
     176class TestErrors(unittest.TestCase): 
     177 
     178    def testError(self): 
     179        parser = _syck.Parser(INVALID[0]) 
     180        self.assertRaises(_syck.error, (lambda: parser.parse())) 
     181        parser.close() 
     182 
     183    def testErrorLocation(self): 
     184        source, line, column = INVALID 
     185        parser = _syck.Parser(source) 
     186        try: 
     187            parser.parse() 
     188            raise Exception 
     189        except _syck.error, e: 
     190            self.assertEqual(e.args[1], line) 
     191            self.assertEqual(e.args[2], column) 
     192 
     193class TestValuesAndSources(unittest.TestCase): 
     194 
     195    def testValues1(self): 
     196        self._testValues(COMPARE1) 
     197 
     198    def testValues2(self): 
     199        self._testValues(COMPARE2) 
     200 
     201    def testValues3(self): 
     202        self._testValues(COMPARE3) 
     203 
     204    def testFileValues1(self): 
     205        self._testFileValues(COMPARE1) 
     206 
     207    def testFileValues2(self): 
     208        self._testFileValues(COMPARE2) 
     209 
     210    def testFileValues3(self): 
     211        self._testFileValues(COMPARE3) 
     212 
     213    def testNonsense(self): 
     214        parser = _syck.Parser(None) 
     215        self.assertRaises(AttributeError, (lambda: parser.parse())) 
     216        parser.close() 
     217 
     218    def _testValues(self, (source, structure)): 
     219        parser = _syck.Parser(source) 
     220        document = parser.parse() 
     221        self.assertEqualStructure(document, structure) 
     222        parser.close() 
     223 
     224    def _testFileValues(self, (source, structure)): 
     225        parser = _syck.Parser(StringIO.StringIO(source)) 
     226        document = parser.parse() 
     227        self.assertEqualStructure(document, structure) 
     228        parser.close() 
     229 
     230    def assertEqualStructure(self, node, structure): 
     231        if node.kind == 'scalar': 
     232            self.assertEqual(type(structure), str) 
     233            self.assertEqual(node.value, structure) 
     234        elif node.kind == 'seq': 
     235            self.assertEqual(type(structure), list) 
     236            self.assertEqual(len(node.value), len(structure)) 
     237            for i, item in enumerate(node.value): 
     238                self.assertEqualStructure(item, structure[i]) 
     239        elif node.kind == 'map': 
     240            self.assertEqual(type(structure), dict) 
     241            self.assertEqual(len(node.value), len(structure)) 
     242            for key in node.value: 
     243                self.assert_(key.value in structure) 
     244                self.assertEqualStructure(node.value[key], structure[key.value]) 
     245 
     246class TestDocuments(unittest.TestCase): 
     247 
     248    def testDocuments0(self): 
     249        self._testDocuments(DOCUMENTS0, 0) 
     250 
     251    def testDocuments1(self): 
     252        self._testDocuments(DOCUMENTS1, 1) 
     253 
     254    def testDocuments2(self): 
     255        self._testDocuments(DOCUMENTS2, 2) 
     256 
     257    def testDocuments3(self): 
     258        self._testDocuments(DOCUMENTS3, 3) 
     259 
     260    def _testDocuments(self, source, length): 
     261        parser = _syck.Parser(source) 
     262        documents = parser.parse_documents() 
     263        self.assertEqual(len(documents), length) 
     264        parser.close() 
     265        parser = _syck.Parser(source) 
     266        for k in range(length): 
     267            document = parser.parse() 
     268            self.assert_(document) 
     269        self.assertEqual(parser.parse(), None) 
     270        parser.close() 
     271 
     272class TestImplicitTyping(unittest.TestCase): 
     273 
     274    def testImplicitAndExpansionTyping(self): 
     275        self._testTyping(True, True) 
     276 
     277    def testImplicitTyping(self): 
     278        self._testTyping(True, False) 
     279 
     280    def testExpansionTyping(self): 
     281        self._testTyping(False, True) 
     282 
     283    def testNoTyping(self): 
     284        self._testTyping(False, False) 
     285 
     286    def _testTyping(self, implicit_typing, taguri_expansion): 
     287        parser = _syck.Parser(IMPLICIT_TYPING[0], implicit_typing, taguri_expansion) 
     288        for node, (type_id, explicit) in zip(parser.parse().value, IMPLICIT_TYPING[1]): 
     289            if type_id is not None and taguri_expansion: 
     290                type_id = 'tag:yaml.org,2002:%s' % type_id 
     291            if implicit_typing or explicit: 
     292                self.assertEqual(node.type_id, type_id) 
     293            else: 
     294                self.assertEqual(node.type_id, None) 
     295 
     296class TestExplicitTyping(unittest.TestCase): 
     297 
     298    def testExplicitTyping(self): 
     299        parser = _syck.Parser(EXPLICIT_TYPING[0]) 
     300        for node, type_id in zip(parser.parse().value, EXPLICIT_TYPING[1]): 
     301            self.assertEqual(node.type_id, type_id) 
    16302 
    17303def main(module='__main__'): 
Note: See TracChangeset for help on using the changeset viewer.