LEFT | RIGHT |
1 /* | 1 /* |
2 * ElementTree | 2 * ElementTree |
3 * $Id: _elementtree.c 3469 2009-01-10 14:30:13Z fredrik $ | 3 * $Id: _elementtree.c 3473 2009-01-11 22:53:55Z fredrik $ |
4 * | 4 * |
5 * elementtree accelerator | 5 * elementtree accelerator |
6 * | 6 * |
7 * History: | 7 * History: |
8 * 1999-06-20 fl created (as part of sgmlop) | 8 * 1999-06-20 fl created (as part of sgmlop) |
9 * 2001-05-29 fl effdom edition | 9 * 2001-05-29 fl effdom edition |
10 * 2003-02-27 fl elementtree edition (alpha) | 10 * 2003-02-27 fl elementtree edition (alpha) |
11 * 2004-06-03 fl updates for elementtree 1.2 | 11 * 2004-06-03 fl updates for elementtree 1.2 |
12 * 2005-01-05 fl added universal name cache, Element/SubElement factories | 12 * 2005-01-05 fl major optimization effort |
13 * 2005-01-06 fl moved python helpers into C module; removed 1.5.2 support | |
14 * 2005-01-07 fl added 2.1 support; work around broken __copy__ in 2.3 | |
15 * 2005-01-08 fl added makeelement method; fixed path support | |
16 * 2005-01-10 fl optimized memory usage | |
17 * 2005-01-11 fl first public release (cElementTree 0.8) | 13 * 2005-01-11 fl first public release (cElementTree 0.8) |
18 * 2005-01-12 fl split element object into base and extras | 14 * 2005-01-12 fl split element object into base and extras |
19 * 2005-01-13 fl use tagged pointers for tail/text (cElementTree 0.9) | 15 * 2005-01-13 fl use tagged pointers for tail/text (cElementTree 0.9) |
20 * 2005-01-17 fl added treebuilder close method | 16 * 2005-01-17 fl added treebuilder close method |
21 * 2005-01-17 fl fixed crash in getchildren | 17 * 2005-01-17 fl fixed crash in getchildren |
22 * 2005-01-18 fl removed observer api, added iterparse (cElementTree 0.9.3) | 18 * 2005-01-18 fl removed observer api, added iterparse (cElementTree 0.9.3) |
23 * 2005-01-23 fl revised iterparse api; added namespace event support (0.9.8) | 19 * 2005-01-23 fl revised iterparse api; added namespace event support (0.9.8) |
24 * 2005-01-26 fl added VERSION module property (cElementTree 1.0) | 20 * 2005-01-26 fl added VERSION module property (cElementTree 1.0) |
25 * 2005-01-28 fl added remove method (1.0.1) | 21 * 2005-01-28 fl added remove method (1.0.1) |
26 * 2005-03-01 fl added iselement function; fixed makeelement aliasing (1.0.2) | 22 * 2005-03-01 fl added iselement function; fixed makeelement aliasing (1.0.2) |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 #endif | 88 #endif |
93 | 89 |
94 /* compiler tweaks */ | 90 /* compiler tweaks */ |
95 #if defined(_MSC_VER) | 91 #if defined(_MSC_VER) |
96 #define LOCAL(type) static __inline type __fastcall | 92 #define LOCAL(type) static __inline type __fastcall |
97 #else | 93 #else |
98 #define LOCAL(type) static type | 94 #define LOCAL(type) static type |
99 #endif | 95 #endif |
100 | 96 |
101 /* compatibility macros */ | 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 |
102 #if (PY_VERSION_HEX < 0x02050000) | 103 #if (PY_VERSION_HEX < 0x02050000) |
103 typedef int Py_ssize_t; | 104 typedef int Py_ssize_t; |
104 #define lenfunc inquiry | 105 #define lenfunc inquiry |
105 #endif | 106 #endif |
106 | 107 |
107 #if (PY_VERSION_HEX < 0x02040000) | 108 #if (PY_VERSION_HEX < 0x02040000) |
108 #define PyDict_CheckExact PyDict_Check | 109 #define PyDict_CheckExact PyDict_Check |
109 #if (PY_VERSION_HEX < 0x02020000) | |
110 #define PyList_CheckExact PyList_Check | |
111 #define PyString_CheckExact PyString_Check | |
112 #if (PY_VERSION_HEX >= 0x01060000) | |
113 #define Py_USING_UNICODE /* always enabled for 2.0 and 2.1 */ | |
114 #endif | |
115 #endif | |
116 #endif | |
117 | 110 |
118 #if !defined(Py_RETURN_NONE) | 111 #if !defined(Py_RETURN_NONE) |
119 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None | 112 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None |
| 113 #endif |
120 #endif | 114 #endif |
121 | 115 |
122 /* macros used to store 'join' flags in string object pointers. note | 116 /* macros used to store 'join' flags in string object pointers. note |
123 that all use of text and tail as object pointers must be wrapped in | 117 that all use of text and tail as object pointers must be wrapped in |
124 JOIN_OBJ. see comments in the ElementObject definition for more | 118 JOIN_OBJ. see comments in the ElementObject definition for more |
125 info. */ | 119 info. */ |
126 #define JOIN_GET(p) ((Py_uintptr_t) (p) & 1) | 120 #define JOIN_GET(p) ((Py_uintptr_t) (p) & 1) |
127 #define JOIN_SET(p, flag) ((void*) ((Py_uintptr_t) (JOIN_OBJ(p)) | (flag))) | 121 #define JOIN_SET(p, flag) ((void*) ((Py_uintptr_t) (JOIN_OBJ(p)) | (flag))) |
128 #define JOIN_OBJ(p) ((PyObject*) ((Py_uintptr_t) (p) & ~1)) | 122 #define JOIN_OBJ(p) ((PyObject*) ((Py_uintptr_t) (p) & ~1)) |
129 | 123 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 PyTuple_SET_ITEM(args, 0, list); | 202 PyTuple_SET_ITEM(args, 0, list); |
209 | 203 |
210 result = PyObject_CallObject(function, args); | 204 result = PyObject_CallObject(function, args); |
211 | 205 |
212 Py_DECREF(args); /* also removes list */ | 206 Py_DECREF(args); /* also removes list */ |
213 Py_DECREF(function); | 207 Py_DECREF(function); |
214 Py_DECREF(joiner); | 208 Py_DECREF(joiner); |
215 | 209 |
216 return result; | 210 return result; |
217 } | 211 } |
218 | |
219 #if (PY_VERSION_HEX < 0x02020000) | |
220 LOCAL(int) | |
221 PyDict_Update(PyObject* dict, PyObject* other) | |
222 { | |
223 /* PyDict_Update emulation for 2.1 and earlier */ | |
224 | |
225 PyObject* res; | |
226 ···· | |
227 res = PyObject_CallMethod(dict, "update", "O", other); | |
228 if (!res) | |
229 return -1; | |
230 | |
231 Py_DECREF(res); | |
232 return 0; | |
233 } | |
234 #endif | |
235 | 212 |
236 /* -------------------------------------------------------------------- */ | 213 /* -------------------------------------------------------------------- */ |
237 /* the element type */ | 214 /* the element type */ |
238 | 215 |
239 typedef struct { | 216 typedef struct { |
240 | 217 |
241 /* attributes (a dictionary object), or None if no attributes */ | 218 /* attributes (a dictionary object), or None if no attributes */ |
242 PyObject* attrib; | 219 PyObject* attrib; |
243 | 220 |
244 /* child elements */ | 221 /* child elements */ |
(...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
807 | 784 |
808 Py_RETURN_NONE; | 785 Py_RETURN_NONE; |
809 } | 786 } |
810 | 787 |
811 static PyObject* | 788 static PyObject* |
812 element_find(ElementObject* self, PyObject* args) | 789 element_find(ElementObject* self, PyObject* args) |
813 { | 790 { |
814 int i; | 791 int i; |
815 | 792 |
816 PyObject* tag; | 793 PyObject* tag; |
817 if (!PyArg_ParseTuple(args, "O:find", &tag)) | 794 PyObject* namespaces = Py_None; |
818 return NULL; | 795 if (!PyArg_ParseTuple(args, "O|O:find", &tag, &namespaces)) |
819 | 796 return NULL; |
820 if (checkpath(tag)) | 797 |
| 798 if (checkpath(tag) || namespaces != Py_None) |
821 return PyObject_CallMethod( | 799 return PyObject_CallMethod( |
822 elementpath_obj, "find", "OO", self, tag | 800 elementpath_obj, "find", "OOO", self, tag, namespaces |
823 ); | 801 ); |
824 | 802 |
825 if (!self->extra) | 803 if (!self->extra) |
826 Py_RETURN_NONE; | 804 Py_RETURN_NONE; |
827 ········ | 805 ········ |
828 for (i = 0; i < self->extra->length; i++) { | 806 for (i = 0; i < self->extra->length; i++) { |
829 PyObject* item = self->extra->children[i]; | 807 PyObject* item = self->extra->children[i]; |
830 if (Element_CheckExact(item) && | 808 if (Element_CheckExact(item) && |
831 PyObject_Compare(((ElementObject*)item)->tag, tag) == 0) { | 809 PyObject_Compare(((ElementObject*)item)->tag, tag) == 0) { |
832 Py_INCREF(item); | 810 Py_INCREF(item); |
833 return item; | 811 return item; |
834 } | 812 } |
835 } | 813 } |
836 | 814 |
837 Py_RETURN_NONE; | 815 Py_RETURN_NONE; |
838 } | 816 } |
839 | 817 |
840 static PyObject* | 818 static PyObject* |
841 element_findtext(ElementObject* self, PyObject* args) | 819 element_findtext(ElementObject* self, PyObject* args) |
842 { | 820 { |
843 int i; | 821 int i; |
844 | 822 |
845 PyObject* tag; | 823 PyObject* tag; |
846 PyObject* default_value = Py_None; | 824 PyObject* default_value = Py_None; |
847 if (!PyArg_ParseTuple(args, "O|O:findtext", &tag, &default_value)) | 825 PyObject* namespaces = Py_None; |
848 return NULL; | 826 if (!PyArg_ParseTuple(args, "O|OO:findtext", &tag, &default_value, &namespac
es)) |
849 | 827 return NULL; |
850 if (checkpath(tag)) | 828 |
| 829 if (checkpath(tag) || namespaces != Py_None) |
851 return PyObject_CallMethod( | 830 return PyObject_CallMethod( |
852 elementpath_obj, "findtext", "OOO", self, tag, default_value | 831 elementpath_obj, "findtext", "OOOO", self, tag, default_value, names
paces |
853 ); | 832 ); |
854 | 833 |
855 if (!self->extra) { | 834 if (!self->extra) { |
856 Py_INCREF(default_value); | 835 Py_INCREF(default_value); |
857 return default_value; | 836 return default_value; |
858 } | 837 } |
859 | 838 |
860 for (i = 0; i < self->extra->length; i++) { | 839 for (i = 0; i < self->extra->length; i++) { |
861 ElementObject* item = (ElementObject*) self->extra->children[i]; | 840 ElementObject* item = (ElementObject*) self->extra->children[i]; |
862 if (Element_CheckExact(item) && !PyObject_Compare(item->tag, tag)) { | 841 if (Element_CheckExact(item) && !PyObject_Compare(item->tag, tag)) { |
863 PyObject* text = element_get_text(item); | 842 PyObject* text = element_get_text(item); |
864 if (text == Py_None) | 843 if (text == Py_None) |
865 return PyString_FromString(""); | 844 return PyString_FromString(""); |
866 Py_XINCREF(text); | 845 Py_XINCREF(text); |
867 return text; | 846 return text; |
868 } | 847 } |
869 } | 848 } |
870 | 849 |
871 Py_INCREF(default_value); | 850 Py_INCREF(default_value); |
872 return default_value; | 851 return default_value; |
873 } | 852 } |
874 | 853 |
875 static PyObject* | 854 static PyObject* |
876 element_findall(ElementObject* self, PyObject* args) | 855 element_findall(ElementObject* self, PyObject* args) |
877 { | 856 { |
878 int i; | 857 int i; |
879 PyObject *out, *it; | 858 PyObject* out; |
880 | 859 |
881 PyObject* tag; | 860 PyObject* tag; |
882 if (!PyArg_ParseTuple(args, "O:findall", &tag)) | 861 PyObject* namespaces = Py_None; |
883 return NULL; | 862 if (!PyArg_ParseTuple(args, "O|O:findall", &tag, &namespaces)) |
884 | 863 return NULL; |
885 if (checkpath(tag)) | 864 |
| 865 if (checkpath(tag) || namespaces != Py_None) |
886 return PyObject_CallMethod( | 866 return PyObject_CallMethod( |
887 elementpath_obj, "findall", "OO", self, tag | 867 elementpath_obj, "findall", "OOO", self, tag, namespaces |
888 ); | 868 ); |
889 | 869 |
890 out = PyList_New(0); | 870 out = PyList_New(0); |
891 if (!out) | 871 if (!out) |
892 return NULL; | 872 return NULL; |
893 | 873 |
894 if (!self->extra) | 874 if (!self->extra) |
895 return out; | 875 return out; |
896 | 876 |
897 for (i = 0; i < self->extra->length; i++) { | 877 for (i = 0; i < self->extra->length; i++) { |
898 PyObject* item = self->extra->children[i]; | 878 PyObject* item = self->extra->children[i]; |
899 if (Element_CheckExact(item) && | 879 if (Element_CheckExact(item) && |
900 PyObject_Compare(((ElementObject*)item)->tag, tag) == 0) { | 880 PyObject_Compare(((ElementObject*)item)->tag, tag) == 0) { |
901 if (PyList_Append(out, item) < 0) { | 881 if (PyList_Append(out, item) < 0) { |
902 Py_DECREF(out); | 882 Py_DECREF(out); |
903 return NULL; | 883 return NULL; |
904 } | 884 } |
905 } | 885 } |
906 } | 886 } |
907 | 887 |
908 it = PyObject_GetIter(out); | 888 return out; |
909 Py_DECREF(out); | 889 } |
910 return it; | 890 |
| 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 ); |
911 } | 902 } |
912 | 903 |
913 static PyObject* | 904 static PyObject* |
914 element_get(ElementObject* self, PyObject* args) | 905 element_get(ElementObject* self, PyObject* args) |
915 { | 906 { |
916 PyObject* value; | 907 PyObject* value; |
917 | 908 |
918 PyObject* key; | 909 PyObject* key; |
919 PyObject* default_value = Py_None; | 910 PyObject* default_value = Py_None; |
920 if (!PyArg_ParseTuple(args, "O|O:get", &key, &default_value)) | 911 if (!PyArg_ParseTuple(args, "O|O:get", &key, &default_value)) |
921 return NULL; | 912 return NULL; |
922 | 913 |
923 if (!self->extra || self->extra->attrib == Py_None) | 914 if (!self->extra || self->extra->attrib == Py_None) |
924 value = default_value; | 915 value = default_value; |
925 else { | 916 else { |
926 value = PyDict_GetItem(self->extra->attrib, key); | 917 value = PyDict_GetItem(self->extra->attrib, key); |
927 if (!value) | 918 if (!value) |
928 value = default_value; | 919 value = default_value; |
929 } | 920 } |
930 | 921 |
931 Py_INCREF(value); | 922 Py_INCREF(value); |
932 return value; | 923 return value; |
933 } | 924 } |
934 | 925 |
935 static PyObject* | 926 static PyObject* |
936 element_getchildren(ElementObject* self, PyObject* args) | 927 element_getchildren(ElementObject* self, PyObject* args) |
937 { | 928 { |
938 int i; | 929 int i; |
939 PyObject* list; | 930 PyObject* list; |
| 931 |
| 932 /* FIXME: report as deprecated? */ |
940 | 933 |
941 if (!PyArg_ParseTuple(args, ":getchildren")) | 934 if (!PyArg_ParseTuple(args, ":getchildren")) |
942 return NULL; | 935 return NULL; |
943 | 936 |
944 if (!self->extra) | 937 if (!self->extra) |
945 return PyList_New(0); | 938 return PyList_New(0); |
946 | 939 |
947 list = PyList_New(self->extra->length); | 940 list = PyList_New(self->extra->length); |
948 if (!list) | 941 if (!list) |
949 return NULL; | 942 return NULL; |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1261 Py_DECREF(old); | 1254 Py_DECREF(old); |
1262 | 1255 |
1263 return 0; | 1256 return 0; |
1264 } | 1257 } |
1265 | 1258 |
1266 static PyObject* | 1259 static PyObject* |
1267 element_subscr(PyObject* self_, PyObject* item) | 1260 element_subscr(PyObject* self_, PyObject* item) |
1268 { | 1261 { |
1269 ElementObject* self = (ElementObject*) self_; | 1262 ElementObject* self = (ElementObject*) self_; |
1270 | 1263 |
| 1264 #if (PY_VERSION_HEX < 0x02050000) |
| 1265 if (PyInt_Check(item) || PyLong_Check(item)) { |
| 1266 long i = PyInt_AsLong(item); |
| 1267 #else |
1271 if (PyIndex_Check(item)) { | 1268 if (PyIndex_Check(item)) { |
1272 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); | 1269 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); |
1273 if (i==-1 && PyErr_Occurred()) { | 1270 #endif |
| 1271 |
| 1272 if (i == -1 && PyErr_Occurred()) { |
1274 return NULL; | 1273 return NULL; |
1275 } | 1274 } |
1276 if (i < 0 && self->extra) | 1275 if (i < 0 && self->extra) |
1277 i += self->extra->length; | 1276 i += self->extra->length; |
1278 return element_getitem(self_, i); | 1277 return element_getitem(self_, i); |
1279 } | 1278 } |
1280 else if (PySlice_Check(item)) { | 1279 else if (PySlice_Check(item)) { |
1281 Py_ssize_t start, stop, step, slicelen, cur, i; | 1280 Py_ssize_t start, stop, step, slicelen, cur, i; |
1282 PyObject* list; | 1281 PyObject* list; |
1283 | 1282 |
(...skipping 28 matching lines...) Expand all Loading... |
1312 "element indices must be integers"); | 1311 "element indices must be integers"); |
1313 return NULL; | 1312 return NULL; |
1314 } | 1313 } |
1315 } | 1314 } |
1316 | 1315 |
1317 static int | 1316 static int |
1318 element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value) | 1317 element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value) |
1319 { | 1318 { |
1320 ElementObject* self = (ElementObject*) self_; | 1319 ElementObject* self = (ElementObject*) self_; |
1321 | 1320 |
| 1321 #if (PY_VERSION_HEX < 0x02050000) |
| 1322 if (PyInt_Check(item) || PyLong_Check(item)) { |
| 1323 long i = PyInt_AsLong(item); |
| 1324 #else |
1322 if (PyIndex_Check(item)) { | 1325 if (PyIndex_Check(item)) { |
1323 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); | 1326 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); |
1324 | 1327 #endif |
1325 if (i==-1 && PyErr_Occurred()) { | 1328 |
| 1329 if (i == -1 && PyErr_Occurred()) { |
1326 return -1; | 1330 return -1; |
1327 } | 1331 } |
1328 if (i < 0 && self->extra) | 1332 if (i < 0 && self->extra) |
1329 i += self->extra->length; | 1333 i += self->extra->length; |
1330 return element_setitem(self_, i, value); | 1334 return element_setitem(self_, i, value); |
1331 } | 1335 } |
1332 else if (PySlice_Check(item)) { | 1336 else if (PySlice_Check(item)) { |
1333 Py_ssize_t start, stop, step, slicelen, newlen, cur, i; | 1337 Py_ssize_t start, stop, step, slicelen, newlen, cur, i; |
1334 | 1338 |
1335 PyObject* recycle = NULL; | 1339 PyObject* recycle = NULL; |
(...skipping 18 matching lines...) Expand all Loading... |
1354 "expected sequence, not \"%.200s\"", Py_TYPE(value)->tp_name | 1358 "expected sequence, not \"%.200s\"", Py_TYPE(value)->tp_name |
1355 ); | 1359 ); |
1356 return -1; | 1360 return -1; |
1357 } | 1361 } |
1358 newlen = PySequence_Size(seq); | 1362 newlen = PySequence_Size(seq); |
1359 } | 1363 } |
1360 | 1364 |
1361 if (step != 1 && newlen != slicelen) | 1365 if (step != 1 && newlen != slicelen) |
1362 { | 1366 { |
1363 PyErr_Format(PyExc_ValueError, | 1367 PyErr_Format(PyExc_ValueError, |
| 1368 #if (PY_VERSION_HEX < 0x02050000) |
| 1369 "attempt to assign sequence of size %d " |
| 1370 "to extended slice of size %d", |
| 1371 #else |
1364 "attempt to assign sequence of size %zd " | 1372 "attempt to assign sequence of size %zd " |
1365 "to extended slice of size %zd", | 1373 "to extended slice of size %zd", |
| 1374 #endif |
1366 newlen, slicelen | 1375 newlen, slicelen |
1367 ); | 1376 ); |
1368 return -1; | 1377 return -1; |
1369 } | 1378 } |
1370 | 1379 |
1371 | 1380 |
1372 /* Resize before creating the recycle bin, to prevent refleaks. */ | 1381 /* Resize before creating the recycle bin, to prevent refleaks. */ |
1373 if (newlen > slicelen) { | 1382 if (newlen > slicelen) { |
1374 if (element_resize(self, newlen - slicelen) < 0) { | 1383 if (element_resize(self, newlen - slicelen) < 0) { |
1375 if (seq) | 1384 if (seq) { |
1376 Py_DECREF(seq); | 1385 Py_DECREF(seq); |
| 1386 } |
1377 return -1; | 1387 return -1; |
1378 } | 1388 } |
1379 } | 1389 } |
1380 | 1390 |
1381 if (slicelen > 0) { | 1391 if (slicelen > 0) { |
1382 /* to avoid recursive calls to this method (via decref), move | 1392 /* to avoid recursive calls to this method (via decref), move |
1383 old items to the recycle bin here, and get rid of them when | 1393 old items to the recycle bin here, and get rid of them when |
1384 we're done modifying the element */ | 1394 we're done modifying the element */ |
1385 recycle = PyList_New(slicelen); | 1395 recycle = PyList_New(slicelen); |
1386 if (!recycle) { | 1396 if (!recycle) { |
1387 if (seq) | 1397 if (seq) { |
1388 Py_DECREF(seq); | 1398 Py_DECREF(seq); |
| 1399 } |
1389 return -1; | 1400 return -1; |
1390 } | 1401 } |
1391 for (cur = start, i = 0; i < slicelen; | 1402 for (cur = start, i = 0; i < slicelen; |
1392 cur += step, i++) | 1403 cur += step, i++) |
1393 PyList_SET_ITEM(recycle, i, self->extra->children[cur]); | 1404 PyList_SET_ITEM(recycle, i, self->extra->children[cur]); |
1394 } | 1405 } |
1395 | 1406 |
1396 if (newlen < slicelen) { | 1407 if (newlen < slicelen) { |
1397 /* delete slice */ | 1408 /* delete slice */ |
1398 for (i = stop; i < self->extra->length; i++) | 1409 for (i = stop; i < self->extra->length; i++) |
1399 self->extra->children[i + newlen - slicelen] = self->extra->chil
dren[i]; | 1410 self->extra->children[i + newlen - slicelen] = self->extra->chil
dren[i]; |
1400 } else if (newlen > slicelen) { | 1411 } else if (newlen > slicelen) { |
1401 /* insert slice */ | 1412 /* insert slice */ |
1402 for (i = self->extra->length-1; i >= stop; i--) | 1413 for (i = self->extra->length-1; i >= stop; i--) |
1403 self->extra->children[i + newlen - slicelen] = self->extra->chil
dren[i]; | 1414 self->extra->children[i + newlen - slicelen] = self->extra->chil
dren[i]; |
1404 } | 1415 } |
1405 | 1416 |
1406 /* replace the slice */ | 1417 /* replace the slice */ |
1407 for (cur = start, i = 0; i < newlen; | 1418 for (cur = start, i = 0; i < newlen; |
1408 cur += step, i++) { | 1419 cur += step, i++) { |
1409 PyObject* element = PySequence_Fast_GET_ITEM(seq, i); | 1420 PyObject* element = PySequence_Fast_GET_ITEM(seq, i); |
1410 Py_INCREF(element); | 1421 Py_INCREF(element); |
1411 self->extra->children[cur] = element; | 1422 self->extra->children[cur] = element; |
1412 } | 1423 } |
1413 | 1424 |
1414 self->extra->length += newlen - slicelen; | 1425 self->extra->length += newlen - slicelen; |
1415 | 1426 |
1416 if (seq) | 1427 if (seq) { |
1417 Py_DECREF(seq); | 1428 Py_DECREF(seq); |
| 1429 } |
1418 | 1430 |
1419 /* discard the recycle bin, and everything in it */ | 1431 /* discard the recycle bin, and everything in it */ |
1420 Py_XDECREF(recycle); | 1432 Py_XDECREF(recycle); |
1421 | 1433 |
1422 return 0; | 1434 return 0; |
1423 } | 1435 } |
1424 else { | 1436 else { |
1425 PyErr_SetString(PyExc_TypeError, | 1437 PyErr_SetString(PyExc_TypeError, |
1426 "element indices must be integers"); | 1438 "element indices must be integers"); |
1427 return -1; | 1439 return -1; |
(...skipping 11 matching lines...) Expand all Loading... |
1439 {"findtext", (PyCFunction) element_findtext, METH_VARARGS}, | 1451 {"findtext", (PyCFunction) element_findtext, METH_VARARGS}, |
1440 {"findall", (PyCFunction) element_findall, METH_VARARGS}, | 1452 {"findall", (PyCFunction) element_findall, METH_VARARGS}, |
1441 | 1453 |
1442 {"append", (PyCFunction) element_append, METH_VARARGS}, | 1454 {"append", (PyCFunction) element_append, METH_VARARGS}, |
1443 {"extend", (PyCFunction) element_extend, METH_VARARGS}, | 1455 {"extend", (PyCFunction) element_extend, METH_VARARGS}, |
1444 {"insert", (PyCFunction) element_insert, METH_VARARGS}, | 1456 {"insert", (PyCFunction) element_insert, METH_VARARGS}, |
1445 {"remove", (PyCFunction) element_remove, METH_VARARGS}, | 1457 {"remove", (PyCFunction) element_remove, METH_VARARGS}, |
1446 | 1458 |
1447 {"iter", (PyCFunction) element_iter, METH_VARARGS}, | 1459 {"iter", (PyCFunction) element_iter, METH_VARARGS}, |
1448 {"itertext", (PyCFunction) element_itertext, METH_VARARGS}, | 1460 {"itertext", (PyCFunction) element_itertext, METH_VARARGS}, |
| 1461 {"iterfind", (PyCFunction) element_iterfind, METH_VARARGS}, |
1449 | 1462 |
1450 {"getiterator", (PyCFunction) element_iter, METH_VARARGS}, | 1463 {"getiterator", (PyCFunction) element_iter, METH_VARARGS}, |
1451 {"getchildren", (PyCFunction) element_getchildren, METH_VARARGS}, | 1464 {"getchildren", (PyCFunction) element_getchildren, METH_VARARGS}, |
1452 | 1465 |
1453 {"items", (PyCFunction) element_items, METH_VARARGS}, | 1466 {"items", (PyCFunction) element_items, METH_VARARGS}, |
1454 {"keys", (PyCFunction) element_keys, METH_VARARGS}, | 1467 {"keys", (PyCFunction) element_keys, METH_VARARGS}, |
1455 | 1468 |
1456 {"makeelement", (PyCFunction) element_makeelement, METH_VARARGS}, | 1469 {"makeelement", (PyCFunction) element_makeelement, METH_VARARGS}, |
1457 | 1470 |
1458 {"__copy__", (PyCFunction) element_copy, METH_VARARGS}, | 1471 {"__copy__", (PyCFunction) element_copy, METH_VARARGS}, |
(...skipping 12 matching lines...) Expand all Loading... |
1471 {"!__reduce__", (PyCFunction) element_reduce, METH_VARARGS}, | 1484 {"!__reduce__", (PyCFunction) element_reduce, METH_VARARGS}, |
1472 | 1485 |
1473 {NULL, NULL} | 1486 {NULL, NULL} |
1474 }; | 1487 }; |
1475 | 1488 |
1476 static PyObject*·· | 1489 static PyObject*·· |
1477 element_getattr(ElementObject* self, char* name) | 1490 element_getattr(ElementObject* self, char* name) |
1478 { | 1491 { |
1479 PyObject* res; | 1492 PyObject* res; |
1480 | 1493 |
| 1494 /* handle common attributes first */ |
| 1495 if (strcmp(name, "tag") == 0) { |
| 1496 res = self->tag; |
| 1497 Py_INCREF(res); |
| 1498 return res; |
| 1499 } else if (strcmp(name, "text") == 0) { |
| 1500 res = element_get_text(self); |
| 1501 Py_INCREF(res); |
| 1502 return res; |
| 1503 } |
| 1504 |
| 1505 /* methods */ |
1481 res = Py_FindMethod(element_methods, (PyObject*) self, name); | 1506 res = Py_FindMethod(element_methods, (PyObject*) self, name); |
1482 if (res) | 1507 if (res) |
1483 return res; | 1508 return res; |
1484 | 1509 |
1485 PyErr_Clear(); | 1510 PyErr_Clear(); |
1486 | 1511 |
1487 if (strcmp(name, "tag") == 0) | 1512 /* less common attributes */ |
1488 res = self->tag; | 1513 if (strcmp(name, "tail") == 0) { |
1489 else if (strcmp(name, "text") == 0) | |
1490 res = element_get_text(self); | |
1491 else if (strcmp(name, "tail") == 0) { | |
1492 res = element_get_tail(self); | 1514 res = element_get_tail(self); |
1493 } else if (strcmp(name, "attrib") == 0) { | 1515 } else if (strcmp(name, "attrib") == 0) { |
1494 if (!self->extra) | 1516 if (!self->extra) |
1495 element_new_extra(self, NULL); | 1517 element_new_extra(self, NULL); |
1496 res = element_get_attrib(self); | 1518 res = element_get_attrib(self); |
1497 } else { | 1519 } else { |
1498 PyErr_SetString(PyExc_AttributeError, name); | 1520 PyErr_SetString(PyExc_AttributeError, name); |
1499 return NULL; | 1521 return NULL; |
1500 } | 1522 } |
1501 | 1523 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1549 0, /* sq_repeat */ | 1571 0, /* sq_repeat */ |
1550 element_getitem, | 1572 element_getitem, |
1551 0, | 1573 0, |
1552 element_setitem, | 1574 element_setitem, |
1553 0, | 1575 0, |
1554 }; | 1576 }; |
1555 | 1577 |
1556 static PyMappingMethods element_as_mapping = { | 1578 static PyMappingMethods element_as_mapping = { |
1557 (lenfunc) element_length, | 1579 (lenfunc) element_length, |
1558 (binaryfunc) element_subscr, | 1580 (binaryfunc) element_subscr, |
1559 (objobjargproc) element_ass_subscr | 1581 (objobjargproc) element_ass_subscr, |
1560 }; | 1582 }; |
1561 | 1583 |
1562 statichere PyTypeObject Element_Type = { | 1584 statichere PyTypeObject Element_Type = { |
1563 PyObject_HEAD_INIT(NULL) | 1585 PyObject_HEAD_INIT(NULL) |
1564 0, "Element", sizeof(ElementObject), 0, | 1586 0, "Element", sizeof(ElementObject), 0, |
1565 /* methods */ | 1587 /* methods */ |
1566 (destructor)element_dealloc, /* tp_dealloc */ | 1588 (destructor)element_dealloc, /* tp_dealloc */ |
1567 0, /* tp_print */ | 1589 0, /* tp_print */ |
1568 (getattrfunc)element_getattr, /* tp_getattr */ | 1590 (getattrfunc)element_getattr, /* tp_getattr */ |
1569 (setattrfunc)element_setattr, /* tp_setattr */ | 1591 (setattrfunc)element_setattr, /* tp_setattr */ |
1570 0, /* tp_compare */ | 1592 0, /* tp_compare */ |
1571 (reprfunc)element_repr, /* tp_repr */ | 1593 (reprfunc)element_repr, /* tp_repr */ |
1572 0, /* tp_as_number */ | 1594 0, /* tp_as_number */ |
1573 &element_as_sequence, /* tp_as_sequence */ | 1595 &element_as_sequence, /* tp_as_sequence */ |
1574 &element_as_mapping, /* tp_as_mapping */ | 1596 &element_as_mapping, /* tp_as_mapping */ |
1575 }; | 1597 }; |
1576 | 1598 |
1577 /* ==================================================================== */ | 1599 /* ==================================================================== */ |
1578 /* the tree builder type */ | 1600 /* the tree builder type */ |
1579 | 1601 |
1580 typedef struct { | 1602 typedef struct { |
1581 PyObject_HEAD | 1603 PyObject_HEAD |
1582 | 1604 |
1583 PyObject* root; /* root node (first created node) */ | 1605 PyObject* root; /* root node (first created node) */ |
1584 | 1606 |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1843 } else | 1865 } else |
1844 PyErr_Clear(); /* FIXME: propagate error */ | 1866 PyErr_Clear(); /* FIXME: propagate error */ |
1845 } | 1867 } |
1846 | 1868 |
1847 Py_INCREF(self->last); | 1869 Py_INCREF(self->last); |
1848 return (PyObject*) self->last; | 1870 return (PyObject*) self->last; |
1849 } | 1871 } |
1850 | 1872 |
1851 LOCAL(void) | 1873 LOCAL(void) |
1852 treebuilder_handle_namespace(TreeBuilderObject* self, int start, | 1874 treebuilder_handle_namespace(TreeBuilderObject* self, int start, |
1853 PyObject* prefix, PyObject *uri) | 1875 PyObject *prefix, PyObject *uri) |
1854 { | 1876 { |
1855 PyObject* res; | 1877 PyObject* res; |
1856 PyObject* action; | 1878 PyObject* action; |
1857 PyObject* parcel; | 1879 PyObject* parcel; |
1858 | 1880 |
1859 if (!self->events) | 1881 if (!self->events) |
1860 return; | 1882 return; |
1861 | 1883 |
1862 if (start) { | 1884 if (start) { |
1863 if (!self->start_ns_event_obj) | 1885 if (!self->start_ns_event_obj) |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2182 else if (self->handle_data) | 2204 else if (self->handle_data) |
2183 res = PyObject_CallFunction(self->handle_data, "O", value); | 2205 res = PyObject_CallFunction(self->handle_data, "O", value); |
2184 else | 2206 else |
2185 res = NULL; | 2207 res = NULL; |
2186 Py_XDECREF(res); | 2208 Py_XDECREF(res); |
2187 } else if (!PyErr_Occurred()) { | 2209 } else if (!PyErr_Occurred()) { |
2188 /* Report the first error, not the last */ | 2210 /* Report the first error, not the last */ |
2189 char message[128]; | 2211 char message[128]; |
2190 sprintf(message, "undefined entity &%.100s;", PyString_AS_STRING(key)); | 2212 sprintf(message, "undefined entity &%.100s;", PyString_AS_STRING(key)); |
2191 expat_set_error( | 2213 expat_set_error( |
2192 message, | 2214 message, |
2193 EXPAT(GetErrorLineNumber)(self->parser), | 2215 EXPAT(GetErrorLineNumber)(self->parser), |
2194 EXPAT(GetErrorColumnNumber)(self->parser) | 2216 EXPAT(GetErrorColumnNumber)(self->parser) |
2195 ); | 2217 ); |
2196 } | 2218 } |
2197 | 2219 |
2198 Py_DECREF(key); | 2220 Py_DECREF(key); |
2199 } | 2221 } |
2200 | 2222 |
2201 static void | 2223 static void |
2202 expat_start_handler(XMLParserObject* self, const XML_Char* tag_in, | 2224 expat_start_handler(XMLParserObject* self, const XML_Char* tag_in, |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2305 } | 2327 } |
2306 } | 2328 } |
2307 | 2329 |
2308 Py_XDECREF(res); | 2330 Py_XDECREF(res); |
2309 } | 2331 } |
2310 | 2332 |
2311 static void | 2333 static void |
2312 expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix, | 2334 expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix, |
2313 const XML_Char *uri) | 2335 const XML_Char *uri) |
2314 { | 2336 { |
2315 | |
2316 PyObject* sprefix = NULL; | 2337 PyObject* sprefix = NULL; |
2317 PyObject* suri = NULL; | 2338 PyObject* suri = NULL; |
2318 | 2339 |
2319 suri = makestring(uri, strlen(uri)); | 2340 suri = makestring(uri, strlen(uri)); |
2320 if (!suri) | 2341 if (!suri) |
2321 return; | 2342 return; |
2322 | 2343 |
2323 if (prefix) | 2344 if (prefix) |
2324 sprefix = makestring(prefix, strlen(prefix)); | 2345 sprefix = makestring(prefix, strlen(prefix)); |
2325 else | 2346 else |
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2858 /* python glue code */ | 2879 /* python glue code */ |
2859 | 2880 |
2860 g = PyDict_New(); | 2881 g = PyDict_New(); |
2861 if (!g) | 2882 if (!g) |
2862 return; | 2883 return; |
2863 | 2884 |
2864 PyDict_SetItemString(g, "__builtins__", PyEval_GetBuiltins()); | 2885 PyDict_SetItemString(g, "__builtins__", PyEval_GetBuiltins()); |
2865 | 2886 |
2866 bootstrap = ( | 2887 bootstrap = ( |
2867 | 2888 |
2868 #if (PY_VERSION_HEX >= 0x02020000 && PY_VERSION_HEX < 0x02030000) | |
2869 "from __future__ import generators\n" /* enable yield under 2.2 */ | |
2870 #endif | |
2871 | |
2872 "from copy import copy, deepcopy\n" | 2889 "from copy import copy, deepcopy\n" |
2873 | 2890 |
2874 "try:\n" | 2891 "try:\n" |
2875 " from xml.etree import ElementTree\n" | 2892 " from xml.etree import ElementTree\n" |
2876 "except ImportError:\n" | 2893 "except ImportError:\n" |
2877 " import ElementTree\n" | 2894 " import ElementTree\n" |
2878 "ET = ElementTree\n" | 2895 "ET = ElementTree\n" |
2879 "del ElementTree\n" | 2896 "del ElementTree\n" |
2880 | 2897 |
2881 "import _elementtree as cElementTree\n" | 2898 "import _elementtree as cElementTree\n" |
(...skipping 26 matching lines...) Expand all Loading... |
2908 " self._root = parser.close()\n" | 2925 " self._root = parser.close()\n" |
2909 " else:\n"· | 2926 " else:\n"· |
2910 " parser = cElementTree.XMLParser()\n" | 2927 " parser = cElementTree.XMLParser()\n" |
2911 " self._root = parser._parse(source)\n" | 2928 " self._root = parser._parse(source)\n" |
2912 " return self._root\n" | 2929 " return self._root\n" |
2913 "cElementTree.ElementTree = ElementTree\n" | 2930 "cElementTree.ElementTree = ElementTree\n" |
2914 | 2931 |
2915 "def iter(node, tag=None):\n" /* helper */ | 2932 "def iter(node, tag=None):\n" /* helper */ |
2916 " if tag == '*':\n" | 2933 " if tag == '*':\n" |
2917 " tag = None\n" | 2934 " tag = None\n" |
2918 #if (PY_VERSION_HEX < 0x02020000) | |
2919 " nodes = []\n" /* 2.1 doesn't have yield */ | |
2920 " if tag is None or node.tag == tag:\n" | |
2921 " nodes.append(node)\n" | |
2922 " for node in node:\n" | |
2923 " nodes.extend(iter(node, tag))\n" | |
2924 " return nodes\n" | |
2925 #else | |
2926 " if tag is None or node.tag == tag:\n" | 2935 " if tag is None or node.tag == tag:\n" |
2927 " yield node\n" | 2936 " yield node\n" |
2928 " for node in node:\n" | 2937 " for node in node:\n" |
2929 " for node in iter(node, tag):\n" | 2938 " for node in iter(node, tag):\n" |
2930 " yield node\n" | 2939 " yield node\n" |
2931 #endif | |
2932 | 2940 |
2933 "def itertext(node):\n" /* helper */ | 2941 "def itertext(node):\n" /* helper */ |
2934 " if node.text:\n" | 2942 " if node.text:\n" |
2935 " yield node.text\n" | 2943 " yield node.text\n" |
2936 " for e in node:\n" | 2944 " for e in node:\n" |
2937 " for s in e.itertext():\n" | 2945 " for s in e.itertext():\n" |
2938 " yield s\n" | 2946 " yield s\n" |
2939 " if e.tail:\n" | 2947 " if e.tail:\n" |
2940 " yield e.tail\n" | 2948 " yield e.tail\n" |
2941 | 2949 |
2942 "def parse(source, parser=None):\n" /* public */ | 2950 "def parse(source, parser=None):\n" /* public */ |
2943 " tree = ElementTree()\n" | 2951 " tree = ElementTree()\n" |
2944 " tree.parse(source, parser)\n" | 2952 " tree.parse(source, parser)\n" |
2945 " return tree\n" | 2953 " return tree\n" |
2946 "cElementTree.parse = parse\n" | 2954 "cElementTree.parse = parse\n" |
2947 | 2955 |
2948 #if (PY_VERSION_HEX < 0x02020000) | |
2949 "if hasattr(ET, 'iterparse'):\n" | |
2950 " cElementTree.iterparse = ET.iterparse\n" /* delegate on 2.1 */ | |
2951 #else | |
2952 "class iterparse(object):\n" | 2956 "class iterparse(object):\n" |
2953 " root = None\n" | 2957 " root = None\n" |
2954 " def __init__(self, file, events=None):\n" | 2958 " def __init__(self, file, events=None):\n" |
2955 " if not hasattr(file, 'read'):\n" | 2959 " if not hasattr(file, 'read'):\n" |
2956 " file = open(file, 'rb')\n" | 2960 " file = open(file, 'rb')\n" |
2957 " self._file = file\n" | 2961 " self._file = file\n" |
2958 " self._events = []\n" | 2962 " self._events = []\n" |
2959 " self._index = 0\n" | 2963 " self._index = 0\n" |
2960 " self.root = self._root = None\n" | 2964 " self.root = self._root = None\n" |
2961 " b = cElementTree.TreeBuilder()\n" | 2965 " b = cElementTree.TreeBuilder()\n" |
(...skipping 15 matching lines...) Expand all Loading... |
2977 " self._parser.feed(data)\n" | 2981 " self._parser.feed(data)\n" |
2978 " else:\n" | 2982 " else:\n" |
2979 " self._root = self._parser.close()\n" | 2983 " self._root = self._parser.close()\n" |
2980 " self._parser = None\n" | 2984 " self._parser = None\n" |
2981 " else:\n" | 2985 " else:\n" |
2982 " self._index = self._index + 1\n" | 2986 " self._index = self._index + 1\n" |
2983 " return item\n" | 2987 " return item\n" |
2984 " def __iter__(self):\n" | 2988 " def __iter__(self):\n" |
2985 " return self\n" | 2989 " return self\n" |
2986 "cElementTree.iterparse = iterparse\n" | 2990 "cElementTree.iterparse = iterparse\n" |
2987 #endif | |
2988 | 2991 |
2989 "class PIProxy:\n" | 2992 "class PIProxy:\n" |
2990 " def __call__(self, target, text=None):\n" | 2993 " def __call__(self, target, text=None):\n" |
2991 " element = cElementTree.Element(ET.PI)\n" | 2994 " element = cElementTree.Element(ET.PI)\n" |
2992 " element.text = target\n" | 2995 " element.text = target\n" |
2993 " if text:\n" | 2996 " if text:\n" |
2994 " element.text = element.text + ' ' + text\n" | 2997 " element.text = element.text + ' ' + text\n" |
2995 " return element\n" | 2998 " return element\n" |
2996 " def __cmp__(self, other):\n" | 2999 " def __cmp__(self, other):\n" |
2997 " return cmp(ET.PI, other)\n" | 3000 " return cmp(ET.PI, other)\n" |
2998 "cElementTree.PI = cElementTree.ProcessingInstruction = PIProxy()\n" | 3001 "cElementTree.PI = cElementTree.ProcessingInstruction = PIProxy()\n" |
2999 | 3002 |
3000 "def XML(text):\n" /* public */ | 3003 "def XML(text):\n" /* public */ |
3001 " parser = cElementTree.XMLParser()\n" | 3004 " parser = cElementTree.XMLParser()\n" |
3002 " parser.feed(text)\n" | 3005 " parser.feed(text)\n" |
3003 " return parser.close()\n" | 3006 " return parser.close()\n" |
3004 "cElementTree.XML = cElementTree.fromstring = XML\n" | 3007 "cElementTree.XML = cElementTree.fromstring = XML\n" |
3005 | 3008 |
3006 "def XMLID(text):\n" /* public */ | 3009 "def XMLID(text):\n" /* public */ |
3007 " tree = XML(text)\n" | 3010 " tree = XML(text)\n" |
3008 " ids = {}\n" | 3011 " ids = {}\n" |
3009 " for elem in tree.getiterator():\n" | 3012 " for elem in tree.iter():\n" |
3010 " id = elem.get('id')\n" | 3013 " id = elem.get('id')\n" |
3011 " if id:\n" | 3014 " if id:\n" |
3012 " ids[id] = elem\n" | 3015 " ids[id] = elem\n" |
3013 " return tree, ids\n" | 3016 " return tree, ids\n" |
3014 "cElementTree.XMLID = XMLID\n" | 3017 "cElementTree.XMLID = XMLID\n" |
3015 | 3018 |
3016 "try:\n" | 3019 "try:\n" |
3017 " register_namespace = ET.register_namespace\n" | 3020 " register_namespace = ET.register_namespace\n" |
3018 "except AttributeError:\n" | 3021 "except AttributeError:\n" |
3019 " def register_namespace(prefix, uri):\n" | 3022 " def register_namespace(prefix, uri):\n" |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3066 expat_capi = NULL; | 3069 expat_capi = NULL; |
3067 } | 3070 } |
3068 #endif | 3071 #endif |
3069 | 3072 |
3070 elementtree_parseerror_obj = PyErr_NewException( | 3073 elementtree_parseerror_obj = PyErr_NewException( |
3071 "cElementTree.ParseError", PyExc_SyntaxError, NULL | 3074 "cElementTree.ParseError", PyExc_SyntaxError, NULL |
3072 ); | 3075 ); |
3073 Py_INCREF(elementtree_parseerror_obj); | 3076 Py_INCREF(elementtree_parseerror_obj); |
3074 PyModule_AddObject(m, "ParseError", elementtree_parseerror_obj); | 3077 PyModule_AddObject(m, "ParseError", elementtree_parseerror_obj); |
3075 } | 3078 } |
LEFT | RIGHT |