Changeset 391 for python/trunk/Modules/_elementtree.c
- Timestamp:
- Mar 19, 2014, 11:31:01 PM (11 years ago)
- Location:
- python/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
python/trunk
-
Property svn:mergeinfo
set to
/python/vendor/Python-2.7.6 merged eligible /python/vendor/current merged eligible
-
Property svn:mergeinfo
set to
-
python/trunk/Modules/_elementtree.c
r2 r391 1 1 /* 2 2 * ElementTree 3 * $Id: _elementtree.c 2657 2006-03-12 20:50:32Z fredrik $3 * $Id: _elementtree.c 3473 2009-01-11 22:53:55Z fredrik $ 4 4 * 5 5 * elementtree accelerator … … 8 8 * 1999-06-20 fl created (as part of sgmlop) 9 9 * 2001-05-29 fl effdom edition 10 * 2001-06-05 fl backported to unix; fixed bogus free in clear11 * 2001-07-10 fl added findall helper12 10 * 2003-02-27 fl elementtree edition (alpha) 13 11 * 2004-06-03 fl updates for elementtree 1.2 14 * 2005-01-05 fl added universal name cache, Element/SubElement factories 15 * 2005-01-06 fl moved python helpers into C module; removed 1.5.2 support 16 * 2005-01-07 fl added 2.1 support; work around broken __copy__ in 2.3 17 * 2005-01-08 fl added makeelement method; fixed path support 18 * 2005-01-10 fl optimized memory usage 12 * 2005-01-05 fl major optimization effort 19 13 * 2005-01-11 fl first public release (cElementTree 0.8) 20 14 * 2005-01-12 fl split element object into base and extras … … 36 30 * 2006-03-08 fl fixed a couple of potential null-refs and leaks 37 31 * 2006-03-12 fl merge in 2.5 ssize_t changes 32 * 2007-08-25 fl call custom builder's close method from XMLParser 33 * 2007-08-31 fl added iter, extend from ET 1.3 34 * 2007-09-01 fl fixed ParseError exception, setslice source type, etc 35 * 2007-09-03 fl fixed handling of negative insert indexes 36 * 2007-09-04 fl added itertext from ET 1.3 37 * 2007-09-06 fl added position attribute to ParseError exception 38 * 2008-06-06 fl delay error reporting in iterparse (from Hrvoje Niksic) 38 39 * 39 * Copyright (c) 1999-200 6by Secret Labs AB. All rights reserved.40 * Copyright (c) 1999-200 6by Fredrik Lundh.40 * Copyright (c) 1999-2009 by Secret Labs AB. All rights reserved. 41 * Copyright (c) 1999-2009 by Fredrik Lundh. 41 42 * 42 43 * info@pythonware.com … … 45 46 46 47 /* Licensed to PSF under a Contributor Agreement. */ 47 /* See http://www.python.org/ 2.4/license for licensing details. */48 /* See http://www.python.org/psf/license for licensing details. */ 48 49 49 50 #include "Python.h" … … 57 58 #define USE_EXPAT 58 59 59 /* Define to to all expat calls via pyexpat's embedded expat library */60 /* Define to do all expat calls via pyexpat's embedded expat library */ 60 61 /* #define USE_PYEXPAT_CAPI */ 61 62 … … 95 96 96 97 /* compatibility macros */ 98 #if (PY_VERSION_HEX < 0x02060000) 99 #define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt) 100 #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) 101 #endif 102 97 103 #if (PY_VERSION_HEX < 0x02050000) 98 104 typedef int Py_ssize_t; … … 102 108 #if (PY_VERSION_HEX < 0x02040000) 103 109 #define PyDict_CheckExact PyDict_Check 104 #if (PY_VERSION_HEX < 0x02020000)105 #define PyList_CheckExact PyList_Check106 #define PyString_CheckExact PyString_Check107 #if (PY_VERSION_HEX >= 0x01060000)108 #define Py_USING_UNICODE /* always enabled for 2.0 and 2.1 */109 #endif110 #endif111 #endif112 110 113 111 #if !defined(Py_RETURN_NONE) 114 112 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None 113 #endif 115 114 #endif 116 115 … … 124 123 125 124 /* glue functions (see the init function for details) */ 125 static PyObject* elementtree_parseerror_obj; 126 126 static PyObject* elementtree_copyelement_obj; 127 127 static PyObject* elementtree_deepcopy_obj; 128 static PyObject* elementtree_getiterator_obj; 128 static PyObject* elementtree_iter_obj; 129 static PyObject* elementtree_itertext_obj; 129 130 static PyObject* elementpath_obj; 130 131 … … 210 211 } 211 212 212 #if (PY_VERSION_HEX < 0x02020000)213 LOCAL(int)214 PyDict_Update(PyObject* dict, PyObject* other)215 {216 /* PyDict_Update emulation for 2.1 and earlier */217 218 PyObject* res;219 220 res = PyObject_CallMethod(dict, "update", "O", other);221 if (!res)222 return -1;223 224 Py_DECREF(res);225 return 0;226 }227 #endif228 229 213 /* -------------------------------------------------------------------- */ 230 214 /* the element type */ … … 331 315 PyObject_Del(self); 332 316 return NULL; 333 317 } 334 318 335 319 self->extra->length = 0; … … 429 413 430 414 if (res == Py_None) { 415 Py_DECREF(res); 431 416 /* create missing dictionary */ 432 417 res = PyDict_New(); … … 710 695 /* add object to memo dictionary (so deepcopy won't visit it again) */ 711 696 id = PyInt_FromLong((Py_uintptr_t) self); 697 if (!id) 698 goto error; 712 699 713 700 i = PyDict_SetItem(memo, id, (PyObject*) element); … … 733 720 /* check if a tag contains an xpath character */ 734 721 735 #define PATHCHAR(ch) (ch == '/' || ch == '*' || ch == '[' || ch == '@') 722 #define PATHCHAR(ch) \ 723 (ch == '/' || ch == '*' || ch == '[' || ch == '@' || ch == '.') 736 724 737 725 #if defined(Py_USING_UNICODE) … … 766 754 767 755 static PyObject* 756 element_extend(ElementObject* self, PyObject* args) 757 { 758 PyObject* seq; 759 Py_ssize_t i, seqlen = 0; 760 761 PyObject* seq_in; 762 if (!PyArg_ParseTuple(args, "O:extend", &seq_in)) 763 return NULL; 764 765 seq = PySequence_Fast(seq_in, ""); 766 if (!seq) { 767 PyErr_Format( 768 PyExc_TypeError, 769 "expected sequence, not \"%.200s\"", Py_TYPE(seq_in)->tp_name 770 ); 771 return NULL; 772 } 773 774 seqlen = PySequence_Size(seq); 775 for (i = 0; i < seqlen; i++) { 776 PyObject* element = PySequence_Fast_GET_ITEM(seq, i); 777 if (element_add_subelement(self, element) < 0) { 778 Py_DECREF(seq); 779 return NULL; 780 } 781 } 782 783 Py_DECREF(seq); 784 785 Py_RETURN_NONE; 786 } 787 788 static PyObject* 768 789 element_find(ElementObject* self, PyObject* args) 769 790 { … … 771 792 772 793 PyObject* tag; 773 if (!PyArg_ParseTuple(args, "O:find", &tag)) 774 return NULL; 775 776 if (checkpath(tag)) 794 PyObject* namespaces = Py_None; 795 if (!PyArg_ParseTuple(args, "O|O:find", &tag, &namespaces)) 796 return NULL; 797 798 if (checkpath(tag) || namespaces != Py_None) 777 799 return PyObject_CallMethod( 778 elementpath_obj, "find", "OO ", self, tag800 elementpath_obj, "find", "OOO", self, tag, namespaces 779 801 ); 780 802 … … 801 823 PyObject* tag; 802 824 PyObject* default_value = Py_None; 803 if (!PyArg_ParseTuple(args, "O|O:findtext", &tag, &default_value)) 804 return NULL; 805 806 if (checkpath(tag)) 825 PyObject* namespaces = Py_None; 826 if (!PyArg_ParseTuple(args, "O|OO:findtext", &tag, &default_value, &namespaces)) 827 return NULL; 828 829 if (checkpath(tag) || namespaces != Py_None) 807 830 return PyObject_CallMethod( 808 elementpath_obj, "findtext", "OOO ", self, tag, default_value831 elementpath_obj, "findtext", "OOOO", self, tag, default_value, namespaces 809 832 ); 810 833 … … 836 859 837 860 PyObject* tag; 838 if (!PyArg_ParseTuple(args, "O:findall", &tag)) 839 return NULL; 840 841 if (checkpath(tag)) 861 PyObject* namespaces = Py_None; 862 if (!PyArg_ParseTuple(args, "O|O:findall", &tag, &namespaces)) 863 return NULL; 864 865 if (checkpath(tag) || namespaces != Py_None) 842 866 return PyObject_CallMethod( 843 elementpath_obj, "findall", "OO ", self, tag867 elementpath_obj, "findall", "OOO", self, tag, namespaces 844 868 ); 845 869 … … 866 890 867 891 static PyObject* 892 element_iterfind(ElementObject* self, PyObject* args) 893 { 894 PyObject* tag; 895 PyObject* namespaces = Py_None; 896 if (!PyArg_ParseTuple(args, "O|O:iterfind", &tag, &namespaces)) 897 return NULL; 898 899 return PyObject_CallMethod( 900 elementpath_obj, "iterfind", "OOO", self, tag, namespaces 901 ); 902 } 903 904 static PyObject* 868 905 element_get(ElementObject* self, PyObject* args) 869 906 { … … 893 930 PyObject* list; 894 931 932 /* FIXME: report as deprecated? */ 933 895 934 if (!PyArg_ParseTuple(args, ":getchildren")) 896 935 return NULL; … … 913 952 914 953 static PyObject* 915 element_ getiterator(ElementObject* self, PyObject* args)954 element_iter(ElementObject* self, PyObject* args) 916 955 { 917 956 PyObject* result; 918 957 919 958 PyObject* tag = Py_None; 920 if (!PyArg_ParseTuple(args, "|O: getiterator", &tag))921 return NULL; 922 923 if (!elementtree_ getiterator_obj) {959 if (!PyArg_ParseTuple(args, "|O:iter", &tag)) 960 return NULL; 961 962 if (!elementtree_iter_obj) { 924 963 PyErr_SetString( 925 964 PyExc_RuntimeError, 926 " getiterator helper not found"965 "iter helper not found" 927 966 ); 928 967 return NULL; … … 936 975 Py_INCREF(tag); PyTuple_SET_ITEM(args, 1, (PyObject*) tag); 937 976 938 result = PyObject_CallObject(elementtree_getiterator_obj, args); 977 result = PyObject_CallObject(elementtree_iter_obj, args); 978 979 Py_DECREF(args); 980 981 return result; 982 } 983 984 985 static PyObject* 986 element_itertext(ElementObject* self, PyObject* args) 987 { 988 PyObject* result; 989 990 if (!PyArg_ParseTuple(args, ":itertext")) 991 return NULL; 992 993 if (!elementtree_itertext_obj) { 994 PyErr_SetString( 995 PyExc_RuntimeError, 996 "itertext helper not found" 997 ); 998 return NULL; 999 } 1000 1001 args = PyTuple_New(1); 1002 if (!args) 1003 return NULL; 1004 1005 Py_INCREF(self); PyTuple_SET_ITEM(args, 0, (PyObject*) self); 1006 1007 result = PyObject_CallObject(elementtree_itertext_obj, args); 939 1008 940 1009 Py_DECREF(args); … … 961 1030 962 1031 static PyObject* 963 element_getslice(PyObject* self_, Py_ssize_t start, Py_ssize_t end)964 {965 ElementObject* self = (ElementObject*) self_;966 Py_ssize_t i;967 PyObject* list;968 969 if (!self->extra)970 return PyList_New(0);971 972 /* standard clamping */973 if (start < 0)974 start = 0;975 if (end < 0)976 end = 0;977 if (end > self->extra->length)978 end = self->extra->length;979 if (start > end)980 start = end;981 982 list = PyList_New(end - start);983 if (!list)984 return NULL;985 986 for (i = start; i < end; i++) {987 PyObject* item = self->extra->children[i];988 Py_INCREF(item);989 PyList_SET_ITEM(list, i - start, item);990 }991 992 return list;993 }994 995 static PyObject*996 1032 element_insert(ElementObject* self, PyObject* args) 997 1033 { … … 1007 1043 element_new_extra(self, NULL); 1008 1044 1009 if (index < 0) 1010 index = 0; 1045 if (index < 0) { 1046 index += self->extra->length; 1047 if (index < 0) 1048 index = 0; 1049 } 1011 1050 if (index > self->extra->length) 1012 1051 index = self->extra->length; … … 1152 1191 element_repr(ElementObject* self) 1153 1192 { 1154 PyObject* repr; 1155 char buffer[100]; 1156 1157 repr = PyString_FromString("<Element "); 1158 1159 PyString_ConcatAndDel(&repr, PyObject_Repr(self->tag)); 1160 1161 sprintf(buffer, " at %p>", self); 1162 PyString_ConcatAndDel(&repr, PyString_FromString(buffer)); 1193 PyObject *repr, *tag; 1194 1195 tag = PyObject_Repr(self->tag); 1196 if (!tag) 1197 return NULL; 1198 1199 repr = PyString_FromFormat("<Element %s at %p>", 1200 PyString_AS_STRING(tag), self); 1201 1202 Py_DECREF(tag); 1163 1203 1164 1204 return repr; … … 1186 1226 1187 1227 Py_RETURN_NONE; 1188 }1189 1190 static int1191 element_setslice(PyObject* self_, Py_ssize_t start, Py_ssize_t end, PyObject* item)1192 {1193 ElementObject* self = (ElementObject*) self_;1194 Py_ssize_t i, new, old;1195 PyObject* recycle = NULL;1196 1197 if (!self->extra)1198 element_new_extra(self, NULL);1199 1200 /* standard clamping */1201 if (start < 0)1202 start = 0;1203 if (end < 0)1204 end = 0;1205 if (end > self->extra->length)1206 end = self->extra->length;1207 if (start > end)1208 start = end;1209 1210 old = end - start;1211 1212 if (item == NULL)1213 new = 0;1214 else if (PyList_CheckExact(item)) {1215 new = PyList_GET_SIZE(item);1216 } else {1217 /* FIXME: support arbitrary sequences? */1218 PyErr_Format(1219 PyExc_TypeError,1220 "expected list, not \"%.200s\"", Py_TYPE(item)->tp_name1221 );1222 return -1;1223 }1224 1225 if (old > 0) {1226 /* to avoid recursive calls to this method (via decref), move1227 old items to the recycle bin here, and get rid of them when1228 we're done modifying the element */1229 recycle = PyList_New(old);1230 for (i = 0; i < old; i++)1231 PyList_SET_ITEM(recycle, i, self->extra->children[i + start]);1232 }1233 1234 if (new < old) {1235 /* delete slice */1236 for (i = end; i < self->extra->length; i++)1237 self->extra->children[i + new - old] = self->extra->children[i];1238 } else if (new > old) {1239 /* insert slice */1240 if (element_resize(self, new - old) < 0)1241 return -1;1242 for (i = self->extra->length-1; i >= end; i--)1243 self->extra->children[i + new - old] = self->extra->children[i];1244 }1245 1246 /* replace the slice */1247 for (i = 0; i < new; i++) {1248 PyObject* element = PyList_GET_ITEM(item, i);1249 Py_INCREF(element);1250 self->extra->children[i + start] = element;1251 }1252 1253 self->extra->length += new - old;1254 1255 /* discard the recycle bin, and everything in it */1256 Py_XDECREF(recycle);1257 1258 return 0;1259 1228 } 1260 1229 … … 1289 1258 } 1290 1259 1260 static PyObject* 1261 element_subscr(PyObject* self_, PyObject* item) 1262 { 1263 ElementObject* self = (ElementObject*) self_; 1264 1265 #if (PY_VERSION_HEX < 0x02050000) 1266 if (PyInt_Check(item) || PyLong_Check(item)) { 1267 long i = PyInt_AsLong(item); 1268 #else 1269 if (PyIndex_Check(item)) { 1270 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); 1271 #endif 1272 1273 if (i == -1 && PyErr_Occurred()) { 1274 return NULL; 1275 } 1276 if (i < 0 && self->extra) 1277 i += self->extra->length; 1278 return element_getitem(self_, i); 1279 } 1280 else if (PySlice_Check(item)) { 1281 Py_ssize_t start, stop, step, slicelen, cur, i; 1282 PyObject* list; 1283 1284 if (!self->extra) 1285 return PyList_New(0); 1286 1287 if (PySlice_GetIndicesEx((PySliceObject *)item, 1288 self->extra->length, 1289 &start, &stop, &step, &slicelen) < 0) { 1290 return NULL; 1291 } 1292 1293 if (slicelen <= 0) 1294 return PyList_New(0); 1295 else { 1296 list = PyList_New(slicelen); 1297 if (!list) 1298 return NULL; 1299 1300 for (cur = start, i = 0; i < slicelen; 1301 cur += step, i++) { 1302 PyObject* item = self->extra->children[cur]; 1303 Py_INCREF(item); 1304 PyList_SET_ITEM(list, i, item); 1305 } 1306 1307 return list; 1308 } 1309 } 1310 else { 1311 PyErr_SetString(PyExc_TypeError, 1312 "element indices must be integers"); 1313 return NULL; 1314 } 1315 } 1316 1317 static int 1318 element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value) 1319 { 1320 ElementObject* self = (ElementObject*) self_; 1321 1322 #if (PY_VERSION_HEX < 0x02050000) 1323 if (PyInt_Check(item) || PyLong_Check(item)) { 1324 long i = PyInt_AsLong(item); 1325 #else 1326 if (PyIndex_Check(item)) { 1327 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); 1328 #endif 1329 1330 if (i == -1 && PyErr_Occurred()) { 1331 return -1; 1332 } 1333 if (i < 0 && self->extra) 1334 i += self->extra->length; 1335 return element_setitem(self_, i, value); 1336 } 1337 else if (PySlice_Check(item)) { 1338 Py_ssize_t start, stop, step, slicelen, newlen, cur, i; 1339 1340 PyObject* recycle = NULL; 1341 PyObject* seq = NULL; 1342 1343 if (!self->extra) 1344 element_new_extra(self, NULL); 1345 1346 if (PySlice_GetIndicesEx((PySliceObject *)item, 1347 self->extra->length, 1348 &start, &stop, &step, &slicelen) < 0) { 1349 return -1; 1350 } 1351 1352 if (value == NULL) 1353 newlen = 0; 1354 else { 1355 seq = PySequence_Fast(value, ""); 1356 if (!seq) { 1357 PyErr_Format( 1358 PyExc_TypeError, 1359 "expected sequence, not \"%.200s\"", Py_TYPE(value)->tp_name 1360 ); 1361 return -1; 1362 } 1363 newlen = PySequence_Size(seq); 1364 } 1365 1366 if (step != 1 && newlen != slicelen) 1367 { 1368 PyErr_Format(PyExc_ValueError, 1369 #if (PY_VERSION_HEX < 0x02050000) 1370 "attempt to assign sequence of size %d " 1371 "to extended slice of size %d", 1372 #else 1373 "attempt to assign sequence of size %zd " 1374 "to extended slice of size %zd", 1375 #endif 1376 newlen, slicelen 1377 ); 1378 return -1; 1379 } 1380 1381 1382 /* Resize before creating the recycle bin, to prevent refleaks. */ 1383 if (newlen > slicelen) { 1384 if (element_resize(self, newlen - slicelen) < 0) { 1385 if (seq) { 1386 Py_DECREF(seq); 1387 } 1388 return -1; 1389 } 1390 } 1391 1392 if (slicelen > 0) { 1393 /* to avoid recursive calls to this method (via decref), move 1394 old items to the recycle bin here, and get rid of them when 1395 we're done modifying the element */ 1396 recycle = PyList_New(slicelen); 1397 if (!recycle) { 1398 if (seq) { 1399 Py_DECREF(seq); 1400 } 1401 return -1; 1402 } 1403 for (cur = start, i = 0; i < slicelen; 1404 cur += step, i++) 1405 PyList_SET_ITEM(recycle, i, self->extra->children[cur]); 1406 } 1407 1408 if (newlen < slicelen) { 1409 /* delete slice */ 1410 for (i = stop; i < self->extra->length; i++) 1411 self->extra->children[i + newlen - slicelen] = self->extra->children[i]; 1412 } else if (newlen > slicelen) { 1413 /* insert slice */ 1414 for (i = self->extra->length-1; i >= stop; i--) 1415 self->extra->children[i + newlen - slicelen] = self->extra->children[i]; 1416 } 1417 1418 /* replace the slice */ 1419 for (cur = start, i = 0; i < newlen; 1420 cur += step, i++) { 1421 PyObject* element = PySequence_Fast_GET_ITEM(seq, i); 1422 Py_INCREF(element); 1423 self->extra->children[cur] = element; 1424 } 1425 1426 self->extra->length += newlen - slicelen; 1427 1428 if (seq) { 1429 Py_DECREF(seq); 1430 } 1431 1432 /* discard the recycle bin, and everything in it */ 1433 Py_XDECREF(recycle); 1434 1435 return 0; 1436 } 1437 else { 1438 PyErr_SetString(PyExc_TypeError, 1439 "element indices must be integers"); 1440 return -1; 1441 } 1442 } 1443 1291 1444 static PyMethodDef element_methods[] = { 1292 1445 … … 1301 1454 1302 1455 {"append", (PyCFunction) element_append, METH_VARARGS}, 1456 {"extend", (PyCFunction) element_extend, METH_VARARGS}, 1303 1457 {"insert", (PyCFunction) element_insert, METH_VARARGS}, 1304 1458 {"remove", (PyCFunction) element_remove, METH_VARARGS}, 1305 1459 1306 {"getiterator", (PyCFunction) element_getiterator, METH_VARARGS}, 1460 {"iter", (PyCFunction) element_iter, METH_VARARGS}, 1461 {"itertext", (PyCFunction) element_itertext, METH_VARARGS}, 1462 {"iterfind", (PyCFunction) element_iterfind, METH_VARARGS}, 1463 1464 {"getiterator", (PyCFunction) element_iter, METH_VARARGS}, 1307 1465 {"getchildren", (PyCFunction) element_getchildren, METH_VARARGS}, 1308 1466 … … 1335 1493 PyObject* res; 1336 1494 1495 /* handle common attributes first */ 1496 if (strcmp(name, "tag") == 0) { 1497 res = self->tag; 1498 Py_INCREF(res); 1499 return res; 1500 } else if (strcmp(name, "text") == 0) { 1501 res = element_get_text(self); 1502 Py_INCREF(res); 1503 return res; 1504 } 1505 1506 /* methods */ 1337 1507 res = Py_FindMethod(element_methods, (PyObject*) self, name); 1338 1508 if (res) 1339 1509 return res; 1340 1510 1341 1511 PyErr_Clear(); 1342 1512 1343 if (strcmp(name, "tag") == 0) 1344 res = self->tag; 1345 else if (strcmp(name, "text") == 0) 1346 res = element_get_text(self); 1347 else if (strcmp(name, "tail") == 0) { 1513 /* less common attributes */ 1514 if (strcmp(name, "tail") == 0) { 1348 1515 res = element_get_tail(self); 1349 1516 } else if (strcmp(name, "attrib") == 0) { 1350 1517 if (!self->extra) 1351 1518 element_new_extra(self, NULL); 1352 1519 res = element_get_attrib(self); 1353 1520 } else { 1354 1521 PyErr_SetString(PyExc_AttributeError, name); … … 1405 1572 0, /* sq_repeat */ 1406 1573 element_getitem, 1407 element_getslice,1574 0, 1408 1575 element_setitem, 1409 element_setslice, 1576 0, 1577 }; 1578 1579 static PyMappingMethods element_as_mapping = { 1580 (lenfunc) element_length, 1581 (binaryfunc) element_subscr, 1582 (objobjargproc) element_ass_subscr, 1410 1583 }; 1411 1584 … … 1422 1595 0, /* tp_as_number */ 1423 1596 &element_as_sequence, /* tp_as_sequence */ 1597 &element_as_mapping, /* tp_as_mapping */ 1424 1598 }; 1425 1599 … … 1559 1733 if (self->root) { 1560 1734 PyErr_SetString( 1561 PyExc_SyntaxError,1735 elementtree_parseerror_obj, 1562 1736 "multiple elements on top level" 1563 1737 ); … … 1700 1874 LOCAL(void) 1701 1875 treebuilder_handle_namespace(TreeBuilderObject* self, int start, 1702 const char* prefix, const char*uri)1876 PyObject *prefix, PyObject *uri) 1703 1877 { 1704 1878 PyObject* res; … … 1713 1887 return; 1714 1888 action = self->start_ns_event_obj; 1715 /* FIXME: prefix and uri use utf-8 encoding! */ 1716 parcel = Py_BuildValue("ss", (prefix) ? prefix : "", uri); 1889 parcel = Py_BuildValue("OO", prefix, uri); 1717 1890 if (!parcel) 1718 1891 return; … … 1858 2031 1859 2032 PyObject* handle_xml; 2033 1860 2034 PyObject* handle_start; 1861 2035 PyObject* handle_data; … … 1864 2038 PyObject* handle_comment; 1865 2039 PyObject* handle_pi; 2040 2041 PyObject* handle_close; 1866 2042 1867 2043 } XMLParserObject; … … 1972 2148 } 1973 2149 2150 static void 2151 expat_set_error(const char* message, int line, int column) 2152 { 2153 PyObject *error; 2154 PyObject *position; 2155 char buffer[256]; 2156 2157 sprintf(buffer, "%s: line %d, column %d", message, line, column); 2158 2159 error = PyObject_CallFunction(elementtree_parseerror_obj, "s", buffer); 2160 if (!error) 2161 return; 2162 2163 /* add position attribute */ 2164 position = Py_BuildValue("(ii)", line, column); 2165 if (!position) { 2166 Py_DECREF(error); 2167 return; 2168 } 2169 if (PyObject_SetAttrString(error, "position", position) == -1) { 2170 Py_DECREF(error); 2171 Py_DECREF(position); 2172 return; 2173 } 2174 Py_DECREF(position); 2175 2176 PyErr_SetObject(elementtree_parseerror_obj, error); 2177 Py_DECREF(error); 2178 } 2179 1974 2180 /* -------------------------------------------------------------------- */ 1975 2181 /* handlers */ … … 2002 2208 res = NULL; 2003 2209 Py_XDECREF(res); 2004 } else { 2005 PyErr_Format( 2006 PyExc_SyntaxError, "undefined entity &%s;: line %ld, column %ld", 2007 PyString_AS_STRING(key), 2210 } else if (!PyErr_Occurred()) { 2211 /* Report the first error, not the last */ 2212 char message[128]; 2213 sprintf(message, "undefined entity &%.100s;", PyString_AS_STRING(key)); 2214 expat_set_error( 2215 message, 2008 2216 EXPAT(GetErrorLineNumber)(self->parser), 2009 2217 EXPAT(GetErrorColumnNumber)(self->parser) … … 2060 2268 res = treebuilder_handle_start((TreeBuilderObject*) self->target, 2061 2269 tag, attrib); 2062 else if (self->handle_start) 2270 else if (self->handle_start) { 2271 if (attrib == Py_None) { 2272 Py_DECREF(attrib); 2273 attrib = PyDict_New(); 2274 if (!attrib) 2275 return; 2276 } 2063 2277 res = PyObject_CallFunction(self->handle_start, "OO", tag, attrib); 2064 else2278 } else 2065 2279 res = NULL; 2066 2280 … … 2122 2336 const XML_Char *uri) 2123 2337 { 2338 PyObject* sprefix = NULL; 2339 PyObject* suri = NULL; 2340 2341 suri = makestring(uri, strlen(uri)); 2342 if (!suri) 2343 return; 2344 2345 if (prefix) 2346 sprefix = makestring(prefix, strlen(prefix)); 2347 else 2348 sprefix = PyString_FromStringAndSize("", 0); 2349 if (!sprefix) { 2350 Py_DECREF(suri); 2351 return; 2352 } 2353 2124 2354 treebuilder_handle_namespace( 2125 (TreeBuilderObject*) self->target, 1, prefix,uri2355 (TreeBuilderObject*) self->target, 1, sprefix, suri 2126 2356 ); 2357 2358 Py_DECREF(sprefix); 2359 Py_DECREF(suri); 2127 2360 } 2128 2361 … … 2195 2428 if (PyUnicode_GET_SIZE(u) != 256) { 2196 2429 Py_DECREF(u); 2430 PyErr_SetString(PyExc_ValueError, 2431 "multi-byte encodings are not supported"); 2197 2432 return XML_STATUS_ERROR; 2198 2433 } … … 2201 2436 2202 2437 for (i = 0; i < 256; i++) { 2203 2204 2438 if (p[i] != Py_UNICODE_REPLACEMENT_CHARACTER) 2439 info->map[i] = p[i]; 2205 2440 else 2206 2441 info->map[i] = -1; 2207 2442 } 2208 2443 … … 2289 2524 self->handle_comment = PyObject_GetAttrString(target, "comment"); 2290 2525 self->handle_pi = PyObject_GetAttrString(target, "pi"); 2526 self->handle_close = PyObject_GetAttrString(target, "close"); 2291 2527 2292 2528 PyErr_Clear(); … … 2334 2570 EXPAT(ParserFree)(self->parser); 2335 2571 2572 Py_XDECREF(self->handle_close); 2336 2573 Py_XDECREF(self->handle_pi); 2337 2574 Py_XDECREF(self->handle_comment); … … 2364 2601 2365 2602 if (!ok) { 2366 PyErr_Format( 2367 PyExc_SyntaxError, "%s: line %ld, column %ld", 2603 expat_set_error( 2368 2604 EXPAT(ErrorString)(EXPAT(GetErrorCode)(self->parser)), 2369 2605 EXPAT(GetErrorLineNumber)(self->parser), … … 2386 2622 2387 2623 res = expat_parse(self, "", 0, 1); 2388 2389 if (res && TreeBuilder_CheckExact(self->target)) { 2624 if (!res) 2625 return NULL; 2626 2627 if (TreeBuilder_CheckExact(self->target)) { 2390 2628 Py_DECREF(res); 2391 2629 return treebuilder_done((TreeBuilderObject*) self->target); 2392 } 2393 2394 return res; 2630 } if (self->handle_close) { 2631 Py_DECREF(res); 2632 return PyObject_CallFunction(self->handle_close, ""); 2633 } else 2634 return res; 2395 2635 } 2396 2636 … … 2576 2816 res = Py_FindMethod(xmlparser_methods, (PyObject*) self, name); 2577 2817 if (res) 2578 2818 return res; 2579 2819 2580 2820 PyErr_Clear(); 2581 2821 2582 2822 if (strcmp(name, "entity") == 0) 2583 2823 res = self->entity; 2584 2824 else if (strcmp(name, "target") == 0) 2585 2825 res = self->target; 2586 2826 else if (strcmp(name, "version") == 0) { 2587 2827 char buffer[100]; … … 2629 2869 PyObject* g; 2630 2870 char* bootstrap; 2631 #if defined(USE_PYEXPAT_CAPI)2632 struct PyExpat_CAPI* capi;2633 #endif2634 2871 2635 2872 /* Patch object type */ … … 2652 2889 2653 2890 bootstrap = ( 2654 2655 #if (PY_VERSION_HEX >= 0x02020000 && PY_VERSION_HEX < 0x02030000)2656 "from __future__ import generators\n" /* enable yield under 2.2 */2657 #endif2658 2891 2659 2892 "from copy import copy, deepcopy\n" … … 2674 2907 " return elem\n" 2675 2908 2676 "def Comment(text=None):\n" /* public */ 2909 "class CommentProxy:\n" 2910 " def __call__(self, text=None):\n" 2677 2911 " element = cElementTree.Element(ET.Comment)\n" 2678 2912 " element.text = text\n" 2679 2913 " return element\n" 2680 "cElementTree.Comment = Comment\n" 2914 " def __cmp__(self, other):\n" 2915 " return cmp(ET.Comment, other)\n" 2916 "cElementTree.Comment = CommentProxy()\n" 2681 2917 2682 2918 "class ElementTree(ET.ElementTree):\n" /* public */ 2683 2919 " def parse(self, source, parser=None):\n" 2920 " close_source = False\n" 2684 2921 " if not hasattr(source, 'read'):\n" 2685 2922 " source = open(source, 'rb')\n" 2686 " if parser is not None:\n" 2687 " while 1:\n" 2688 " data = source.read(65536)\n" 2689 " if not data:\n" 2690 " break\n" 2691 " parser.feed(data)\n" 2692 " self._root = parser.close()\n" 2693 " else:\n" 2694 " parser = cElementTree.XMLParser()\n" 2695 " self._root = parser._parse(source)\n" 2696 " return self._root\n" 2923 " close_source = False\n" 2924 " try:\n" 2925 " if parser is not None:\n" 2926 " while 1:\n" 2927 " data = source.read(65536)\n" 2928 " if not data:\n" 2929 " break\n" 2930 " parser.feed(data)\n" 2931 " self._root = parser.close()\n" 2932 " else:\n" 2933 " parser = cElementTree.XMLParser()\n" 2934 " self._root = parser._parse(source)\n" 2935 " return self._root\n" 2936 " finally:\n" 2937 " if close_source:\n" 2938 " source.close()\n" 2697 2939 "cElementTree.ElementTree = ElementTree\n" 2698 2940 2699 "def getiterator(node, tag=None):\n" /* helper */2941 "def iter(node, tag=None):\n" /* helper */ 2700 2942 " if tag == '*':\n" 2701 2943 " tag = None\n" 2702 #if (PY_VERSION_HEX < 0x02020000)2703 " nodes = []\n" /* 2.1 doesn't have yield */2704 " if tag is None or node.tag == tag:\n"2705 " nodes.append(node)\n"2706 " for node in node:\n"2707 " nodes.extend(getiterator(node, tag))\n"2708 " return nodes\n"2709 #else2710 2944 " if tag is None or node.tag == tag:\n" 2711 2945 " yield node\n" 2712 2946 " for node in node:\n" 2713 " for node in getiterator(node, tag):\n"2947 " for node in iter(node, tag):\n" 2714 2948 " yield node\n" 2715 #endif 2949 2950 "def itertext(node):\n" /* helper */ 2951 " if node.text:\n" 2952 " yield node.text\n" 2953 " for e in node:\n" 2954 " for s in e.itertext():\n" 2955 " yield s\n" 2956 " if e.tail:\n" 2957 " yield e.tail\n" 2716 2958 2717 2959 "def parse(source, parser=None):\n" /* public */ … … 2721 2963 "cElementTree.parse = parse\n" 2722 2964 2723 #if (PY_VERSION_HEX < 0x02020000)2724 "if hasattr(ET, 'iterparse'):\n"2725 " cElementTree.iterparse = ET.iterparse\n" /* delegate on 2.1 */2726 #else2727 2965 "class iterparse(object):\n" 2728 2966 " root = None\n" 2729 2967 " def __init__(self, file, events=None):\n" 2968 " self._close_file = False\n" 2730 2969 " if not hasattr(file, 'read'):\n" 2731 2970 " file = open(file, 'rb')\n" 2971 " self._close_file = True\n" 2732 2972 " self._file = file\n" 2733 " self._events = events\n" 2734 " def __iter__(self):\n" 2735 " events = []\n" 2973 " self._events = []\n" 2974 " self._index = 0\n" 2975 " self._error = None\n" 2976 " self.root = self._root = None\n" 2736 2977 " b = cElementTree.TreeBuilder()\n" 2737 " p = cElementTree.XMLParser(b)\n" 2738 " p._setevents(events, self._events)\n" 2978 " self._parser = cElementTree.XMLParser(b)\n" 2979 " self._parser._setevents(self._events, events)\n" 2980 " def next(self):\n" 2739 2981 " while 1:\n" 2982 " try:\n" 2983 " item = self._events[self._index]\n" 2984 " self._index += 1\n" 2985 " return item\n" 2986 " except IndexError:\n" 2987 " pass\n" 2988 " if self._error:\n" 2989 " e = self._error\n" 2990 " self._error = None\n" 2991 " raise e\n" 2992 " if self._parser is None:\n" 2993 " self.root = self._root\n" 2994 " if self._close_file:\n" 2995 " self._file.close()\n" 2996 " raise StopIteration\n" 2997 " # load event buffer\n" 2998 " del self._events[:]\n" 2999 " self._index = 0\n" 2740 3000 " data = self._file.read(16384)\n" 2741 " if notdata:\n"2742 " break\n"2743 " p.feed(data)\n"2744 " for event in events:\n"2745 " yield event\n"2746 " del events[:]\n"2747 " root = p.close()\n"2748 " for event in events:\n"2749 " yield event\n"2750 " self.root = root\n"3001 " if data:\n" 3002 " try:\n" 3003 " self._parser.feed(data)\n" 3004 " except SyntaxError as exc:\n" 3005 " self._error = exc\n" 3006 " else:\n" 3007 " self._root = self._parser.close()\n" 3008 " self._parser = None\n" 3009 " def __iter__(self):\n" 3010 " return self\n" 2751 3011 "cElementTree.iterparse = iterparse\n" 2752 #endif 2753 2754 " def PI(target, text=None):\n" /* public */2755 " element = cElementTree.Element(ET.P rocessingInstruction)\n"3012 3013 "class PIProxy:\n" 3014 " def __call__(self, target, text=None):\n" 3015 " element = cElementTree.Element(ET.PI)\n" 2756 3016 " element.text = target\n" 2757 3017 " if text:\n" 2758 3018 " element.text = element.text + ' ' + text\n" 2759 3019 " return element\n" 2760 2761 " elem = cElementTree.Element(ET.PI)\n" 2762 " elem.text = text\n" 2763 " return elem\n" 2764 "cElementTree.PI = cElementTree.ProcessingInstruction = PI\n" 3020 " def __cmp__(self, other):\n" 3021 " return cmp(ET.PI, other)\n" 3022 "cElementTree.PI = cElementTree.ProcessingInstruction = PIProxy()\n" 2765 3023 2766 3024 "def XML(text):\n" /* public */ … … 2773 3031 " tree = XML(text)\n" 2774 3032 " ids = {}\n" 2775 " for elem in tree. getiterator():\n"3033 " for elem in tree.iter():\n" 2776 3034 " id = elem.get('id')\n" 2777 3035 " if id:\n" … … 2780 3038 "cElementTree.XMLID = XMLID\n" 2781 3039 3040 "try:\n" 3041 " register_namespace = ET.register_namespace\n" 3042 "except AttributeError:\n" 3043 " def register_namespace(prefix, uri):\n" 3044 " ET._namespace_map[uri] = prefix\n" 3045 "cElementTree.register_namespace = register_namespace\n" 3046 2782 3047 "cElementTree.dump = ET.dump\n" 2783 3048 "cElementTree.ElementPath = ElementPath = ET.ElementPath\n" … … 2785 3050 "cElementTree.QName = ET.QName\n" 2786 3051 "cElementTree.tostring = ET.tostring\n" 3052 "cElementTree.fromstringlist = ET.fromstringlist\n" 3053 "cElementTree.tostringlist = ET.tostringlist\n" 2787 3054 "cElementTree.VERSION = '" VERSION "'\n" 2788 3055 "cElementTree.__version__ = '" VERSION "'\n" 2789 "cElementTree.XMLParserError = SyntaxError\n"2790 3056 2791 3057 ); 2792 3058 2793 PyRun_String(bootstrap, Py_file_input, g, NULL); 3059 if (!PyRun_String(bootstrap, Py_file_input, g, NULL)) 3060 return; 2794 3061 2795 3062 elementpath_obj = PyDict_GetItemString(g, "ElementPath"); … … 2806 3073 } else 2807 3074 PyErr_Clear(); 3075 2808 3076 elementtree_deepcopy_obj = PyDict_GetItemString(g, "deepcopy"); 2809 elementtree_getiterator_obj = PyDict_GetItemString(g, "getiterator"); 3077 elementtree_iter_obj = PyDict_GetItemString(g, "iter"); 3078 elementtree_itertext_obj = PyDict_GetItemString(g, "itertext"); 2810 3079 2811 3080 #if defined(USE_PYEXPAT_CAPI) 2812 3081 /* link against pyexpat, if possible */ 2813 capi = PyCObject_Import("pyexpat", "expat_CAPI");2814 if ( capi &&2815 strcmp(capi->magic, PyExpat_CAPI_MAGIC) == 0 &&2816 capi->size <= sizeof(*expat_capi) &&2817 capi->MAJOR_VERSION == XML_MAJOR_VERSION &&2818 capi->MINOR_VERSION == XML_MINOR_VERSION &&2819 capi->MICRO_VERSION == XML_MICRO_VERSION)2820 expat_capi = capi;2821 else2822 expat_capi = NULL;3082 expat_capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0); 3083 if (expat_capi) { 3084 /* check that it's usable */ 3085 if (strcmp(expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 || 3086 expat_capi->size < sizeof(struct PyExpat_CAPI) || 3087 expat_capi->MAJOR_VERSION != XML_MAJOR_VERSION || 3088 expat_capi->MINOR_VERSION != XML_MINOR_VERSION || 3089 expat_capi->MICRO_VERSION != XML_MICRO_VERSION) 3090 expat_capi = NULL; 3091 } 2823 3092 #endif 2824 3093 2825 } 3094 elementtree_parseerror_obj = PyErr_NewException( 3095 "cElementTree.ParseError", PyExc_SyntaxError, NULL 3096 ); 3097 Py_INCREF(elementtree_parseerror_obj); 3098 PyModule_AddObject(m, "ParseError", elementtree_parseerror_obj); 3099 }
Note:
See TracChangeset
for help on using the changeset viewer.