Changeset 15
- Timestamp:
- 07/28/05 19:40:56 (8 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
- 2 moved
-
ext/_syckmodule.c (modified) (16 diffs)
-
tests/test_high_level_parser.py (moved) (moved from trunk/tests/test_high_parser.py) (3 diffs)
-
tests/test_low_level_parser.py (moved) (moved from trunk/tests/test_low_parser.py) (9 diffs)
-
tests/test_syck.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/ext/_syckmodule.c
r14 r15 42 42 43 43 PyDoc_STRVAR(PySyckNode_doc, 44 " The base Node type\n\n"44 "_syck.Node() -> TypeError\n\n" 45 45 "_syck.Node is an abstract type. It is a base type for _syck.Scalar,\n" 46 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 .\n");47 "directly. You may use _syck.Node for type checking or subclassing.\n"); 48 48 49 49 typedef struct { … … 220 220 " -> a Scalar node\n\n" 221 221 "_syck.Scalar represents a scalar node in Syck parser and emitter\n" 222 "graphs. A scalar node points to a single string value.\n\n" 223 "Attributes:\n\n" 224 "kind -- always 'scalar'; read-only\n" 225 "value -- the node value, a string\n" 226 "tag -- the node tag; a string or None\n" 227 "anchor -- the name of the node anchor or None; read-only\n" 228 "style -- the node style; None (means literal or plain),\n" 229 " '1quote', '2quote', 'fold', 'literal', 'plain'\n" 230 "indent -- indentation, an integer; 0 means default\n" 231 "width -- the preferred width; 0 means default\n" 232 "chomp -- None (clip), '-' (strip), or '+' (keep)\n"); 222 "graphs. A scalar node points to a single string value.\n"); 233 223 234 224 typedef struct { … … 489 479 static PyGetSetDef PySyckScalar_getsetters[] = { 490 480 {"kind", (getter)PySyckNode_getkind, NULL, 491 "the node kind", &PySyck_ScalarKind}, 481 PyDoc_STR("the node kind, always 'scalar', read-only"), 482 &PySyck_ScalarKind}, 492 483 {"value", (getter)PySyckNode_getvalue, (setter)PySyckScalar_setvalue, 493 "the node value", NULL},484 PyDoc_STR("the node value, a string"), NULL}, 494 485 {"tag", (getter)PySyckNode_gettag, (setter)PySyckNode_settag, 495 "the node tag", NULL},486 PyDoc_STR("the node tag, a string or None"), NULL}, 496 487 {"anchor", (getter)PySyckNode_getanchor, (setter)PySyckNode_setanchor, 497 "the node anchor", NULL},488 PyDoc_STR("the node anchor, a string or None"), NULL}, 498 489 {"style", (getter)PySyckScalar_getstyle, (setter)PySyckScalar_setstyle, 499 "the node style", NULL}, 490 PyDoc_STR("the node style, values: None (means literal or plain),\n" 491 "'1quote', '2quote', 'fold', 'literal', 'plain'"), NULL}, 500 492 {"indent", (getter)PySyckScalar_getindent, (setter)PySyckScalar_setindent, 501 "the field indentation", NULL},493 PyDoc_STR("the node indentation, an integer"), NULL}, 502 494 {"width", (getter)PySyckScalar_getwidth, (setter)PySyckScalar_setwidth, 503 "the field width", NULL},495 PyDoc_STR("the node width, an integer"), NULL}, 504 496 {"chomp", (getter)PySyckScalar_getchomp, (setter)PySyckScalar_setchomp, 505 "the chomping method", NULL}, 497 PyDoc_STR("the chomping method,\n" 498 "values: None (clip), '-' (strip), or '+' (keep)"), NULL}, 506 499 {NULL} /* Sentinel */ 507 500 }; … … 556 549 "Seq(value=[], tag=None, inline=False) -> a Seq node\n\n" 557 550 "_syck.Seq represents a sequence node in Syck parser and emitter\n" 558 "graphs. A sequence node points to an ordered set of subnodes.\n\n" 559 "Attributes:\n\n" 560 "kind -- always 'seq'; read-only\n" 561 "value -- the node value, a list\n" 562 "tag -- the node tag; a string or None\n" 563 "anchor -- the name of the node anchor or None; read-only\n" 564 "inline -- is the node inline? False or True\n"); 551 "graphs. A sequence node points to an ordered set of subnodes.\n"); 565 552 566 553 typedef struct { … … 672 659 static PyGetSetDef PySyckSeq_getsetters[] = { 673 660 {"kind", (getter)PySyckNode_getkind, NULL, 674 "the node kind", &PySyck_SeqKind},661 PyDoc_STR("the node kind, always 'seq', read-only"), &PySyck_SeqKind}, 675 662 {"value", (getter)PySyckNode_getvalue, (setter)PySyckSeq_setvalue, 676 "the node value", NULL},663 PyDoc_STR("the node value, a sequence"), NULL}, 677 664 {"tag", (getter)PySyckNode_gettag, (setter)PySyckNode_settag, 678 "the node tag", NULL},665 PyDoc_STR("the node tag, a string or None"), NULL}, 679 666 {"anchor", (getter)PySyckNode_getanchor, (setter)PySyckNode_setanchor, 680 "the node anchor", NULL},667 PyDoc_STR("the node anchor, a string or None"), NULL}, 681 668 {"inline", (getter)PySyckSeq_getinline, (setter)PySyckSeq_setinline, 682 "the node style", NULL},669 PyDoc_STR("the block/flow flag"), NULL}, 683 670 {NULL} /* Sentinel */ 684 671 }; … … 733 720 "Map(value='', tag=None, inline=False) -> a Map node\n\n" 734 721 "_syck.Map represents a mapping node in Syck parser and emitter\n" 735 "graphs. A mapping node points to an unordered collections of pairs.\n\n" 736 "Attributes:\n\n" 737 "kind -- always 'map'; read-only\n" 738 "value -- the node value, a dictionary\n" 739 "tag -- the node tag; a string or None\n" 740 "anchor -- the name of the node anchor or None; read-only\n" 741 "inline -- is the node inline? False or True\n"); 722 "graphs. A mapping node points to an unordered collections of pairs.\n"); 742 723 743 724 typedef struct { … … 849 830 static PyGetSetDef PySyckMap_getsetters[] = { 850 831 {"kind", (getter)PySyckNode_getkind, NULL, 851 "the node kind", &PySyck_MapKind},832 PyDoc_STR("the node kind, always 'map', read-only"), &PySyck_MapKind}, 852 833 {"value", (getter)PySyckNode_getvalue, (setter)PySyckMap_setvalue, 853 "the node value", NULL},834 PyDoc_STR("the node value, a mapping"), NULL}, 854 835 {"tag", (getter)PySyckNode_gettag, (setter)PySyckNode_settag, 855 "the node tag", NULL},836 PyDoc_STR("the node tag, a string or None"), NULL}, 856 837 {"anchor", (getter)PySyckNode_getanchor, (setter)PySyckNode_setanchor, 857 "the node anchor", NULL},838 PyDoc_STR("the node anchor, a string or None"), NULL}, 858 839 {"inline", (getter)PySyckMap_getinline, (setter)PySyckMap_setinline, 859 "the node style", NULL},840 PyDoc_STR("the block/flow flag"), NULL}, 860 841 {NULL} /* Sentinel */ 861 842 }; … … 903 884 }; 904 885 905 906 /* 886 /**************************************************************************** 887 * The type _syck.Parser. 888 ****************************************************************************/ 889 890 PyDoc_STRVAR(PySyckParser_doc, 891 "Parser(source, implicit_typing=True, taguri_expansion=True)\n" 892 " -> a Parser object\n\n" 893 "_syck.Parser is a low-lever wrapper of the Syck parser. It parses\n" 894 "a YAML stream and produces a graph of Nodes.\n"); 895 907 896 typedef struct { 908 897 PyObject_HEAD 909 PyObject *kind; 910 PyObject *type_id; 911 PyObject *value; 912 } PySyckNodeObject; 898 /* Attributes: */ 899 PyObject *source; /* a string or file-like object */ 900 int implicit_typing; 901 int taguri_expansion; 902 /* Internal fields: */ 903 PyObject *symbols; /* symbol table, a list, NULL outside parse() */ 904 SyckParser *parser; 905 int parsing; 906 int halt; 907 } PySyckParserObject; 908 909 static PyObject * 910 PySyckParser_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 911 { 912 PySyckParserObject *self; 913 914 self = (PySyckParserObject *)type->tp_alloc(type, 0); 915 if (!self) return NULL; 916 917 self->source = NULL; 918 self->implicit_typing = 0; 919 self->taguri_expansion = 0; 920 self->symbols = NULL; 921 self->parser = NULL; 922 self->parsing = 0; 923 self->halt = 1; 924 925 /* 926 self->symbols = PyList_New(0); 927 if (!self->symbols) { 928 Py_DECREF(self); 929 return NULL; 930 } 931 */ 932 933 return (PyObject *)self; 934 } 935 936 static int 937 PySyckParser_clear(PySyckParserObject *self) 938 { 939 PyObject *tmp; 940 941 if (self->parser) { 942 syck_free_parser(self->parser); 943 self->parser = NULL; 944 } 945 946 tmp = self->source; 947 self->source = NULL; 948 Py_XDECREF(tmp); 949 950 tmp = self->symbols; 951 self->symbols = NULL; 952 Py_XDECREF(tmp); 953 954 return 0; 955 } 956 957 static int 958 PySyckParser_traverse(PySyckParserObject *self, visitproc visit, void *arg) 959 { 960 int ret; 961 962 if (self->source) 963 if ((ret = visit(self->source, arg)) != 0) 964 return ret; 965 966 if (self->symbols) 967 if ((ret = visit(self->symbols, arg)) != 0) 968 return ret; 969 970 return 0; 971 } 913 972 914 973 static void 915 PySyckNode_dealloc(PySyckNodeObject *self) 916 { 917 Py_XDECREF(self->kind); 918 Py_XDECREF(self->type_id); 919 Py_XDECREF(self->value); 920 PyObject_Del(self); 921 } 922 923 static PyObject * 924 PySyckNode_getattr(PySyckNodeObject *self, char *name) 925 { 926 PyObject *value; 927 928 if (strcmp(name, "kind") == 0) 929 value = self->kind; 930 else if (strcmp(name, "type_id") == 0) 931 value = self->type_id; 932 else if (strcmp(name, "value") == 0) 933 value = self->value; 934 else { 935 PyErr_SetString(PyExc_AttributeError, name); 936 return NULL; 937 } 974 PySyckParser_dealloc(PySyckParserObject *self) 975 { 976 PySyckParser_clear(self); 977 self->ob_type->tp_free((PyObject *)self); 978 } 979 980 static PyObject * 981 PySyckParser_getsource(PySyckParserObject *self, void *closure) 982 { 983 PyObject *value = self->source ? self->source : Py_None; 938 984 939 985 Py_INCREF(value); … … 941 987 } 942 988 943 944 */ 989 static PyObject * 990 PySyckParser_getimplicit_typing(PySyckParserObject *self, void *closure) 991 { 992 PyObject *value = self->implicit_typing ? Py_True : Py_False; 993 994 Py_INCREF(value); 995 return value; 996 } 997 998 static PyObject * 999 PySyckParser_gettaguri_expansion(PySyckParserObject *self, void *closure) 1000 { 1001 PyObject *value = self->taguri_expansion ? Py_True : Py_False; 1002 1003 Py_INCREF(value); 1004 return value; 1005 } 1006 1007 static PyObject * 1008 PySyckParser_geteof(PySyckParserObject *self, void *closure) 1009 { 1010 PyObject *value = self->halt ? Py_True : Py_False; 1011 1012 Py_INCREF(value); 1013 return value; 1014 } 1015 1016 static PyGetSetDef PySyckParser_getsetters[] = { 1017 {"source", (getter)PySyckParser_getsource, NULL, 1018 PyDoc_STR("IO source, a string or file-like object"), NULL}, 1019 {"implicit_typing", (getter)PySyckParser_getimplicit_typing, NULL, 1020 PyDoc_STR("implicit typing of builtin YAML types"), NULL}, 1021 {"taguri_expansion", (getter)PySyckParser_gettaguri_expansion, NULL, 1022 PyDoc_STR("expansion of types in full taguri"), NULL}, 1023 {"eof", (getter)PySyckParser_geteof, NULL, 1024 PyDoc_STR("EOF flag"), NULL}, 1025 {NULL} /* Sentinel */ 1026 }; 1027 1028 static SYMID 1029 PySyckParser_node_handler(SyckParser *parser, SyckNode *node) 1030 { 1031 PySyckParserObject *self = (PySyckParserObject *)parser->bonus; 1032 1033 SYMID index; 1034 PySyckNodeObject *object = NULL; 1035 1036 PyObject *key, *value; 1037 int k; 1038 1039 if (self->halt) 1040 return -1; 1041 1042 switch (node->kind) { 1043 1044 case syck_str_kind: 1045 object = (PySyckNodeObject *) 1046 PySyckScalar_new(&PySyckScalar_Type, NULL, NULL); 1047 if (!object) goto error; 1048 value = PyString_FromStringAndSize(node->data.str->ptr, 1049 node->data.str->len); 1050 if (!value) goto error; 1051 Py_DECREF(object->value); 1052 object->value = value; 1053 break; 1054 1055 case syck_seq_kind: 1056 object = (PySyckNodeObject *) 1057 PySyckSeq_new(&PySyckSeq_Type, NULL, NULL); 1058 if (!object) goto error; 1059 for (k = 0; k < node->data.list->idx; k++) { 1060 index = syck_seq_read(node, k); 1061 value = PyList_GetItem(self->symbols, index); 1062 if (!value) goto error; 1063 if (PyList_Append(object->value, value) < 0) 1064 goto error; 1065 } 1066 break; 1067 1068 case syck_map_kind: 1069 object = (PySyckNodeObject *) 1070 PySyckMap_new(&PySyckMap_Type, NULL, NULL); 1071 if (!object) goto error; 1072 for (k = 0; k < node->data.pairs->idx; k++) 1073 { 1074 index = syck_map_read(node, map_key, k); 1075 key = PyList_GetItem(self->symbols, index); 1076 if (!key) goto error; 1077 index = syck_map_read(node, map_value, k); 1078 value = PyList_GetItem(self->symbols, index); 1079 if (!value) goto error; 1080 if (PyDict_SetItem(object->value, key, value) < 0) 1081 goto error; 1082 } 1083 break; 1084 } 1085 1086 if (node->type_id) { 1087 object->tag = PyString_FromString(node->type_id); 1088 if (!object->tag) goto error; 1089 } 1090 1091 if (node->anchor) { 1092 object->anchor = PyString_FromString(node->anchor); 1093 if (!object->anchor) goto error; 1094 } 1095 1096 if (PyList_Append(self->symbols, (PyObject *)object) < 0) 1097 goto error; 1098 1099 index = PyList_GET_SIZE(self->symbols)-1; 1100 return index; 1101 1102 error: 1103 Py_XDECREF(object); 1104 self->halt = 1; 1105 return -1; 1106 } 1107 1108 static void 1109 PySyckParser_error_handler(SyckParser *parser, char *str) 1110 { 1111 PySyckParserObject *self = (PySyckParserObject *)parser->bonus; 1112 PyObject *value; 1113 1114 if (self->halt) return; 1115 1116 self->halt = 1; 1117 1118 value = Py_BuildValue("(sii)", str, 1119 parser->linect, parser->cursor - parser->lineptr); 1120 if (value) { 1121 PyErr_SetObject(PySyck_Error, value); 1122 } 1123 } 1124 1125 static long 1126 PySyckParser_read_handler(char *buf, SyckIoFile *file, long max_size, long skip) 1127 { 1128 PySyckParserObject *self = (PySyckParserObject *)file->ptr; 1129 1130 PyObject *value; 1131 1132 char *str; 1133 int length; 1134 1135 buf[skip] = '\0'; 1136 1137 if (self->halt) { 1138 return skip; 1139 } 1140 1141 max_size -= skip; 1142 1143 value = PyObject_CallMethod(self->source, "read", "(i)", max_size); 1144 if (!value) { 1145 self->halt = 1; 1146 return skip; 1147 } 1148 1149 if (!PyString_CheckExact(value)) { 1150 Py_DECREF(value); 1151 PyErr_SetString(PyExc_TypeError, "file-like object should return a string"); 1152 self->halt = 1; 1153 1154 return skip; 1155 } 1156 1157 str = PyString_AS_STRING(value); 1158 length = PyString_GET_SIZE(value); 1159 if (!length) { 1160 Py_DECREF(value); 1161 return skip; 1162 } 1163 1164 if (length > max_size) { 1165 Py_DECREF(value); 1166 PyErr_SetString(PyExc_ValueError, "read returns an overly long string"); 1167 self->halt = 1; 1168 return skip; 1169 } 1170 1171 memcpy(buf+skip, str, length); 1172 length += skip; 1173 buf[length] = '\0'; 1174 1175 Py_DECREF(value); 1176 1177 return length; 1178 } 1179 1180 static int 1181 PySyckParser_init(PySyckParserObject *self, PyObject *args, PyObject *kwds) 1182 { 1183 PyObject *source = NULL; 1184 int implicit_typing = 1; 1185 int taguri_expansion = 1; 1186 1187 static char *kwdlist[] = {"source", "implicit_typing", "taguri_expansion", 1188 NULL}; 1189 1190 PySyckParser_clear(self); 1191 1192 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|ii", kwdlist, 1193 &source, &implicit_typing, &taguri_expansion)) 1194 return -1; 1195 1196 Py_INCREF(source); 1197 self->source = source; 1198 1199 self->implicit_typing = implicit_typing; 1200 self->taguri_expansion = taguri_expansion; 1201 1202 self->parser = syck_new_parser(); 1203 self->parser->bonus = self; 1204 1205 if (PyString_CheckExact(self->source)) { 1206 syck_parser_str(self->parser, 1207 PyString_AS_STRING(self->source), 1208 PyString_GET_SIZE(self->source), NULL); 1209 } 1210 /* 1211 else if (PyUnicode_CheckExact(self->source)) { 1212 syck_parser_str(self->parser, 1213 PyUnicode_AS_DATA(self->source), 1214 PyString_GET_DATA_SIZE(self->source), NULL); 1215 } 1216 */ 1217 else { 1218 syck_parser_file(self->parser, (FILE *)self, PySyckParser_read_handler); 1219 } 1220 1221 syck_parser_implicit_typing(self->parser, self->implicit_typing); 1222 syck_parser_taguri_expansion(self->parser, self->taguri_expansion); 1223 1224 syck_parser_handler(self->parser, PySyckParser_node_handler); 1225 syck_parser_error_handler(self->parser, PySyckParser_error_handler); 1226 /* 1227 syck_parser_bad_anchor_handler(parser, PySyckParser_bad_anchor_handler); 1228 */ 1229 1230 self->parsing = 0; 1231 self->halt = 0; 1232 1233 return 0; 1234 } 1235 1236 static PyObject * 1237 PySyckParser_parse(PySyckParserObject *self) 1238 { 1239 SYMID index; 1240 PyObject *value; 1241 1242 if (self->parsing) { 1243 PyErr_SetString(PyExc_RuntimeError, "do not call Parser.parse while it is already parsing"); 1244 return NULL; 1245 } 1246 1247 if (self->halt) { 1248 Py_INCREF(Py_None); 1249 return Py_None; 1250 } 1251 1252 self->symbols = PyList_New(0); 1253 if (!self->symbols) { 1254 return NULL; 1255 } 1256 1257 self->parsing = 1; 1258 index = syck_parse(self->parser); 1259 self->parsing = 0; 1260 1261 if (self->halt || self->parser->eof) { 1262 Py_DECREF(self->symbols); 1263 self->symbols = NULL; 1264 1265 if (self->halt) return NULL; 1266 1267 self->halt = 1; 1268 Py_INCREF(Py_None); 1269 return Py_None; 1270 } 1271 1272 value = PyList_GetItem(self->symbols, index); 1273 1274 Py_DECREF(self->symbols); 1275 self->symbols = NULL; 1276 1277 return value; 1278 } 1279 1280 PyDoc_STRVAR(PySyckParser_parse_doc, 1281 "parse() -> the root Node object\n\n" 1282 "Parses the source and returns the next document. On EOF, returns None\n" 1283 "and sets the 'eof' attribute on.\n"); 1284 1285 static PyMethodDef PySyckParser_methods[] = { 1286 {"parse", (PyCFunction)PySyckParser_parse, 1287 METH_NOARGS, PySyckParser_parse_doc}, 1288 {NULL} /* Sentinel */ 1289 }; 1290 1291 static PyTypeObject PySyckParser_Type = { 1292 PyObject_HEAD_INIT(NULL) 1293 0, /* ob_size */ 1294 "_syck.Parser", /* tp_name */ 1295 sizeof(PySyckParserObject), /* tp_basicsize */ 1296 0, /* tp_itemsize */ 1297 (destructor)PySyckParser_dealloc, /* tp_dealloc */ 1298 0, /* tp_print */ 1299 0, /* tp_getattr */ 1300 0, /* tp_setattr */ 1301 0, /* tp_compare */ 1302 0, /* tp_repr */ 1303 0, /* tp_as_number */ 1304 0, /* tp_as_sequence */ 1305 0, /* tp_as_mapping */ 1306 0, /* tp_hash */ 1307 0, /* tp_call */ 1308 0, /* tp_str */ 1309 0, /* tp_getattro */ 1310 0, /* tp_setattro */ 1311 0, /* tp_as_buffer */ 1312 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /* tp_flags */ 1313 PySyckParser_doc, /* tp_doc */ 1314 (traverseproc)PySyckParser_traverse, /* tp_traverse */ 1315 (inquiry)PySyckParser_clear, /* tp_clear */ 1316 0, /* tp_richcompare */ 1317 0, /* tp_weaklistoffset */ 1318 0, /* tp_iter */ 1319 0, /* tp_iternext */ 1320 PySyckParser_methods, /* tp_methods */ 1321 0, /* tp_members */ 1322 PySyckParser_getsetters, /* tp_getset */ 1323 0, /* tp_base */ 1324 0, /* tp_dict */ 1325 0, /* tp_descr_get */ 1326 0, /* tp_descr_set */ 1327 0, /* tp_dictoffset */ 1328 (initproc)PySyckParser_init, /* tp_init */ 1329 0, /* tp_alloc */ 1330 PySyckParser_new, /* tp_new */ 1331 }; 1332 1333 1334 945 1335 #if 0 946 1336 947 static PyTypeObject PySyckNode_Type = {948 PyObject_HEAD_INIT(NULL)949 0, /* ob_size */950 "_syck.Node", /* tp_name */951 sizeof(PySyckNodeObject), /* tp_basicsize */952 0, /* tp_itemsize */953 (destructor)PySyckNode_dealloc, /* tp_dealloc */954 0, /* tp_print */955 (getattrfunc)PySyckNode_getattr, /* tp_getattr */956 0, /* tp_setattr */957 0, /* tp_compare */958 0, /* tp_repr */959 0, /* tp_as_number */960 0, /* tp_as_sequence */961 0, /* tp_as_mapping */962 0, /* tp_hash */963 0, /* tp_call */964 0, /* tp_str */965 0, /* tp_getattro */966 0, /* tp_setattro */967 0, /* tp_as_buffer */968 Py_TPFLAGS_DEFAULT, /* tp_flags */969 PySyckNode_doc, /* tp_doc */970 };971 1337 972 1338 static PyObject * … … 1007 1373 return (PyObject *)self; 1008 1374 } 1009 1010 static PyObject *1011 PySyck_Node(PyObject *self, PyObject *args)1012 {1013 if (!PyArg_ParseTuple(args, ":_syck.Node"))1014 return NULL;1015 1016 PyErr_SetString(PyExc_TypeError, "Node object cannot be created explicitly. Use _syck.Parser.parse() instead.");1017 return NULL;1018 }1019 1020 static char PySyck_Node_doc[] =1021 "Node object cannot be created explicitly. Use _syck.Parser.parse() instead.";1022 1023 1024 */1025 1375 1026 1376 /* Parser type. */ … … 1166 1516 }; 1167 1517 1168 static long1169 PySyckParser_read_handler(char *buf, SyckIoFile *file, long max_size, long skip)1170 {1171 PySyckParserObject *parser = (PySyckParserObject *)file->ptr;1172 1173 PyObject *value;1174 1175 char *str;1176 int length;1177 1178 buf[skip] = '\0';1179 1180 if (parser->error) {1181 return skip;1182 }1183 1184 max_size -= skip;1185 1186 value = PyObject_CallMethod(parser->source, "read", "(i)", max_size);1187 if (!value) {1188 parser->error = 1;1189 return skip;1190 }1191 1192 if (!PyString_Check(value)) {1193 Py_DECREF(value);1194 PyErr_SetString(PyExc_TypeError, "file-like object should return a string");1195 parser->error = 1;1196 1197 return skip;1198 }1199 1200 str = PyString_AS_STRING(value);1201 length = PyString_GET_SIZE(value);1202 if (!length) {1203 Py_DECREF(value);1204 return skip;1205 }1206 1207 if (length > max_size) {1208 Py_DECREF(value);1209 PyErr_SetString(PyExc_ValueError, "read returns an overly long string");1210 parser->error = 1;1211 return skip;1212 }1213 1214 memcpy(buf+skip, str, length);1215 length += skip;1216 buf[length] = '\0';1217 1218 Py_DECREF(value);1219 1220 return length;1221 }1222 1518 1223 1519 static SYMID … … 1294 1590 } 1295 1591 1296 static void1297 PySyckParser_error_handler(SyckParser *syck, char *str)1298 {1299 PySyckParserObject *parser = (PySyckParserObject *)syck->bonus;1300 PyObject *value;1301 1302 if (parser->error) return;1303 1304 parser->error = 1;1305 1306 value = Py_BuildValue("(sii)", str, syck->linect, syck->cursor-syck->lineptr);1307 if (value) {1308 PyErr_SetObject(PySyck_Error, value);1309 }1310 }1311 1312 static PyObject *1313 PySyck_Parser(PyObject *self, PyObject *args, PyObject *kwds)1314 {1315 PySyckParserObject *parser;1316 PyObject *source;1317 PyObject *resolver = NULL;1318 int implicit_typing = 1;1319 int taguri_expansion = 1;1320 1321 static char *kwdlist[] = {"source", "resolver", "implicit_typing", "taguri_expansion", NULL};1322 1323 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oii", kwdlist,1324 &source, &resolver, &implicit_typing, &taguri_expansion))1325 return NULL;1326 1327 parser = PyObject_NEW(PySyckParserObject, &PySyckParser_Type);1328 if (!parser)1329 return NULL;1330 1331 parser->error = 0;1332 parser->symbols = NULL;1333 1334 Py_INCREF(source);1335 parser->source = source;1336 1337 if (resolver == Py_None)1338 resolver = NULL;1339 Py_XINCREF(resolver);1340 parser->resolver = resolver;1341 1342 parser->syck = syck_new_parser();1343 parser->syck->bonus = parser;1344 1345 if (PyString_Check(source)) {1346 syck_parser_str(parser->syck, PyString_AS_STRING(source), PyString_GET_SIZE(source), NULL);1347 }1348 else {1349 syck_parser_file(parser->syck, (FILE *)parser, PySyckParser_read_handler);1350 }1351 syck_parser_implicit_typing(parser->syck, implicit_typing);1352 syck_parser_taguri_expansion(parser->syck, taguri_expansion);1353 1354 syck_parser_handler(parser->syck, PySyckParser_node_handler);1355 syck_parser_error_handler(parser->syck, PySyckParser_error_handler);1356 /*1357 syck_parser_bad_anchor_handler(parser, PySyckParser_bad_anchor_handler);1358 */1359 1360 return (PyObject *)parser;1361 }1362 1363 static char PySyck_Parser_doc[] =1364 "Creates a new Parser object.";1365 1366 /* The module definitions. */1367 1368 static PyMethodDef PySyck_methods[] = {1369 {"Node", (PyCFunction)PySyck_Node, METH_VARARGS, PySyck_Node_doc},1370 {"Parser", (PyCFunction)PySyck_Parser, METH_VARARGS|METH_KEYWORDS, PySyck_Parser_doc},1371 {NULL} /* Sentinel */1372 };1373 1374 static char PySyck_doc[] =1375 "This module provides low-level access to the Syck parser and emitter.\n"1376 "Do not use this module directly, use the package 'syck' instead.\n";1377 1378 /* PyMODINIT_FUNC - does not work with versions <2.3 */1379 void1380 init_syck(void)1381 {1382 PyObject *m;1383 1384 PySyckNode_Type.ob_type = &PyType_Type;1385 PySyckParser_Type.ob_type = &PyType_Type;1386 1387 PySyck_Error = PyErr_NewException("_syck.error", NULL, NULL);1388 if (!PySyck_Error)1389 return;1390 1391 PySyck_ScalarKind = PyString_FromString("scalar");1392 if (!PySyck_ScalarKind)1393 return;1394 PySyck_SeqKind = PyString_FromString("seq");1395 if (!PySyck_SeqKind)1396 return;1397 PySyck_MapKind = PyString_FromString("map");1398 if (!PySyck_MapKind)1399 return;1400 1401 m = Py_InitModule3("_syck", PySyck_methods, PySyck_doc);1402 1403 Py_INCREF(PySyck_Error);1404 if (!PyModule_AddObject(m, "error", PySyck_Error) < 0)1405 return;1406 1407 Py_INCREF(&PySyckNode_Type);1408 if (PyModule_AddObject(m, "NodeType", (PyObject *)&PySyckNode_Type) < 0)1409 return;1410 1411 Py_INCREF(&PySyckParser_Type);1412 if (PyModule_AddObject(m, "ParserType", (PyObject *)&PySyckParser_Type) < 0)1413 return;1414 }1415 1592 1416 1593 #endif … … 1423 1600 1424 1601 PyDoc_STRVAR(PySyck_doc, 1425 "The low-level wrapper for the Syck YAML parser and emitter\n\n" 1426 "Types:\n\n" 1427 "Node -- the base Node type\n"); 1602 "low-level wrapper for the Syck YAML parser and emitter"); 1428 1603 1429 1604 PyMODINIT_FUNC … … 1439 1614 return; 1440 1615 if (PyType_Ready(&PySyckMap_Type) < 0) 1616 return; 1617 if (PyType_Ready(&PySyckParser_Type) < 0) 1441 1618 return; 1442 1619 … … 1469 1646 m = Py_InitModule3("_syck", PySyck_methods, PySyck_doc); 1470 1647 1648 Py_INCREF(PySyck_Error); 1649 if (PyModule_AddObject(m, "error", (PyObject *)PySyck_Error) < 0) 1650 return; 1651 1471 1652 Py_INCREF(&PySyckNode_Type); 1472 1653 if (PyModule_AddObject(m, "Node", (PyObject *)&PySyckNode_Type) < 0) … … 1484 1665 if (PyModule_AddObject(m, "Map", (PyObject *)&PySyckMap_Type) < 0) 1485 1666 return; 1486 } 1487 1488 1667 1668 Py_INCREF(&PySyckParser_Type); 1669 if (PyModule_AddObject(m, "Parser", (PyObject *)&PySyckParser_Type) < 0) 1670 return; 1671 } 1672 -
trunk/tests/test_high_level_parser.py
r9 r15 2 2 import unittest 3 3 import syck 4 import test_low_ parser4 import test_low_level_parser 5 5 import os 6 6 … … 125 125 } 126 126 127 class TestDocuments(test_low_ parser.TestDocuments):127 class TestDocuments(test_low_level_parser.TestDocuments): 128 128 129 129 def _testDocuments(self, source, length): … … 137 137 self.assertEqual(actual_length, length) 138 138 139 class TestValuesAndSources(test_low_ parser.TestValuesAndSources):139 class TestValuesAndSources(test_low_level_parser.TestValuesAndSources): 140 140 141 141 def testValues1(self): 142 self._testValues(test_low_ parser.COMPARE1)142 self._testValues(test_low_level_parser.COMPARE1) 143 143 144 144 def testValues2(self): 145 self._testValues(test_low_ parser.COMPARE2)145 self._testValues(test_low_level_parser.COMPARE2) 146 146 147 147 def testValues3(self): 148 self._testValues(test_low_ parser.COMPARE3)148 self._testValues(test_low_level_parser.COMPARE3) 149 149 150 150 def testFileValues1(self): 151 self._testFileValues(test_low_ parser.COMPARE1)151 self._testFileValues(test_low_level_parser.COMPARE1) 152 152 153 153 def testFileValues2(self): 154 self._testFileValues(test_low_ parser.COMPARE2)154 self._testFileValues(test_low_level_parser.COMPARE2) 155 155 156 156 def testFileValues3(self): 157 self._testFileValues(test_low_ parser.COMPARE3)157 self._testFileValues(test_low_level_parser.COMPARE3) 158 158 159 159 def testNonsense(self): -
trunk/tests/test_low_level_parser.py
r7 r15 4 4 import _syck 5 5 6 import StringIO 6 import StringIO, gc 7 7 8 8 EXAMPLE = """ … … 160 160 ] 161 161 162 class Test Types(unittest.TestCase):163 164 def test ParserType(self):162 class TestAttributes(unittest.TestCase): 163 164 def testAttributes(self): 165 165 parser = _syck.Parser(EXAMPLE) 166 self.assertEqual(type(parser), _syck.ParserType) 167 168 def testNodeType(self): 169 parser = _syck.Parser(EXAMPLE) 170 document = parser.parse() 171 self.assertEqual(type(document), _syck.NodeType) 172 173 def testNodeType2(self): 174 self.assertRaises(TypeError, (lambda: _syck.Node())) 166 self.assertEqual(type(parser), _syck.Parser) 167 self.assertEqual(parser.source, EXAMPLE) 168 self.assertEqual(parser.implicit_typing, True) 169 self.assertEqual(parser.taguri_expansion, True) 170 self.assertEqual(parser.eof, False) 171 node = parser.parse() 172 self.assert_(isinstance(node, _syck.Node)) 173 self.assertEqual(parser.source, EXAMPLE) 174 self.assertEqual(parser.implicit_typing, True) 175 self.assertEqual(parser.taguri_expansion, True) 176 self.assertEqual(parser.eof, False) 177 self.assertEqual(parser.parse(), None) 178 self.assertEqual(parser.eof, True) 179 180 class TestGarbage(unittest.TestCase): 181 182 def testGarbage(self): 183 gc.collect() 184 source = [] 185 parser = _syck.Parser(source) 186 source.append(parser) 187 del source, parser 188 self.assertEqual(gc.collect(), 2) 175 189 176 190 class TestErrors(unittest.TestCase): … … 178 192 def testError(self): 179 193 parser = _syck.Parser(INVALID[0]) 180 self.assertRaises(_syck.error, (lambda: parser.parse()))194 self.assertRaises(_syck.error, lambda: parser.parse()) 181 195 182 196 def testErrorLocation(self): … … 230 244 def testNonsense(self): 231 245 parser = _syck.Parser(None) 232 self.assertRaises(AttributeError, (lambda: parser.parse())) 246 self.assertRaises(AttributeError, lambda: parser.parse()) 247 248 def testCallMeNot(self): 249 class Source: 250 def __init__(self): 251 self.parser = None 252 def read(self, size=None): 253 if self.parser: 254 self.parser.parse() 255 return 256 source = Source() 257 parser = _syck.Parser(source) 258 source.parser = parser 259 self.assertRaises(RuntimeError, lambda: parser.parse()) 260 261 def testAbsoluteHorror(self): 262 class Source: 263 def __init__(self): 264 self.parser = None 265 def read(self, size=None): 266 if self.parser: 267 self.parser = None 268 return '' 269 source = Source() 270 parser = _syck.Parser(source) 271 source.parser = parser 272 del parser 273 self.assertEqual(None, source.parser.parse()) 233 274 234 275 def _testValues(self, (source, structure)): … … 242 283 self.assertEqualStructure(document, structure) 243 284 244 class TestResolver(unittest.TestCase, EqualStructure):245 246 object = 12345247 248 def object_resolver(self, node):249 return self.object250 251 def simple_resolver(self, node):252 return node.value253 254 def default_resolver(self, node):255 return node256 257 def call_me_not_resolver(self, node):258 self.call_me_not_parser.parse()259 return node260 261 def testResolver1(self):262 self._testResolver(COMPARE1)263 264 def testResolver2(self):265 self._testResolver(COMPARE2)266 267 def testResolver3(self):268 self._testResolver(COMPARE3)269 270 def testCallMeNot(self):271 self.call_me_not_parser = _syck.Parser(EXAMPLE, self.call_me_not_resolver)272 self.assertRaises(RuntimeError, (lambda: self.call_me_not_parser.parse()))273 del self.call_me_not_parser274 275 def _testResolver(self, compare):276 self._testObject(compare)277 self._testSimple(compare)278 self._testDefault(compare)279 self._testNone(compare)280 281 def _testObject(self, (source, structure)):282 parser = _syck.Parser(source, self.object_resolver)283 document = parser.parse()284 self.assert_(document is self.object)285 286 def _testSimple(self, (source, structure)):287 parser = _syck.Parser(source, self.simple_resolver)288 document = parser.parse()289 self.assert_(document, structure)290 291 def _testDefault(self, (source, structure)):292 parser = _syck.Parser(source, resolver=self.default_resolver)293 document = parser.parse()294 self.assertEqualStructure(document, structure)295 296 def _testNone(self, (source, structure)):297 parser = _syck.Parser(source, resolver=None)298 document = parser.parse()299 self.assertEqualStructure(document, structure)300 301 285 class TestDocuments(unittest.TestCase): 302 286 … … 318 302 while True: 319 303 document = parser.parse() 320 if parser.eof ():304 if parser.eof: 321 305 self.assertEqual(document, None) 322 306 break … … 324 308 self.assertEqual(actual_length, length) 325 309 self.assertEqual(parser.parse(), None) 326 self.assert_(parser.eof ())310 self.assert_(parser.eof) 327 311 self.assertEqual(parser.parse(), None) 328 self.assert_(parser.eof()) 312 self.assert_(parser.eof) 313 self.assert_(parser.eof) 329 314 330 315 class TestImplicitTyping(unittest.TestCase): … … 343 328 344 329 def _testTyping(self, implicit_typing, taguri_expansion): 345 parser = _syck.Parser(IMPLICIT_TYPING[0], None,implicit_typing, taguri_expansion)346 for node, (t ype_id, explicit) in zip(parser.parse().value, IMPLICIT_TYPING[1]):347 if t ype_idis not None and taguri_expansion:348 t ype_id = 'tag:yaml.org,2002:%s' % type_id330 parser = _syck.Parser(IMPLICIT_TYPING[0], implicit_typing, taguri_expansion) 331 for node, (tag, explicit) in zip(parser.parse().value, IMPLICIT_TYPING[1]): 332 if tag is not None and taguri_expansion: 333 tag = 'tag:yaml.org,2002:%s' % tag 349 334 if implicit_typing or explicit: 350 self.assertEqual(node.t ype_id, type_id)335 self.assertEqual(node.tag, tag) 351 336 else: 352 self.assertEqual(node.t ype_id, None)337 self.assertEqual(node.tag, None) 353 338 354 339 class TestExplicitTyping(unittest.TestCase): … … 356 341 def testExplicitTyping(self): 357 342 parser = _syck.Parser(EXPLICIT_TYPING[0]) 358 for node, t ype_idin zip(parser.parse().value, EXPLICIT_TYPING[1]):359 self.assertEqual(node.t ype_id, type_id)360 343 for node, tag in zip(parser.parse().value, EXPLICIT_TYPING[1]): 344 self.assertEqual(node.tag, tag) 345 -
trunk/tests/test_syck.py
r12 r15 2 2 import unittest 3 3 4 from test_low_level_node import *5 #from test_low_ parser import *6 #from test_high_parser import *4 #from test_low_level_node import * 5 #from test_low_level_parser import * 6 from test_high_level_parser import * 7 7 8 8 def main(module='__main__'):
Note: See TracChangeset
for help on using the changeset viewer.
