Left: | ||
Right: |
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 $ |
flox
2010/02/10 09:34:37
Careful merge of upstream into trunk.
New additio
| |
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) |
27 * 2005-03-13 fl export Comment and ProcessingInstruction/PI helpers | 23 * 2005-03-13 fl export Comment and ProcessingInstruction/PI helpers |
28 * 2005-03-26 fl added Comment and PI support to XMLParser | 24 * 2005-03-26 fl added Comment and PI support to XMLParser |
29 * 2005-03-27 fl event optimizations; complain about bogus events | 25 * 2005-03-27 fl event optimizations; complain about bogus events |
30 * 2005-08-08 fl fixed read error handling in parse | 26 * 2005-08-08 fl fixed read error handling in parse |
31 * 2005-08-11 fl added runtime test for copy workaround (1.0.3) | 27 * 2005-08-11 fl added runtime test for copy workaround (1.0.3) |
32 * 2005-12-13 fl added expat_capi support (for xml.etree) (1.0.4) | 28 * 2005-12-13 fl added expat_capi support (for xml.etree) (1.0.4) |
33 * 2005-12-16 fl added support for non-standard encodings | 29 * 2005-12-16 fl added support for non-standard encodings |
34 * 2006-03-08 fl fixed a couple of potential null-refs and leaks | 30 * 2006-03-08 fl fixed a couple of potential null-refs and leaks |
35 * 2006-03-12 fl merge in 2.5 ssize_t changes | 31 * 2006-03-12 fl merge in 2.5 ssize_t changes |
36 * 2007-08-25 fl call custom builder's close method from XMLParser | 32 * 2007-08-25 fl call custom builder's close method from XMLParser |
37 * 2007-08-31 fl added iter, extend from ET 1.3 | 33 * 2007-08-31 fl added iter, extend from ET 1.3 |
38 * 2007-09-01 fl fixed ParseError exception, setslice source type, etc | 34 * 2007-09-01 fl fixed ParseError exception, setslice source type, etc |
39 * 2007-09-03 fl fixed handling of negative insert indexes | 35 * 2007-09-03 fl fixed handling of negative insert indexes |
40 * 2007-09-04 fl added itertext from ET 1.3 | 36 * 2007-09-04 fl added itertext from ET 1.3 |
41 * 2007-09-06 fl added position attribute to ParseError exception | 37 * 2007-09-06 fl added position attribute to ParseError exception |
42 * 2008-06-06 fl delay error reporting in iterparse (from Hrvoje Niksic) | 38 * 2008-06-06 fl delay error reporting in iterparse (from Hrvoje Niksic) |
43 * 2009-01-10 fl added experimental CAPI interface | |
44 * | 39 * |
45 * Copyright (c) 1999-2009 by Secret Labs AB. All rights reserved. | 40 * Copyright (c) 1999-2009 by Secret Labs AB. All rights reserved. |
46 * Copyright (c) 1999-2009 by Fredrik Lundh. | 41 * Copyright (c) 1999-2009 by Fredrik Lundh. |
47 * | 42 * |
48 * info@pythonware.com | 43 * info@pythonware.com |
49 * http://www.pythonware.com | 44 * http://www.pythonware.com |
50 */ | 45 */ |
51 | 46 |
52 /* Licensed to PSF under a Contributor Agreement. */ | 47 /* Licensed to PSF under a Contributor Agreement. */ |
53 /* See http://www.python.org/psf/license for licensing details. */ | 48 /* See http://www.python.org/psf/license for licensing details. */ |
54 | 49 |
55 #include "Python.h" | 50 #include "Python.h" |
56 | 51 |
57 #include "celementtree.h" /* CAPI stuff */ | 52 #define VERSION "1.0.6" |
58 | |
59 #define VERSION "1.0.6a2" | |
60 | 53 |
61 /* -------------------------------------------------------------------- */ | 54 /* -------------------------------------------------------------------- */ |
62 /* configuration */ | 55 /* configuration */ |
63 | 56 |
64 /* Leave defined to include the expat-based XMLParser type */ | 57 /* Leave defined to include the expat-based XMLParser type */ |
65 #define USE_EXPAT | 58 #define USE_EXPAT |
66 | 59 |
67 /* Define to do all expat calls via pyexpat's embedded expat library */ | 60 /* Define to do all expat calls via pyexpat's embedded expat library */ |
68 /* #define USE_PYEXPAT_CAPI */ | 61 /* #define USE_PYEXPAT_CAPI */ |
69 | 62 |
(...skipping 25 matching lines...) Expand all Loading... | |
95 #endif | 88 #endif |
96 | 89 |
97 /* compiler tweaks */ | 90 /* compiler tweaks */ |
98 #if defined(_MSC_VER) | 91 #if defined(_MSC_VER) |
99 #define LOCAL(type) static __inline type __fastcall | 92 #define LOCAL(type) static __inline type __fastcall |
100 #else | 93 #else |
101 #define LOCAL(type) static type | 94 #define LOCAL(type) static type |
102 #endif | 95 #endif |
103 | 96 |
104 /* 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 | |
105 #if (PY_VERSION_HEX < 0x02050000) | 103 #if (PY_VERSION_HEX < 0x02050000) |
106 typedef int Py_ssize_t; | 104 typedef int Py_ssize_t; |
107 #define lenfunc inquiry | 105 #define lenfunc inquiry |
108 #endif | 106 #endif |
109 | 107 |
110 #if (PY_VERSION_HEX < 0x02040000) | 108 #if (PY_VERSION_HEX < 0x02040000) |
111 #define PyDict_CheckExact PyDict_Check | 109 #define PyDict_CheckExact PyDict_Check |
112 #if (PY_VERSION_HEX < 0x02020000) | |
113 #define PyList_CheckExact PyList_Check | |
114 #define PyString_CheckExact PyString_Check | |
115 #if (PY_VERSION_HEX >= 0x01060000) | |
116 #define Py_USING_UNICODE /* always enabled for 2.0 and 2.1 */ | |
117 #endif | |
118 #endif | |
119 #endif | |
120 | 110 |
121 #if !defined(Py_RETURN_NONE) | 111 #if !defined(Py_RETURN_NONE) |
122 #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 | |
123 #endif | 114 #endif |
124 | 115 |
125 /* macros used to store 'join' flags in string object pointers. note | 116 /* macros used to store 'join' flags in string object pointers. note |
126 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 |
127 JOIN_OBJ. see comments in the ElementObject definition for more | 118 JOIN_OBJ. see comments in the ElementObject definition for more |
128 info. */ | 119 info. */ |
129 #define JOIN_GET(p) ((Py_uintptr_t) (p) & 1) | 120 #define JOIN_GET(p) ((Py_uintptr_t) (p) & 1) |
130 #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))) |
131 #define JOIN_OBJ(p) ((PyObject*) ((Py_uintptr_t) (p) & ~1)) | 122 #define JOIN_OBJ(p) ((PyObject*) ((Py_uintptr_t) (p) & ~1)) |
132 | 123 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
211 PyTuple_SET_ITEM(args, 0, list); | 202 PyTuple_SET_ITEM(args, 0, list); |
212 | 203 |
213 result = PyObject_CallObject(function, args); | 204 result = PyObject_CallObject(function, args); |
214 | 205 |
215 Py_DECREF(args); /* also removes list */ | 206 Py_DECREF(args); /* also removes list */ |
216 Py_DECREF(function); | 207 Py_DECREF(function); |
217 Py_DECREF(joiner); | 208 Py_DECREF(joiner); |
218 | 209 |
219 return result; | 210 return result; |
220 } | 211 } |
221 | |
222 #if (PY_VERSION_HEX < 0x02020000) | |
223 LOCAL(int) | |
224 PyDict_Update(PyObject* dict, PyObject* other) | |
225 { | |
226 /* PyDict_Update emulation for 2.1 and earlier */ | |
227 | |
228 PyObject* res; | |
229 ···· | |
230 res = PyObject_CallMethod(dict, "update", "O", other); | |
231 if (!res) | |
232 return -1; | |
233 | |
234 Py_DECREF(res); | |
235 return 0; | |
236 } | |
237 #endif | |
238 | 212 |
239 /* -------------------------------------------------------------------- */ | 213 /* -------------------------------------------------------------------- */ |
240 /* the element type */ | 214 /* the element type */ |
241 | 215 |
242 typedef struct { | 216 typedef struct { |
243 | 217 |
244 /* attributes (a dictionary object), or None if no attributes */ | 218 /* attributes (a dictionary object), or None if no attributes */ |
245 PyObject* attrib; | 219 PyObject* attrib; |
246 | 220 |
247 /* child elements */ | 221 /* child elements */ |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
422 return -1; | 396 return -1; |
423 | 397 |
424 Py_INCREF(element); | 398 Py_INCREF(element); |
425 self->extra->children[self->extra->length] = element; | 399 self->extra->children[self->extra->length] = element; |
426 | 400 |
427 self->extra->length++; | 401 self->extra->length++; |
428 | 402 |
429 return 0; | 403 return 0; |
430 } | 404 } |
431 | 405 |
432 static PyObject* | |
433 element_get_type(void) | |
434 { | |
435 /* return borrowed reference to type object */ | |
436 | |
437 return (PyObject*) &Element_Type; | |
438 } | |
439 | |
440 LOCAL(PyObject*) | 406 LOCAL(PyObject*) |
441 element_get_attrib(ElementObject* self) | 407 element_get_attrib(ElementObject* self) |
442 { | 408 { |
443 /* return borrowed reference to attrib dictionary */ | 409 /* return borrowed reference to attrib dictionary */ |
444 /* note: this function assumes that the extra section exists */ | 410 /* note: this function assumes that the extra section exists */ |
445 | 411 |
446 PyObject* res = self->extra->attrib; | 412 PyObject* res = self->extra->attrib; |
447 | 413 |
448 if (res == Py_None) { | 414 if (res == Py_None) { |
415 Py_DECREF(res); | |
449 /* create missing dictionary */ | 416 /* create missing dictionary */ |
450 res = PyDict_New(); | 417 res = PyDict_New(); |
451 if (!res) | 418 if (!res) |
452 return NULL; | 419 return NULL; |
453 self->extra->attrib = res; | 420 self->extra->attrib = res; |
454 } | 421 } |
455 | 422 |
456 return res; | 423 return res; |
457 } | 424 } |
458 | 425 |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
788 static PyObject* | 755 static PyObject* |
789 element_extend(ElementObject* self, PyObject* args) | 756 element_extend(ElementObject* self, PyObject* args) |
790 { | 757 { |
791 PyObject* seq; | 758 PyObject* seq; |
792 Py_ssize_t i, seqlen = 0; | 759 Py_ssize_t i, seqlen = 0; |
793 | 760 |
794 PyObject* seq_in; | 761 PyObject* seq_in; |
795 if (!PyArg_ParseTuple(args, "O:extend", &seq_in)) | 762 if (!PyArg_ParseTuple(args, "O:extend", &seq_in)) |
796 return NULL; | 763 return NULL; |
797 | 764 |
798 seq = PySequence_Fast(seq_in, ""); | 765 seq = PySequence_Fast(seq_in, ""); |
Antoine Pitrou
2010/02/10 13:14:37
The second argument (error message if seq_in is no
| |
799 if (!seq) | 766 if (!seq) { |
800 return NULL; | 767 PyErr_Format( |
768 PyExc_TypeError, | |
769 "expected sequence, not \"%.200s\"", Py_TYPE(seq_in)->tp_name | |
770 ); | |
771 return NULL; | |
772 } | |
801 | 773 |
802 seqlen = PySequence_Size(seq); | 774 seqlen = PySequence_Size(seq); |
803 for (i = 0; i < seqlen; i++) { | 775 for (i = 0; i < seqlen; i++) { |
804 PyObject* element = PySequence_Fast_GET_ITEM(seq, i); | 776 PyObject* element = PySequence_Fast_GET_ITEM(seq, i); |
805 if (element_add_subelement(self, element) < 0) { | 777 if (element_add_subelement(self, element) < 0) { |
806 Py_DECREF(seq); | 778 Py_DECREF(seq); |
807 return NULL; | 779 return NULL; |
808 } | 780 } |
809 } | 781 } |
810 | 782 |
811 Py_DECREF(seq); | 783 Py_DECREF(seq); |
812 | 784 |
813 Py_RETURN_NONE; | 785 Py_RETURN_NONE; |
814 } | 786 } |
815 | 787 |
816 static PyObject* | 788 static PyObject* |
817 element_find(ElementObject* self, PyObject* args) | 789 element_find(ElementObject* self, PyObject* args) |
818 { | 790 { |
819 int i; | 791 int i; |
820 | 792 |
821 PyObject* tag; | 793 PyObject* tag; |
822 if (!PyArg_ParseTuple(args, "O:find", &tag)) | 794 PyObject* namespaces = Py_None; |
823 return NULL; | 795 if (!PyArg_ParseTuple(args, "O|O:find", &tag, &namespaces)) |
824 | 796 return NULL; |
825 if (checkpath(tag)) | 797 |
798 if (checkpath(tag) || namespaces != Py_None) | |
826 return PyObject_CallMethod( | 799 return PyObject_CallMethod( |
827 elementpath_obj, "find", "OO", self, tag | 800 elementpath_obj, "find", "OOO", self, tag, namespaces |
828 ); | 801 ); |
829 | 802 |
830 if (!self->extra) | 803 if (!self->extra) |
831 Py_RETURN_NONE; | 804 Py_RETURN_NONE; |
832 ········ | 805 ········ |
833 for (i = 0; i < self->extra->length; i++) { | 806 for (i = 0; i < self->extra->length; i++) { |
834 PyObject* item = self->extra->children[i]; | 807 PyObject* item = self->extra->children[i]; |
835 if (Element_CheckExact(item) && | 808 if (Element_CheckExact(item) && |
836 PyObject_Compare(((ElementObject*)item)->tag, tag) == 0) { | 809 PyObject_Compare(((ElementObject*)item)->tag, tag) == 0) { |
837 Py_INCREF(item); | 810 Py_INCREF(item); |
838 return item; | 811 return item; |
839 } | 812 } |
840 } | 813 } |
841 | 814 |
842 Py_RETURN_NONE; | 815 Py_RETURN_NONE; |
843 } | 816 } |
844 | 817 |
845 static PyObject* | 818 static PyObject* |
846 element_findtext(ElementObject* self, PyObject* args) | 819 element_findtext(ElementObject* self, PyObject* args) |
847 { | 820 { |
848 int i; | 821 int i; |
849 | 822 |
850 PyObject* tag; | 823 PyObject* tag; |
851 PyObject* default_value = Py_None; | 824 PyObject* default_value = Py_None; |
852 if (!PyArg_ParseTuple(args, "O|O:findtext", &tag, &default_value)) | 825 PyObject* namespaces = Py_None; |
853 return NULL; | 826 if (!PyArg_ParseTuple(args, "O|OO:findtext", &tag, &default_value, &namespac es)) |
854 | 827 return NULL; |
855 if (checkpath(tag)) | 828 |
829 if (checkpath(tag) || namespaces != Py_None) | |
856 return PyObject_CallMethod( | 830 return PyObject_CallMethod( |
857 elementpath_obj, "findtext", "OOO", self, tag, default_value | 831 elementpath_obj, "findtext", "OOOO", self, tag, default_value, names paces |
858 ); | 832 ); |
859 | 833 |
860 if (!self->extra) { | 834 if (!self->extra) { |
861 Py_INCREF(default_value); | 835 Py_INCREF(default_value); |
862 return default_value; | 836 return default_value; |
863 } | 837 } |
864 | 838 |
865 for (i = 0; i < self->extra->length; i++) { | 839 for (i = 0; i < self->extra->length; i++) { |
866 ElementObject* item = (ElementObject*) self->extra->children[i]; | 840 ElementObject* item = (ElementObject*) self->extra->children[i]; |
867 if (Element_CheckExact(item) && !PyObject_Compare(item->tag, tag)) { | 841 if (Element_CheckExact(item) && !PyObject_Compare(item->tag, tag)) { |
868 PyObject* text = element_get_text(item); | 842 PyObject* text = element_get_text(item); |
869 if (text == Py_None) | 843 if (text == Py_None) |
870 return PyString_FromString(""); | 844 return PyString_FromString(""); |
871 Py_XINCREF(text); | 845 Py_XINCREF(text); |
872 return text; | 846 return text; |
873 } | 847 } |
874 } | 848 } |
875 | 849 |
876 Py_INCREF(default_value); | 850 Py_INCREF(default_value); |
877 return default_value; | 851 return default_value; |
878 } | 852 } |
879 | 853 |
880 static PyObject* | 854 static PyObject* |
881 element_findall(ElementObject* self, PyObject* args) | 855 element_findall(ElementObject* self, PyObject* args) |
882 { | 856 { |
883 /* int i; | 857 int i; |
884 PyObject* out; */ | 858 PyObject* out; |
885 | 859 |
886 PyObject* tag; | 860 PyObject* tag; |
887 if (!PyArg_ParseTuple(args, "O:findall", &tag)) | 861 PyObject* namespaces = Py_None; |
888 return NULL; | 862 if (!PyArg_ParseTuple(args, "O|O:findall", &tag, &namespaces)) |
889 | 863 return NULL; |
890 /* Use the Python implementation without condition. | 864 |
891 The method will return an iterator in all cases. | 865 if (checkpath(tag) || namespaces != Py_None) |
892 See bug 6472. */ | |
Antoine Pitrou
2010/02/10 13:14:37
Rather than disabling the C implementation, we cou
| |
893 | |
894 /* if (checkpath(tag)) */ | |
895 | |
896 return PyObject_CallMethod( | 866 return PyObject_CallMethod( |
897 elementpath_obj, "findall", "OO", self, tag | 867 elementpath_obj, "findall", "OOO", self, tag, namespaces |
898 ); | 868 ); |
899 | 869 |
900 /* | |
901 out = PyList_New(0); | 870 out = PyList_New(0); |
902 if (!out) | 871 if (!out) |
903 return NULL; | 872 return NULL; |
904 | 873 |
905 if (!self->extra) | 874 if (!self->extra) |
906 return out; | 875 return out; |
907 | 876 |
908 for (i = 0; i < self->extra->length; i++) { | 877 for (i = 0; i < self->extra->length; i++) { |
909 PyObject* item = self->extra->children[i]; | 878 PyObject* item = self->extra->children[i]; |
910 if (Element_CheckExact(item) && | 879 if (Element_CheckExact(item) && |
911 PyObject_Compare(((ElementObject*)item)->tag, tag) == 0) { | 880 PyObject_Compare(((ElementObject*)item)->tag, tag) == 0) { |
912 if (PyList_Append(out, item) < 0) { | 881 if (PyList_Append(out, item) < 0) { |
913 Py_DECREF(out); | 882 Py_DECREF(out); |
914 return NULL; | 883 return NULL; |
915 } | 884 } |
916 } | 885 } |
917 } | 886 } |
918 | 887 |
919 return out; | 888 return out; |
920 */ | 889 } |
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 ); | |
921 } | 902 } |
922 | 903 |
923 static PyObject* | 904 static PyObject* |
924 element_get(ElementObject* self, PyObject* args) | 905 element_get(ElementObject* self, PyObject* args) |
925 { | 906 { |
926 PyObject* value; | 907 PyObject* value; |
927 | 908 |
928 PyObject* key; | 909 PyObject* key; |
929 PyObject* default_value = Py_None; | 910 PyObject* default_value = Py_None; |
930 if (!PyArg_ParseTuple(args, "O|O:get", &key, &default_value)) | 911 if (!PyArg_ParseTuple(args, "O|O:get", &key, &default_value)) |
(...skipping 10 matching lines...) Expand all Loading... | |
941 Py_INCREF(value); | 922 Py_INCREF(value); |
942 return value; | 923 return value; |
943 } | 924 } |
944 | 925 |
945 static PyObject* | 926 static PyObject* |
946 element_getchildren(ElementObject* self, PyObject* args) | 927 element_getchildren(ElementObject* self, PyObject* args) |
947 { | 928 { |
948 int i; | 929 int i; |
949 PyObject* list; | 930 PyObject* list; |
950 | 931 |
932 /* FIXME: report as deprecated? */ | |
933 | |
951 if (!PyArg_ParseTuple(args, ":getchildren")) | 934 if (!PyArg_ParseTuple(args, ":getchildren")) |
952 return NULL; | 935 return NULL; |
953 | 936 |
954 if (!self->extra) | 937 if (!self->extra) |
955 return PyList_New(0); | 938 return PyList_New(0); |
956 | 939 |
957 list = PyList_New(self->extra->length); | 940 list = PyList_New(self->extra->length); |
958 if (!list) | 941 if (!list) |
959 return NULL; | 942 return NULL; |
960 | 943 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1036 if (!self->extra || index < 0 || index >= self->extra->length) { | 1019 if (!self->extra || index < 0 || index >= self->extra->length) { |
1037 PyErr_SetString( | 1020 PyErr_SetString( |
1038 PyExc_IndexError, | 1021 PyExc_IndexError, |
1039 "child index out of range" | 1022 "child index out of range" |
1040 ); | 1023 ); |
1041 return NULL; | 1024 return NULL; |
1042 } | 1025 } |
1043 | 1026 |
1044 Py_INCREF(self->extra->children[index]); | 1027 Py_INCREF(self->extra->children[index]); |
1045 return self->extra->children[index]; | 1028 return self->extra->children[index]; |
1046 } | |
1047 | |
1048 static PyObject* | |
1049 element_getslice(PyObject* self_, Py_ssize_t start, Py_ssize_t end) | |
1050 { | |
1051 ElementObject* self = (ElementObject*) self_; | |
1052 Py_ssize_t i; | |
1053 PyObject* list; | |
1054 | |
1055 if (!self->extra) | |
1056 return PyList_New(0); | |
1057 | |
1058 /* standard clamping */ | |
1059 if (start < 0) | |
1060 start = 0; | |
1061 if (end < 0) | |
1062 end = 0; | |
1063 if (end > self->extra->length) | |
1064 end = self->extra->length; | |
1065 if (start > end) | |
1066 start = end; | |
1067 | |
1068 list = PyList_New(end - start); | |
1069 if (!list) | |
1070 return NULL; | |
1071 | |
1072 for (i = start; i < end; i++) { | |
1073 PyObject* item = self->extra->children[i]; | |
1074 Py_INCREF(item); | |
1075 PyList_SET_ITEM(list, i - start, item); | |
1076 } | |
1077 | |
1078 return list; | |
1079 } | 1029 } |
1080 | 1030 |
1081 static PyObject* | 1031 static PyObject* |
1082 element_insert(ElementObject* self, PyObject* args) | 1032 element_insert(ElementObject* self, PyObject* args) |
1083 { | 1033 { |
1084 int i; | 1034 int i; |
1085 | 1035 |
1086 int index; | 1036 int index; |
1087 PyObject* element; | 1037 PyObject* element; |
1088 if (!PyArg_ParseTuple(args, "iO!:insert", &index, | 1038 if (!PyArg_ParseTuple(args, "iO!:insert", &index, |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1267 element_new_extra(self, NULL); | 1217 element_new_extra(self, NULL); |
1268 | 1218 |
1269 attrib = element_get_attrib(self); | 1219 attrib = element_get_attrib(self); |
1270 if (!attrib) | 1220 if (!attrib) |
1271 return NULL; | 1221 return NULL; |
1272 | 1222 |
1273 if (PyDict_SetItem(attrib, key, value) < 0) | 1223 if (PyDict_SetItem(attrib, key, value) < 0) |
1274 return NULL; | 1224 return NULL; |
1275 | 1225 |
1276 Py_RETURN_NONE; | 1226 Py_RETURN_NONE; |
1277 } | |
1278 | |
1279 static int | |
1280 element_setslice(PyObject* self_, Py_ssize_t start, Py_ssize_t end, PyObject* se q_in) | |
1281 { | |
1282 ElementObject* self = (ElementObject*) self_; | |
1283 Py_ssize_t i, new, old; | |
1284 PyObject* recycle = NULL; | |
1285 PyObject* seq = NULL; | |
1286 | |
1287 if (!self->extra) | |
1288 element_new_extra(self, NULL); | |
1289 | |
1290 /* standard clamping */ | |
1291 if (start < 0) | |
1292 start = 0; | |
1293 if (end < 0) | |
1294 end = 0; | |
1295 if (end > self->extra->length) | |
1296 end = self->extra->length; | |
1297 if (start > end) | |
1298 start = end; | |
1299 | |
1300 old = end - start; | |
1301 | |
1302 if (seq_in == NULL) | |
1303 new = 0; | |
1304 else { | |
1305 seq = PySequence_Fast(seq_in, ""); | |
1306 if (!seq) { | |
1307 PyErr_Format( | |
1308 PyExc_TypeError, | |
1309 "expected sequence, not \"%.200s\"", Py_TYPE(seq_in)->tp_name | |
1310 ); | |
1311 return -1; | |
1312 } | |
1313 new = PySequence_Size(seq); | |
1314 } | |
1315 | |
1316 if (old > 0) { | |
1317 /* to avoid recursive calls to this method (via decref), move | |
1318 old items to the recycle bin here, and get rid of them when | |
1319 we're done modifying the element */ | |
1320 recycle = PyList_New(old); | |
1321 for (i = 0; i < old; i++) | |
1322 PyList_SET_ITEM(recycle, i, self->extra->children[i + start]); | |
1323 } | |
1324 | |
1325 if (new < old) { | |
1326 /* delete slice */ | |
1327 for (i = end; i < self->extra->length; i++) | |
1328 self->extra->children[i + new - old] = self->extra->children[i]; | |
1329 } else if (new > old) { | |
1330 /* insert slice */ | |
1331 if (element_resize(self, new - old) < 0) { | |
1332 if (seq) | |
1333 Py_DECREF(seq); | |
1334 return -1; | |
1335 } | |
1336 for (i = self->extra->length-1; i >= end; i--) | |
1337 self->extra->children[i + new - old] = self->extra->children[i]; | |
1338 } | |
1339 | |
1340 /* replace the slice */ | |
1341 for (i = 0; i < new; i++) { | |
1342 PyObject* element = PySequence_Fast_GET_ITEM(seq, i); | |
1343 Py_INCREF(element); | |
1344 self->extra->children[i + start] = element; | |
1345 } | |
1346 | |
1347 self->extra->length += new - old; | |
1348 | |
1349 if (seq) | |
1350 Py_DECREF(seq); | |
1351 | |
1352 /* discard the recycle bin, and everything in it */ | |
1353 Py_XDECREF(recycle); | |
1354 | |
1355 return 0; | |
1356 } | 1227 } |
1357 | 1228 |
1358 static int | 1229 static int |
1359 element_setitem(PyObject* self_, Py_ssize_t index, PyObject* item) | 1230 element_setitem(PyObject* self_, Py_ssize_t index, PyObject* item) |
1360 { | 1231 { |
1361 ElementObject* self = (ElementObject*) self_; | 1232 ElementObject* self = (ElementObject*) self_; |
1362 int i; | 1233 int i; |
1363 PyObject* old; | 1234 PyObject* old; |
1364 | 1235 |
1365 if (!self->extra || index < 0 || index >= self->extra->length) { | 1236 if (!self->extra || index < 0 || index >= self->extra->length) { |
(...skipping 17 matching lines...) Expand all Loading... | |
1383 Py_DECREF(old); | 1254 Py_DECREF(old); |
1384 | 1255 |
1385 return 0; | 1256 return 0; |
1386 } | 1257 } |
1387 | 1258 |
1388 static PyObject* | 1259 static PyObject* |
1389 element_subscr(PyObject* self_, PyObject* item) | 1260 element_subscr(PyObject* self_, PyObject* item) |
1390 { | 1261 { |
1391 ElementObject* self = (ElementObject*) self_; | 1262 ElementObject* self = (ElementObject*) self_; |
1392 | 1263 |
1264 #if (PY_VERSION_HEX < 0x02050000) | |
1265 if (PyInt_Check(item) || PyLong_Check(item)) { | |
1266 long i = PyInt_AsLong(item); | |
1267 #else | |
1393 if (PyIndex_Check(item)) { | 1268 if (PyIndex_Check(item)) { |
1394 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); | 1269 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); |
1395 if (i==-1 && PyErr_Occurred()) { | 1270 #endif |
1271 | |
1272 if (i == -1 && PyErr_Occurred()) { | |
1396 return NULL; | 1273 return NULL; |
1397 } | 1274 } |
1398 if (i < 0 && self->extra) | 1275 if (i < 0 && self->extra) |
1399 i += self->extra->length; | 1276 i += self->extra->length; |
1400 return element_getitem(self_, i); | 1277 return element_getitem(self_, i); |
1401 } | 1278 } |
1402 else if (PySlice_Check(item)) { | 1279 else if (PySlice_Check(item)) { |
1403 Py_ssize_t start, stop, step, slicelen, cur, i; | 1280 Py_ssize_t start, stop, step, slicelen, cur, i; |
1404 PyObject* list; | 1281 PyObject* list; |
1405 | 1282 |
(...skipping 28 matching lines...) Expand all Loading... | |
1434 "element indices must be integers"); | 1311 "element indices must be integers"); |
1435 return NULL; | 1312 return NULL; |
1436 } | 1313 } |
1437 } | 1314 } |
1438 | 1315 |
1439 static int | 1316 static int |
1440 element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value) | 1317 element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value) |
1441 { | 1318 { |
1442 ElementObject* self = (ElementObject*) self_; | 1319 ElementObject* self = (ElementObject*) self_; |
1443 | 1320 |
1321 #if (PY_VERSION_HEX < 0x02050000) | |
1322 if (PyInt_Check(item) || PyLong_Check(item)) { | |
1323 long i = PyInt_AsLong(item); | |
1324 #else | |
1444 if (PyIndex_Check(item)) { | 1325 if (PyIndex_Check(item)) { |
1445 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); | 1326 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); |
1446 | 1327 #endif |
1447 if (i==-1 && PyErr_Occurred()) { | 1328 |
1329 if (i == -1 && PyErr_Occurred()) { | |
1448 return -1; | 1330 return -1; |
1449 } | 1331 } |
1450 if (i < 0 && self->extra) | 1332 if (i < 0 && self->extra) |
1451 i += self->extra->length; | 1333 i += self->extra->length; |
1452 return element_setitem(self_, i, value); | 1334 return element_setitem(self_, i, value); |
1453 } | 1335 } |
1454 else if (PySlice_Check(item)) { | 1336 else if (PySlice_Check(item)) { |
1455 Py_ssize_t start, stop, step, slicelen, newlen, cur, i; | 1337 Py_ssize_t start, stop, step, slicelen, newlen, cur, i; |
1456 | 1338 |
1457 PyObject* recycle = NULL; | 1339 PyObject* recycle = NULL; |
(...skipping 18 matching lines...) Expand all Loading... | |
1476 "expected sequence, not \"%.200s\"", Py_TYPE(value)->tp_name | 1358 "expected sequence, not \"%.200s\"", Py_TYPE(value)->tp_name |
1477 ); | 1359 ); |
1478 return -1; | 1360 return -1; |
1479 } | 1361 } |
1480 newlen = PySequence_Size(seq); | 1362 newlen = PySequence_Size(seq); |
1481 } | 1363 } |
1482 | 1364 |
1483 if (step != 1 && newlen != slicelen) | 1365 if (step != 1 && newlen != slicelen) |
1484 { | 1366 { |
1485 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 | |
1486 "attempt to assign sequence of size %zd " | 1372 "attempt to assign sequence of size %zd " |
1487 "to extended slice of size %zd", | 1373 "to extended slice of size %zd", |
1374 #endif | |
1488 newlen, slicelen | 1375 newlen, slicelen |
1489 ); | 1376 ); |
1490 return -1; | 1377 return -1; |
1491 } | 1378 } |
1492 | 1379 |
1380 | |
1381 /* Resize before creating the recycle bin, to prevent refleaks. */ | |
1382 if (newlen > slicelen) { | |
1383 if (element_resize(self, newlen - slicelen) < 0) { | |
1384 if (seq) { | |
1385 Py_DECREF(seq); | |
1386 } | |
1387 return -1; | |
1388 } | |
1389 } | |
1493 | 1390 |
1494 if (slicelen > 0) { | 1391 if (slicelen > 0) { |
1495 /* to avoid recursive calls to this method (via decref), move | 1392 /* to avoid recursive calls to this method (via decref), move |
1496 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 |
1497 we're done modifying the element */ | 1394 we're done modifying the element */ |
1498 recycle = PyList_New(slicelen); | 1395 recycle = PyList_New(slicelen); |
Antoine Pitrou
2010/02/10 13:14:37
This lacks an error check.
| |
1396 if (!recycle) { | |
1397 if (seq) { | |
1398 Py_DECREF(seq); | |
1399 } | |
1400 return -1; | |
1401 } | |
1499 for (cur = start, i = 0; i < slicelen; | 1402 for (cur = start, i = 0; i < slicelen; |
1500 cur += step, i++) | 1403 cur += step, i++) |
1501 PyList_SET_ITEM(recycle, i, self->extra->children[cur]); | 1404 PyList_SET_ITEM(recycle, i, self->extra->children[cur]); |
1502 } | 1405 } |
1503 | 1406 |
1504 if (newlen < slicelen) { | 1407 if (newlen < slicelen) { |
1505 /* delete slice */ | 1408 /* delete slice */ |
1506 for (i = stop; i < self->extra->length; i++) | 1409 for (i = stop; i < self->extra->length; i++) |
1507 self->extra->children[i + newlen - slicelen] = self->extra->chil dren[i]; | 1410 self->extra->children[i + newlen - slicelen] = self->extra->chil dren[i]; |
1508 } else if (newlen > slicelen) { | 1411 } else if (newlen > slicelen) { |
1509 /* insert slice */ | 1412 /* insert slice */ |
1510 if (element_resize(self, newlen - slicelen) < 0) { | |
1511 if (seq) | |
1512 Py_DECREF(seq); | |
Antoine Pitrou
2010/02/10 13:14:37
There's a refleak with `recycle` but we can't decr
| |
1513 return -1; | |
1514 } | |
1515 for (i = self->extra->length-1; i >= stop; i--) | 1413 for (i = self->extra->length-1; i >= stop; i--) |
1516 self->extra->children[i + newlen - slicelen] = self->extra->chil dren[i]; | 1414 self->extra->children[i + newlen - slicelen] = self->extra->chil dren[i]; |
1517 } | 1415 } |
1518 | 1416 |
1519 /* replace the slice */ | 1417 /* replace the slice */ |
1520 for (cur = start, i = 0; i < newlen; | 1418 for (cur = start, i = 0; i < newlen; |
1521 cur += step, i++) { | 1419 cur += step, i++) { |
1522 PyObject* element = PySequence_Fast_GET_ITEM(seq, i); | 1420 PyObject* element = PySequence_Fast_GET_ITEM(seq, i); |
1523 Py_INCREF(element); | 1421 Py_INCREF(element); |
1524 self->extra->children[cur] = element; | 1422 self->extra->children[cur] = element; |
1525 } | 1423 } |
1526 | 1424 |
1527 self->extra->length += newlen - slicelen; | 1425 self->extra->length += newlen - slicelen; |
1528 | 1426 |
1529 if (seq) | 1427 if (seq) { |
1530 Py_DECREF(seq); | 1428 Py_DECREF(seq); |
1429 } | |
1531 | 1430 |
1532 /* discard the recycle bin, and everything in it */ | 1431 /* discard the recycle bin, and everything in it */ |
1533 Py_XDECREF(recycle); | 1432 Py_XDECREF(recycle); |
1534 | 1433 |
1535 return 0; | 1434 return 0; |
1536 } | 1435 } |
1537 else { | 1436 else { |
1538 PyErr_SetString(PyExc_TypeError, | 1437 PyErr_SetString(PyExc_TypeError, |
1539 "element indices must be integers"); | 1438 "element indices must be integers"); |
1540 return -1; | 1439 return -1; |
(...skipping 11 matching lines...) Expand all Loading... | |
1552 {"findtext", (PyCFunction) element_findtext, METH_VARARGS}, | 1451 {"findtext", (PyCFunction) element_findtext, METH_VARARGS}, |
1553 {"findall", (PyCFunction) element_findall, METH_VARARGS}, | 1452 {"findall", (PyCFunction) element_findall, METH_VARARGS}, |
1554 | 1453 |
1555 {"append", (PyCFunction) element_append, METH_VARARGS}, | 1454 {"append", (PyCFunction) element_append, METH_VARARGS}, |
1556 {"extend", (PyCFunction) element_extend, METH_VARARGS}, | 1455 {"extend", (PyCFunction) element_extend, METH_VARARGS}, |
1557 {"insert", (PyCFunction) element_insert, METH_VARARGS}, | 1456 {"insert", (PyCFunction) element_insert, METH_VARARGS}, |
1558 {"remove", (PyCFunction) element_remove, METH_VARARGS}, | 1457 {"remove", (PyCFunction) element_remove, METH_VARARGS}, |
1559 | 1458 |
1560 {"iter", (PyCFunction) element_iter, METH_VARARGS}, | 1459 {"iter", (PyCFunction) element_iter, METH_VARARGS}, |
1561 {"itertext", (PyCFunction) element_itertext, METH_VARARGS}, | 1460 {"itertext", (PyCFunction) element_itertext, METH_VARARGS}, |
1461 {"iterfind", (PyCFunction) element_iterfind, METH_VARARGS}, | |
1562 | 1462 |
1563 {"getiterator", (PyCFunction) element_iter, METH_VARARGS}, | 1463 {"getiterator", (PyCFunction) element_iter, METH_VARARGS}, |
1564 {"getchildren", (PyCFunction) element_getchildren, METH_VARARGS}, | 1464 {"getchildren", (PyCFunction) element_getchildren, METH_VARARGS}, |
1565 | 1465 |
1566 {"items", (PyCFunction) element_items, METH_VARARGS}, | 1466 {"items", (PyCFunction) element_items, METH_VARARGS}, |
1567 {"keys", (PyCFunction) element_keys, METH_VARARGS}, | 1467 {"keys", (PyCFunction) element_keys, METH_VARARGS}, |
1568 | 1468 |
1569 {"makeelement", (PyCFunction) element_makeelement, METH_VARARGS}, | 1469 {"makeelement", (PyCFunction) element_makeelement, METH_VARARGS}, |
1570 | 1470 |
1571 {"__copy__", (PyCFunction) element_copy, METH_VARARGS}, | 1471 {"__copy__", (PyCFunction) element_copy, METH_VARARGS}, |
(...skipping 12 matching lines...) Expand all Loading... | |
1584 {"!__reduce__", (PyCFunction) element_reduce, METH_VARARGS}, | 1484 {"!__reduce__", (PyCFunction) element_reduce, METH_VARARGS}, |
1585 | 1485 |
1586 {NULL, NULL} | 1486 {NULL, NULL} |
1587 }; | 1487 }; |
1588 | 1488 |
1589 static PyObject*·· | 1489 static PyObject*·· |
1590 element_getattr(ElementObject* self, char* name) | 1490 element_getattr(ElementObject* self, char* name) |
1591 { | 1491 { |
1592 PyObject* res; | 1492 PyObject* res; |
1593 | 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 */ | |
1594 res = Py_FindMethod(element_methods, (PyObject*) self, name); | 1506 res = Py_FindMethod(element_methods, (PyObject*) self, name); |
1595 if (res) | 1507 if (res) |
1596 return res; | 1508 return res; |
1597 | 1509 |
1598 PyErr_Clear(); | 1510 PyErr_Clear(); |
1599 | 1511 |
1600 if (strcmp(name, "tag") == 0) | 1512 /* less common attributes */ |
1601 res = self->tag; | 1513 if (strcmp(name, "tail") == 0) { |
1602 else if (strcmp(name, "text") == 0) | |
1603 res = element_get_text(self); | |
1604 else if (strcmp(name, "tail") == 0) { | |
1605 res = element_get_tail(self); | 1514 res = element_get_tail(self); |
1606 } else if (strcmp(name, "attrib") == 0) { | 1515 } else if (strcmp(name, "attrib") == 0) { |
1607 if (!self->extra) | 1516 if (!self->extra) |
1608 element_new_extra(self, NULL); | 1517 element_new_extra(self, NULL); |
1609 res = element_get_attrib(self); | 1518 res = element_get_attrib(self); |
1610 } else { | 1519 } else { |
1611 PyErr_SetString(PyExc_AttributeError, name); | 1520 PyErr_SetString(PyExc_AttributeError, name); |
1612 return NULL; | 1521 return NULL; |
1613 } | 1522 } |
1614 | 1523 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1662 0, /* sq_repeat */ | 1571 0, /* sq_repeat */ |
1663 element_getitem, | 1572 element_getitem, |
1664 0, | 1573 0, |
1665 element_setitem, | 1574 element_setitem, |
1666 0, | 1575 0, |
1667 }; | 1576 }; |
1668 | 1577 |
1669 static PyMappingMethods element_as_mapping = { | 1578 static PyMappingMethods element_as_mapping = { |
1670 (lenfunc) element_length, | 1579 (lenfunc) element_length, |
1671 (binaryfunc) element_subscr, | 1580 (binaryfunc) element_subscr, |
1672 (objobjargproc) element_ass_subscr | 1581 (objobjargproc) element_ass_subscr, |
1673 }; | 1582 }; |
1674 | 1583 |
1675 statichere PyTypeObject Element_Type = { | 1584 statichere PyTypeObject Element_Type = { |
1676 PyObject_HEAD_INIT(NULL) | 1585 PyObject_HEAD_INIT(NULL) |
1677 0, "Element", sizeof(ElementObject), 0, | 1586 0, "Element", sizeof(ElementObject), 0, |
1678 /* methods */ | 1587 /* methods */ |
1679 (destructor)element_dealloc, /* tp_dealloc */ | 1588 (destructor)element_dealloc, /* tp_dealloc */ |
1680 0, /* tp_print */ | 1589 0, /* tp_print */ |
1681 (getattrfunc)element_getattr, /* tp_getattr */ | 1590 (getattrfunc)element_getattr, /* tp_getattr */ |
1682 (setattrfunc)element_setattr, /* tp_setattr */ | 1591 (setattrfunc)element_setattr, /* tp_setattr */ |
1683 0, /* tp_compare */ | 1592 0, /* tp_compare */ |
1684 (reprfunc)element_repr, /* tp_repr */ | 1593 (reprfunc)element_repr, /* tp_repr */ |
1685 0, /* tp_as_number */ | 1594 0, /* tp_as_number */ |
1686 &element_as_sequence, /* tp_as_sequence */ | 1595 &element_as_sequence, /* tp_as_sequence */ |
1687 &element_as_mapping, /* tp_as_mapping */ | 1596 &element_as_mapping, /* tp_as_mapping */ |
1688 }; | 1597 }; |
1689 | |
1690 /* -------------------------------------------------------------------- */ | |
1691 /* CAPI interface */ | |
1692 | |
1693 static int | |
1694 element_capi_assert(PyObject* elem) | |
1695 { | |
1696 if (Element_CheckExact(elem)) | |
1697 return 0; | |
1698 PyErr_Format( | |
1699 PyExc_TypeError, | |
1700 "expected cElementTree.Element, not \"%.200s\"", | |
1701 elem->ob_type->tp_name | |
1702 ); | |
1703 return -1; | |
1704 } | |
1705 | |
1706 static PyObject* | |
1707 element_capi_getitem(PyObject* self, int index) | |
1708 { | |
1709 ElementObject* elem = (ElementObject*) self; | |
1710 | |
1711 if (!elem->extra || index < 0 || index >= elem->extra->length) | |
1712 Py_RETURN_NONE; | |
1713 | |
1714 Py_INCREF(elem->extra->children[index]); | |
1715 return elem->extra->children[index]; | |
1716 } | |
1717 | |
1718 static int | |
1719 element_capi_snapshot(PyObject* self, struct cElementTree_Snapshot* snapshot, | |
1720 int mode) | |
1721 { | |
1722 ElementObject* elem = (ElementObject*) self; | |
1723 | |
1724 snapshot->tag = elem->tag; | |
1725 Py_INCREF(snapshot->tag); | |
1726 | |
1727 snapshot->text = element_get_text(elem); | |
1728 Py_INCREF(snapshot->text); | |
1729 | |
1730 snapshot->tail = element_get_tail(elem); | |
1731 Py_INCREF(snapshot->tail); | |
1732 | |
1733 if (elem->extra) | |
1734 snapshot->attrib = element_get_attrib(elem); | |
1735 else | |
1736 snapshot->attrib = Py_None; | |
1737 Py_INCREF(snapshot->attrib); | |
1738 | |
1739 if (!mode) | |
1740 return 0; | |
1741 | |
1742 if (elem->extra) { | |
1743 snapshot->children = element_getslice( | |
1744 (PyObject*) elem, 0, elem->extra->length | |
1745 ); | |
1746 /* FIXME: clean up if slice fails */ | |
1747 } else { | |
1748 snapshot->children = Py_None; | |
1749 Py_INCREF(snapshot->children); | |
1750 } | |
1751 ········ | |
1752 return 0; | |
1753 } | |
1754 | 1598 |
1755 /* ==================================================================== */ | 1599 /* ==================================================================== */ |
1756 /* the tree builder type */ | 1600 /* the tree builder type */ |
1757 | 1601 |
1758 typedef struct { | 1602 typedef struct { |
1759 PyObject_HEAD | 1603 PyObject_HEAD |
1760 | 1604 |
1761 PyObject* root; /* root node (first created node) */ | 1605 PyObject* root; /* root node (first created node) */ |
1762 | 1606 |
1763 ElementObject* this; /* current node */ | 1607 ElementObject* this; /* current node */ |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2021 } else | 1865 } else |
2022 PyErr_Clear(); /* FIXME: propagate error */ | 1866 PyErr_Clear(); /* FIXME: propagate error */ |
2023 } | 1867 } |
2024 | 1868 |
2025 Py_INCREF(self->last); | 1869 Py_INCREF(self->last); |
2026 return (PyObject*) self->last; | 1870 return (PyObject*) self->last; |
2027 } | 1871 } |
2028 | 1872 |
2029 LOCAL(void) | 1873 LOCAL(void) |
2030 treebuilder_handle_namespace(TreeBuilderObject* self, int start, | 1874 treebuilder_handle_namespace(TreeBuilderObject* self, int start, |
2031 const char* prefix, const char *uri) | 1875 PyObject *prefix, PyObject *uri) |
2032 { | 1876 { |
2033 PyObject* res; | 1877 PyObject* res; |
2034 PyObject* action; | 1878 PyObject* action; |
2035 PyObject* parcel; | 1879 PyObject* parcel; |
2036 | 1880 |
2037 if (!self->events) | 1881 if (!self->events) |
2038 return; | 1882 return; |
2039 | 1883 |
2040 if (start) { | 1884 if (start) { |
2041 if (!self->start_ns_event_obj) | 1885 if (!self->start_ns_event_obj) |
2042 return; | 1886 return; |
2043 action = self->start_ns_event_obj; | 1887 action = self->start_ns_event_obj; |
2044 /* FIXME: prefix and uri use utf-8 encoding! */ | 1888 parcel = Py_BuildValue("OO", prefix, uri); |
2045 parcel = Py_BuildValue("ss", (prefix) ? prefix : "", uri); | |
2046 if (!parcel) | 1889 if (!parcel) |
2047 return; | 1890 return; |
2048 Py_INCREF(action); | 1891 Py_INCREF(action); |
2049 } else { | 1892 } else { |
2050 if (!self->end_ns_event_obj) | 1893 if (!self->end_ns_event_obj) |
2051 return; | 1894 return; |
2052 action = self->end_ns_event_obj; | 1895 action = self->end_ns_event_obj; |
2053 Py_INCREF(action); | 1896 Py_INCREF(action); |
2054 parcel = Py_None; | 1897 parcel = Py_None; |
2055 Py_INCREF(parcel); | 1898 Py_INCREF(parcel); |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2311 char buffer[256]; | 2154 char buffer[256]; |
2312 | 2155 |
2313 sprintf(buffer, "%s: line %d, column %d", message, line, column); | 2156 sprintf(buffer, "%s: line %d, column %d", message, line, column); |
2314 | 2157 |
2315 error = PyObject_CallFunction(elementtree_parseerror_obj, "s", buffer); | 2158 error = PyObject_CallFunction(elementtree_parseerror_obj, "s", buffer); |
2316 if (!error) | 2159 if (!error) |
2317 return; | 2160 return; |
2318 | 2161 |
2319 /* add position attribute */ | 2162 /* add position attribute */ |
2320 position = Py_BuildValue("(ii)", line, column); | 2163 position = Py_BuildValue("(ii)", line, column); |
2321 if (!position) | 2164 if (!position) { |
2165 Py_DECREF(error); | |
2322 return; | 2166 return; |
2167 } | |
2323 if (PyObject_SetAttrString(error, "position", position) == -1) { | 2168 if (PyObject_SetAttrString(error, "position", position) == -1) { |
2169 Py_DECREF(error); | |
2324 Py_DECREF(position); | 2170 Py_DECREF(position); |
2325 return; | 2171 return; |
2326 } | 2172 } |
2327 Py_DECREF(position); | 2173 Py_DECREF(position); |
2328 | 2174 |
2329 PyErr_SetObject(elementtree_parseerror_obj, error); | 2175 PyErr_SetObject(elementtree_parseerror_obj, error); |
2176 Py_DECREF(error); | |
2330 } | 2177 } |
2331 | 2178 |
2332 /* -------------------------------------------------------------------- */ | 2179 /* -------------------------------------------------------------------- */ |
2333 /* handlers */ | 2180 /* handlers */ |
2334 | 2181 |
2335 static void | 2182 static void |
2336 expat_default_handler(XMLParserObject* self, const XML_Char* data_in, | 2183 expat_default_handler(XMLParserObject* self, const XML_Char* data_in, |
2337 int data_len) | 2184 int data_len) |
2338 { | 2185 { |
2339 PyObject* key; | 2186 PyObject* key; |
(...skipping 12 matching lines...) Expand all Loading... | |
2352 if (value) { | 2199 if (value) { |
2353 if (TreeBuilder_CheckExact(self->target)) | 2200 if (TreeBuilder_CheckExact(self->target)) |
2354 res = treebuilder_handle_data( | 2201 res = treebuilder_handle_data( |
2355 (TreeBuilderObject*) self->target, value | 2202 (TreeBuilderObject*) self->target, value |
2356 ); | 2203 ); |
2357 else if (self->handle_data) | 2204 else if (self->handle_data) |
2358 res = PyObject_CallFunction(self->handle_data, "O", value); | 2205 res = PyObject_CallFunction(self->handle_data, "O", value); |
2359 else | 2206 else |
2360 res = NULL; | 2207 res = NULL; |
2361 Py_XDECREF(res); | 2208 Py_XDECREF(res); |
2362 } else { | 2209 } else if (!PyErr_Occurred()) { |
2210 /* Report the first error, not the last */ | |
2363 char message[128]; | 2211 char message[128]; |
2364 sprintf(message, "undefined entity &%.100s;", PyString_AS_STRING(key)); | 2212 sprintf(message, "undefined entity &%.100s;", PyString_AS_STRING(key)); |
2365 expat_set_error( | 2213 expat_set_error( |
2366 message, | 2214 message, |
2367 EXPAT(GetErrorLineNumber)(self->parser), | 2215 EXPAT(GetErrorLineNumber)(self->parser), |
2368 EXPAT(GetErrorColumnNumber)(self->parser) | 2216 EXPAT(GetErrorColumnNumber)(self->parser) |
2369 ); | 2217 ); |
2370 } | 2218 } |
2371 | 2219 |
2372 Py_DECREF(key); | 2220 Py_DECREF(key); |
2373 } | 2221 } |
2374 | 2222 |
2375 static void | 2223 static void |
2376 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... | |
2479 } | 2327 } |
2480 } | 2328 } |
2481 | 2329 |
2482 Py_XDECREF(res); | 2330 Py_XDECREF(res); |
2483 } | 2331 } |
2484 | 2332 |
2485 static void | 2333 static void |
2486 expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix, | 2334 expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix, |
2487 const XML_Char *uri) | 2335 const XML_Char *uri) |
2488 { | 2336 { |
2337 PyObject* sprefix = NULL; | |
2338 PyObject* suri = NULL; | |
2339 | |
2340 suri = makestring(uri, strlen(uri)); | |
2341 if (!suri) | |
2342 return; | |
2343 | |
2344 if (prefix) | |
2345 sprefix = makestring(prefix, strlen(prefix)); | |
2346 else | |
2347 sprefix = PyString_FromStringAndSize("", 0); | |
2348 if (!sprefix) { | |
2349 Py_DECREF(suri); | |
2350 return; | |
2351 } | |
2352 | |
2489 treebuilder_handle_namespace( | 2353 treebuilder_handle_namespace( |
2490 (TreeBuilderObject*) self->target, 1, prefix, uri | 2354 (TreeBuilderObject*) self->target, 1, sprefix, suri |
2491 ); | 2355 ); |
2356 | |
2357 Py_DECREF(sprefix); | |
2358 Py_DECREF(suri); | |
2492 } | 2359 } |
2493 | 2360 |
2494 static void | 2361 static void |
2495 expat_end_ns_handler(XMLParserObject* self, const XML_Char* prefix_in) | 2362 expat_end_ns_handler(XMLParserObject* self, const XML_Char* prefix_in) |
2496 { | 2363 { |
2497 treebuilder_handle_namespace( | 2364 treebuilder_handle_namespace( |
2498 (TreeBuilderObject*) self->target, 0, NULL, NULL | 2365 (TreeBuilderObject*) self->target, 0, NULL, NULL |
2499 ); | 2366 ); |
2500 } | 2367 } |
2501 | 2368 |
(...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2991 #endif | 2858 #endif |
2992 {NULL, NULL} | 2859 {NULL, NULL} |
2993 }; | 2860 }; |
2994 | 2861 |
2995 DL_EXPORT(void) | 2862 DL_EXPORT(void) |
2996 init_elementtree(void) | 2863 init_elementtree(void) |
2997 { | 2864 { |
2998 PyObject* m; | 2865 PyObject* m; |
2999 PyObject* g; | 2866 PyObject* g; |
3000 char* bootstrap; | 2867 char* bootstrap; |
3001 static struct cElementTree_CAPI capi; | |
3002 PyObject* capi_object; | |
3003 | 2868 |
3004 /* Patch object type */ | 2869 /* Patch object type */ |
3005 Py_TYPE(&Element_Type) = Py_TYPE(&TreeBuilder_Type) = &PyType_Type; | 2870 Py_TYPE(&Element_Type) = Py_TYPE(&TreeBuilder_Type) = &PyType_Type; |
3006 #if defined(USE_EXPAT) | 2871 #if defined(USE_EXPAT) |
3007 Py_TYPE(&XMLParser_Type) = &PyType_Type; | 2872 Py_TYPE(&XMLParser_Type) = &PyType_Type; |
3008 #endif | 2873 #endif |
3009 | 2874 |
3010 m = Py_InitModule("_elementtree", _functions); | 2875 m = Py_InitModule("_elementtree", _functions); |
3011 if (!m) | 2876 if (!m) |
3012 return; | 2877 return; |
3013 | 2878 |
3014 /* python glue code */ | 2879 /* python glue code */ |
3015 | 2880 |
3016 g = PyDict_New(); | 2881 g = PyDict_New(); |
3017 if (!g) | 2882 if (!g) |
3018 return; | 2883 return; |
3019 | 2884 |
3020 PyDict_SetItemString(g, "__builtins__", PyEval_GetBuiltins()); | 2885 PyDict_SetItemString(g, "__builtins__", PyEval_GetBuiltins()); |
3021 | 2886 |
3022 bootstrap = ( | 2887 bootstrap = ( |
3023 | |
3024 #if (PY_VERSION_HEX >= 0x02020000 && PY_VERSION_HEX < 0x02030000) | |
3025 "from __future__ import generators\n" /* enable yield under 2.2 */ | |
3026 #endif | |
3027 | 2888 |
3028 "from copy import copy, deepcopy\n" | 2889 "from copy import copy, deepcopy\n" |
3029 | 2890 |
3030 "try:\n" | 2891 "try:\n" |
3031 " from xml.etree import ElementTree\n" | 2892 " from xml.etree import ElementTree\n" |
3032 "except ImportError:\n" | 2893 "except ImportError:\n" |
3033 " import ElementTree\n" | 2894 " import ElementTree\n" |
3034 "ET = ElementTree\n" | 2895 "ET = ElementTree\n" |
3035 "del ElementTree\n" | 2896 "del ElementTree\n" |
3036 | 2897 |
(...skipping 27 matching lines...) Expand all Loading... | |
3064 " self._root = parser.close()\n" | 2925 " self._root = parser.close()\n" |
3065 " else:\n"· | 2926 " else:\n"· |
3066 " parser = cElementTree.XMLParser()\n" | 2927 " parser = cElementTree.XMLParser()\n" |
3067 " self._root = parser._parse(source)\n" | 2928 " self._root = parser._parse(source)\n" |
3068 " return self._root\n" | 2929 " return self._root\n" |
3069 "cElementTree.ElementTree = ElementTree\n" | 2930 "cElementTree.ElementTree = ElementTree\n" |
3070 | 2931 |
3071 "def iter(node, tag=None):\n" /* helper */ | 2932 "def iter(node, tag=None):\n" /* helper */ |
3072 " if tag == '*':\n" | 2933 " if tag == '*':\n" |
3073 " tag = None\n" | 2934 " tag = None\n" |
3074 #if (PY_VERSION_HEX < 0x02020000) | |
3075 " nodes = []\n" /* 2.1 doesn't have yield */ | |
3076 " if tag is None or node.tag == tag:\n" | |
3077 " nodes.append(node)\n" | |
3078 " for node in node:\n" | |
3079 " nodes.extend(iter(node, tag))\n" | |
3080 " return nodes\n" | |
3081 #else | |
3082 " if tag is None or node.tag == tag:\n" | 2935 " if tag is None or node.tag == tag:\n" |
3083 " yield node\n" | 2936 " yield node\n" |
3084 " for node in node:\n" | 2937 " for node in node:\n" |
3085 " for node in iter(node, tag):\n" | 2938 " for node in iter(node, tag):\n" |
3086 " yield node\n" | 2939 " yield node\n" |
3087 #endif | |
3088 | 2940 |
3089 "def itertext(node):\n" /* helper */ | 2941 "def itertext(node):\n" /* helper */ |
3090 " if node.text:\n" | 2942 " if node.text:\n" |
3091 " yield node.text\n" | 2943 " yield node.text\n" |
3092 " for e in node:\n" | 2944 " for e in node:\n" |
3093 " for s in e.itertext():\n" | 2945 " for s in e.itertext():\n" |
3094 " yield s\n" | 2946 " yield s\n" |
3095 " if e.tail:\n" | 2947 " if e.tail:\n" |
3096 " yield e.tail\n" | 2948 " yield e.tail\n" |
3097 | 2949 |
3098 "def parse(source, parser=None):\n" /* public */ | 2950 "def parse(source, parser=None):\n" /* public */ |
3099 " tree = ElementTree()\n" | 2951 " tree = ElementTree()\n" |
3100 " tree.parse(source, parser)\n" | 2952 " tree.parse(source, parser)\n" |
3101 " return tree\n" | 2953 " return tree\n" |
3102 "cElementTree.parse = parse\n" | 2954 "cElementTree.parse = parse\n" |
3103 | 2955 |
3104 #if (PY_VERSION_HEX < 0x02020000) | |
3105 "if hasattr(ET, 'iterparse'):\n" | |
3106 " cElementTree.iterparse = ET.iterparse\n" /* delegate on 2.1 */ | |
3107 #else | |
3108 "class iterparse(object):\n" | 2956 "class iterparse(object):\n" |
3109 " root = None\n" | 2957 " root = None\n" |
3110 " def __init__(self, file, events=None):\n" | 2958 " def __init__(self, file, events=None):\n" |
3111 " if not hasattr(file, 'read'):\n" | 2959 " if not hasattr(file, 'read'):\n" |
3112 " file = open(file, 'rb')\n" | 2960 " file = open(file, 'rb')\n" |
3113 " self._file = file\n" | 2961 " self._file = file\n" |
3114 " self._events = []\n" | 2962 " self._events = []\n" |
3115 " self._index = 0\n" | 2963 " self._index = 0\n" |
3116 " self.root = self._root = None\n" | 2964 " self.root = self._root = None\n" |
3117 " b = cElementTree.TreeBuilder()\n" | 2965 " b = cElementTree.TreeBuilder()\n" |
(...skipping 15 matching lines...) Expand all Loading... | |
3133 " self._parser.feed(data)\n" | 2981 " self._parser.feed(data)\n" |
3134 " else:\n" | 2982 " else:\n" |
3135 " self._root = self._parser.close()\n" | 2983 " self._root = self._parser.close()\n" |
3136 " self._parser = None\n" | 2984 " self._parser = None\n" |
3137 " else:\n" | 2985 " else:\n" |
3138 " self._index = self._index + 1\n" | 2986 " self._index = self._index + 1\n" |
3139 " return item\n" | 2987 " return item\n" |
3140 " def __iter__(self):\n" | 2988 " def __iter__(self):\n" |
3141 " return self\n" | 2989 " return self\n" |
3142 "cElementTree.iterparse = iterparse\n" | 2990 "cElementTree.iterparse = iterparse\n" |
3143 #endif | |
3144 | 2991 |
3145 "class PIProxy:\n" | 2992 "class PIProxy:\n" |
3146 " def __call__(self, target, text=None):\n" | 2993 " def __call__(self, target, text=None):\n" |
3147 " element = cElementTree.Element(ET.PI)\n" | 2994 " element = cElementTree.Element(ET.PI)\n" |
3148 " element.text = target\n" | 2995 " element.text = target\n" |
3149 " if text:\n" | 2996 " if text:\n" |
3150 " element.text = element.text + ' ' + text\n" | 2997 " element.text = element.text + ' ' + text\n" |
3151 " return element\n" | 2998 " return element\n" |
3152 " def __cmp__(self, other):\n" | 2999 " def __cmp__(self, other):\n" |
3153 " return cmp(ET.PI, other)\n" | 3000 " return cmp(ET.PI, other)\n" |
3154 "cElementTree.PI = cElementTree.ProcessingInstruction = PIProxy()\n" | 3001 "cElementTree.PI = cElementTree.ProcessingInstruction = PIProxy()\n" |
3155 | 3002 |
3156 "def XML(text):\n" /* public */ | 3003 "def XML(text):\n" /* public */ |
3157 " parser = cElementTree.XMLParser()\n" | 3004 " parser = cElementTree.XMLParser()\n" |
3158 " parser.feed(text)\n" | 3005 " parser.feed(text)\n" |
3159 " return parser.close()\n" | 3006 " return parser.close()\n" |
3160 "cElementTree.XML = cElementTree.fromstring = XML\n" | 3007 "cElementTree.XML = cElementTree.fromstring = XML\n" |
3161 | 3008 |
3162 "def XMLID(text):\n" /* public */ | 3009 "def XMLID(text):\n" /* public */ |
3163 " tree = XML(text)\n" | 3010 " tree = XML(text)\n" |
3164 " ids = {}\n" | 3011 " ids = {}\n" |
3165 " for elem in tree.getiterator():\n" | 3012 " for elem in tree.iter():\n" |
3166 " id = elem.get('id')\n" | 3013 " id = elem.get('id')\n" |
3167 " if id:\n" | 3014 " if id:\n" |
3168 " ids[id] = elem\n" | 3015 " ids[id] = elem\n" |
3169 " return tree, ids\n" | 3016 " return tree, ids\n" |
3170 "cElementTree.XMLID = XMLID\n" | 3017 "cElementTree.XMLID = XMLID\n" |
3171 | 3018 |
3172 "try:\n" | 3019 "try:\n" |
3173 " register_namespace = ET.register_namespace\n" | 3020 " register_namespace = ET.register_namespace\n" |
3174 "except AttributeError:\n" | 3021 "except AttributeError:\n" |
3175 " def register_namespace(prefix, uri):\n" | 3022 " def register_namespace(prefix, uri):\n" |
3176 " ET._namespace_map[uri] = prefix\n" | 3023 " ET._namespace_map[uri] = prefix\n" |
3177 "cElementTree.register_namespace = register_namespace\n" | 3024 "cElementTree.register_namespace = register_namespace\n" |
3178 | 3025 |
3179 "cElementTree.dump = ET.dump\n" | 3026 "cElementTree.dump = ET.dump\n" |
3180 "cElementTree.ElementPath = ElementPath = ET.ElementPath\n" | 3027 "cElementTree.ElementPath = ElementPath = ET.ElementPath\n" |
3181 "cElementTree.iselement = ET.iselement\n" | 3028 "cElementTree.iselement = ET.iselement\n" |
3182 "cElementTree.QName = ET.QName\n" | 3029 "cElementTree.QName = ET.QName\n" |
3183 "cElementTree.tostring = ET.tostring\n" | 3030 "cElementTree.tostring = ET.tostring\n" |
3031 "cElementTree.fromstringlist = ET.fromstringlist\n" | |
3032 "cElementTree.tostringlist = ET.tostringlist\n" | |
3184 "cElementTree.VERSION = '" VERSION "'\n" | 3033 "cElementTree.VERSION = '" VERSION "'\n" |
3185 "cElementTree.__version__ = '" VERSION "'\n" | 3034 "cElementTree.__version__ = '" VERSION "'\n" |
3186 | 3035 |
3187 ); | 3036 ); |
3188 | 3037 |
3189 if (!PyRun_String(bootstrap, Py_file_input, g, NULL)) | 3038 if (!PyRun_String(bootstrap, Py_file_input, g, NULL)) |
3190 return; | 3039 return; |
3191 | 3040 |
3192 elementpath_obj = PyDict_GetItemString(g, "ElementPath"); | 3041 elementpath_obj = PyDict_GetItemString(g, "ElementPath"); |
3193 | 3042 |
(...skipping 25 matching lines...) Expand all Loading... | |
3219 expat_capi->MICRO_VERSION != XML_MICRO_VERSION) | 3068 expat_capi->MICRO_VERSION != XML_MICRO_VERSION) |
3220 expat_capi = NULL; | 3069 expat_capi = NULL; |
3221 } | 3070 } |
3222 #endif | 3071 #endif |
3223 | 3072 |
3224 elementtree_parseerror_obj = PyErr_NewException( | 3073 elementtree_parseerror_obj = PyErr_NewException( |
3225 "cElementTree.ParseError", PyExc_SyntaxError, NULL | 3074 "cElementTree.ParseError", PyExc_SyntaxError, NULL |
3226 ); | 3075 ); |
3227 Py_INCREF(elementtree_parseerror_obj); | 3076 Py_INCREF(elementtree_parseerror_obj); |
3228 PyModule_AddObject(m, "ParseError", elementtree_parseerror_obj); | 3077 PyModule_AddObject(m, "ParseError", elementtree_parseerror_obj); |
3229 | 3078 } |
3230 capi.size = sizeof(capi); | |
3231 capi.magic = cElementTree_CAPI_MAGIC; | |
3232 capi.version = cElementTree_CAPI_VERSION; | |
3233 capi.type = (PyObject*) &Element_Type; | |
3234 capi.assert = element_capi_assert; | |
3235 capi.snapshot = element_capi_snapshot; | |
3236 capi.getitem = element_capi_getitem; | |
3237 | |
3238 /* export as cobject */ | |
3239 capi_object = PyCObject_FromVoidPtr(&capi, NULL); | |
3240 if (capi_object) | |
3241 PyModule_AddObject(m, "CAPI", capi_object); | |
3242 } | |
LEFT | RIGHT |