Left: | ||
Right: |
OLD | NEW |
---|---|
1 /* | 1 /* |
2 * ElementTree | 2 * ElementTree |
3 * $Id: _elementtree.c 2657 2006-03-12 20:50:32Z fredrik $ | 3 * $Id: _elementtree.c 3469 2009-01-10 14:30:13Z 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 * 2001-06-05 fl backported to unix; fixed bogus free in clear | |
11 * 2001-07-10 fl added findall helper | |
12 * 2003-02-27 fl elementtree edition (alpha) | 10 * 2003-02-27 fl elementtree edition (alpha) |
13 * 2004-06-03 fl updates for elementtree 1.2 | 11 * 2004-06-03 fl updates for elementtree 1.2 |
14 * 2005-01-05 fl added universal name cache, Element/SubElement factories | 12 * 2005-01-05 fl added universal name cache, Element/SubElement factories |
15 * 2005-01-06 fl moved python helpers into C module; removed 1.5.2 support | 13 * 2005-01-06 fl moved python helpers into C module; removed 1.5.2 support |
16 * 2005-01-07 fl added 2.1 support; work around broken __copy__ in 2.3 | 14 * 2005-01-07 fl added 2.1 support; work around broken __copy__ in 2.3 |
17 * 2005-01-08 fl added makeelement method; fixed path support | 15 * 2005-01-08 fl added makeelement method; fixed path support |
18 * 2005-01-10 fl optimized memory usage | 16 * 2005-01-10 fl optimized memory usage |
19 * 2005-01-11 fl first public release (cElementTree 0.8) | 17 * 2005-01-11 fl first public release (cElementTree 0.8) |
20 * 2005-01-12 fl split element object into base and extras | 18 * 2005-01-12 fl split element object into base and extras |
21 * 2005-01-13 fl use tagged pointers for tail/text (cElementTree 0.9) | 19 * 2005-01-13 fl use tagged pointers for tail/text (cElementTree 0.9) |
22 * 2005-01-17 fl added treebuilder close method | 20 * 2005-01-17 fl added treebuilder close method |
23 * 2005-01-17 fl fixed crash in getchildren | 21 * 2005-01-17 fl fixed crash in getchildren |
24 * 2005-01-18 fl removed observer api, added iterparse (cElementTree 0.9.3) | 22 * 2005-01-18 fl removed observer api, added iterparse (cElementTree 0.9.3) |
25 * 2005-01-23 fl revised iterparse api; added namespace event support (0.9.8) | 23 * 2005-01-23 fl revised iterparse api; added namespace event support (0.9.8) |
26 * 2005-01-26 fl added VERSION module property (cElementTree 1.0) | 24 * 2005-01-26 fl added VERSION module property (cElementTree 1.0) |
27 * 2005-01-28 fl added remove method (1.0.1) | 25 * 2005-01-28 fl added remove method (1.0.1) |
28 * 2005-03-01 fl added iselement function; fixed makeelement aliasing (1.0.2) | 26 * 2005-03-01 fl added iselement function; fixed makeelement aliasing (1.0.2) |
29 * 2005-03-13 fl export Comment and ProcessingInstruction/PI helpers | 27 * 2005-03-13 fl export Comment and ProcessingInstruction/PI helpers |
30 * 2005-03-26 fl added Comment and PI support to XMLParser | 28 * 2005-03-26 fl added Comment and PI support to XMLParser |
31 * 2005-03-27 fl event optimizations; complain about bogus events | 29 * 2005-03-27 fl event optimizations; complain about bogus events |
32 * 2005-08-08 fl fixed read error handling in parse | 30 * 2005-08-08 fl fixed read error handling in parse |
33 * 2005-08-11 fl added runtime test for copy workaround (1.0.3) | 31 * 2005-08-11 fl added runtime test for copy workaround (1.0.3) |
34 * 2005-12-13 fl added expat_capi support (for xml.etree) (1.0.4) | 32 * 2005-12-13 fl added expat_capi support (for xml.etree) (1.0.4) |
35 * 2005-12-16 fl added support for non-standard encodings | 33 * 2005-12-16 fl added support for non-standard encodings |
36 * 2006-03-08 fl fixed a couple of potential null-refs and leaks | 34 * 2006-03-08 fl fixed a couple of potential null-refs and leaks |
37 * 2006-03-12 fl merge in 2.5 ssize_t changes | 35 * 2006-03-12 fl merge in 2.5 ssize_t changes |
36 * 2007-08-25 fl call custom builder's close method from XMLParser | |
37 * 2007-08-31 fl added iter, extend from ET 1.3 | |
38 * 2007-09-01 fl fixed ParseError exception, setslice source type, etc | |
39 * 2007-09-03 fl fixed handling of negative insert indexes | |
40 * 2007-09-04 fl added itertext from ET 1.3 | |
41 * 2007-09-06 fl added position attribute to ParseError exception | |
42 * 2008-06-06 fl delay error reporting in iterparse (from Hrvoje Niksic) | |
43 * 2009-01-10 fl added experimental CAPI interface | |
38 * | 44 * |
39 * Copyright (c) 1999-2006 by Secret Labs AB. All rights reserved. | 45 * Copyright (c) 1999-2009 by Secret Labs AB. All rights reserved. |
40 * Copyright (c) 1999-2006 by Fredrik Lundh. | 46 * Copyright (c) 1999-2009 by Fredrik Lundh. |
41 * | 47 * |
42 * info@pythonware.com | 48 * info@pythonware.com |
43 * http://www.pythonware.com | 49 * http://www.pythonware.com |
44 */ | 50 */ |
45 | 51 |
46 /* Licensed to PSF under a Contributor Agreement. */ | 52 /* Licensed to PSF under a Contributor Agreement. */ |
47 /* See http://www.python.org/2.4/license for licensing details. */ | 53 /* See http://www.python.org/psf/license for licensing details. */ |
48 | 54 |
49 #include "Python.h" | 55 #include "Python.h" |
50 | 56 |
51 #define VERSION "1.0.6" | 57 #include "celementtree.h" /* CAPI stuff */ |
58 | |
59 #define VERSION "1.0.6a2" | |
52 | 60 |
53 /* -------------------------------------------------------------------- */ | 61 /* -------------------------------------------------------------------- */ |
54 /* configuration */ | 62 /* configuration */ |
55 | 63 |
56 /* Leave defined to include the expat-based XMLParser type */ | 64 /* Leave defined to include the expat-based XMLParser type */ |
57 #define USE_EXPAT | 65 #define USE_EXPAT |
58 | 66 |
59 /* Define to to all expat calls via pyexpat's embedded expat library */ | 67 /* Define to do all expat calls via pyexpat's embedded expat library */ |
60 /* #define USE_PYEXPAT_CAPI */ | 68 /* #define USE_PYEXPAT_CAPI */ |
61 | 69 |
62 /* An element can hold this many children without extra memory | 70 /* An element can hold this many children without extra memory |
63 allocations. */ | 71 allocations. */ |
64 #define STATIC_CHILDREN 4 | 72 #define STATIC_CHILDREN 4 |
65 | 73 |
66 /* For best performance, chose a value so that 80-90% of all nodes | 74 /* For best performance, chose a value so that 80-90% of all nodes |
67 have no more than the given number of children. Set this to zero | 75 have no more than the given number of children. Set this to zero |
68 to minimize the size of the element structure itself (this only | 76 to minimize the size of the element structure itself (this only |
69 helps if you have lots of leaf nodes with attributes). */ | 77 helps if you have lots of leaf nodes with attributes). */ |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
116 | 124 |
117 /* macros used to store 'join' flags in string object pointers. note | 125 /* macros used to store 'join' flags in string object pointers. note |
118 that all use of text and tail as object pointers must be wrapped in | 126 that all use of text and tail as object pointers must be wrapped in |
119 JOIN_OBJ. see comments in the ElementObject definition for more | 127 JOIN_OBJ. see comments in the ElementObject definition for more |
120 info. */ | 128 info. */ |
121 #define JOIN_GET(p) ((Py_uintptr_t) (p) & 1) | 129 #define JOIN_GET(p) ((Py_uintptr_t) (p) & 1) |
122 #define JOIN_SET(p, flag) ((void*) ((Py_uintptr_t) (JOIN_OBJ(p)) | (flag))) | 130 #define JOIN_SET(p, flag) ((void*) ((Py_uintptr_t) (JOIN_OBJ(p)) | (flag))) |
123 #define JOIN_OBJ(p) ((PyObject*) ((Py_uintptr_t) (p) & ~1)) | 131 #define JOIN_OBJ(p) ((PyObject*) ((Py_uintptr_t) (p) & ~1)) |
124 | 132 |
125 /* glue functions (see the init function for details) */ | 133 /* glue functions (see the init function for details) */ |
134 static PyObject* elementtree_parseerror_obj; | |
126 static PyObject* elementtree_copyelement_obj; | 135 static PyObject* elementtree_copyelement_obj; |
127 static PyObject* elementtree_deepcopy_obj; | 136 static PyObject* elementtree_deepcopy_obj; |
128 static PyObject* elementtree_getiterator_obj; | 137 static PyObject* elementtree_iter_obj; |
138 static PyObject* elementtree_itertext_obj; | |
129 static PyObject* elementpath_obj; | 139 static PyObject* elementpath_obj; |
130 | 140 |
131 /* helpers */ | 141 /* helpers */ |
132 | 142 |
133 LOCAL(PyObject*) | 143 LOCAL(PyObject*) |
134 deepcopy(PyObject* object, PyObject* memo) | 144 deepcopy(PyObject* object, PyObject* memo) |
135 { | 145 { |
136 /* do a deep copy of the given object */ | 146 /* do a deep copy of the given object */ |
137 | 147 |
138 PyObject* args; | 148 PyObject* args; |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
323 if (PyDict_CheckExact(attrib) && !PyDict_Size(attrib)) | 333 if (PyDict_CheckExact(attrib) && !PyDict_Size(attrib)) |
324 attrib = Py_None; | 334 attrib = Py_None; |
325 | 335 |
326 self->extra = NULL; | 336 self->extra = NULL; |
327 | 337 |
328 if (attrib != Py_None) { | 338 if (attrib != Py_None) { |
329 | 339 |
330 if (element_new_extra(self, attrib) < 0) { | 340 if (element_new_extra(self, attrib) < 0) { |
331 PyObject_Del(self); | 341 PyObject_Del(self); |
332 return NULL; | 342 return NULL; |
333 » } | 343 } |
334 | 344 |
335 self->extra->length = 0; | 345 self->extra->length = 0; |
336 self->extra->allocated = STATIC_CHILDREN; | 346 self->extra->allocated = STATIC_CHILDREN; |
337 self->extra->children = self->extra->_children; | 347 self->extra->children = self->extra->_children; |
338 | 348 |
339 } | 349 } |
340 | 350 |
341 Py_INCREF(tag); | 351 Py_INCREF(tag); |
342 self->tag = tag; | 352 self->tag = tag; |
343 | 353 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
412 return -1; | 422 return -1; |
413 | 423 |
414 Py_INCREF(element); | 424 Py_INCREF(element); |
415 self->extra->children[self->extra->length] = element; | 425 self->extra->children[self->extra->length] = element; |
416 | 426 |
417 self->extra->length++; | 427 self->extra->length++; |
418 | 428 |
419 return 0; | 429 return 0; |
420 } | 430 } |
421 | 431 |
432 static PyObject* | |
433 element_get_type(void) | |
434 { | |
435 /* return borrowed reference to type object */ | |
436 | |
437 return (PyObject*) &Element_Type; | |
438 } | |
439 | |
422 LOCAL(PyObject*) | 440 LOCAL(PyObject*) |
423 element_get_attrib(ElementObject* self) | 441 element_get_attrib(ElementObject* self) |
424 { | 442 { |
425 /* return borrowed reference to attrib dictionary */ | 443 /* return borrowed reference to attrib dictionary */ |
426 /* note: this function assumes that the extra section exists */ | 444 /* note: this function assumes that the extra section exists */ |
427 | 445 |
428 PyObject* res = self->extra->attrib; | 446 PyObject* res = self->extra->attrib; |
429 | 447 |
430 if (res == Py_None) { | 448 if (res == Py_None) { |
449 Py_DECREF(res); | |
431 /* create missing dictionary */ | 450 /* create missing dictionary */ |
432 res = PyDict_New(); | 451 res = PyDict_New(); |
433 if (!res) | 452 if (!res) |
434 return NULL; | 453 return NULL; |
435 self->extra->attrib = res; | 454 self->extra->attrib = res; |
436 } | 455 } |
437 | 456 |
438 return res; | 457 return res; |
439 } | 458 } |
440 | 459 |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
702 } | 721 } |
703 element->extra->children[i] = child; | 722 element->extra->children[i] = child; |
704 } | 723 } |
705 | 724 |
706 element->extra->length = self->extra->length; | 725 element->extra->length = self->extra->length; |
707 ········ | 726 ········ |
708 } | 727 } |
709 | 728 |
710 /* add object to memo dictionary (so deepcopy won't visit it again) */ | 729 /* add object to memo dictionary (so deepcopy won't visit it again) */ |
711 id = PyInt_FromLong((Py_uintptr_t) self); | 730 id = PyInt_FromLong((Py_uintptr_t) self); |
731 if (!id) | |
732 goto error; | |
712 | 733 |
713 i = PyDict_SetItem(memo, id, (PyObject*) element); | 734 i = PyDict_SetItem(memo, id, (PyObject*) element); |
714 | 735 |
715 Py_DECREF(id); | 736 Py_DECREF(id); |
716 | 737 |
717 if (i < 0) | 738 if (i < 0) |
718 goto error; | 739 goto error; |
719 | 740 |
720 return (PyObject*) element; | 741 return (PyObject*) element; |
721 | 742 |
722 error: | 743 error: |
723 Py_DECREF(element); | 744 Py_DECREF(element); |
724 return NULL; | 745 return NULL; |
725 } | 746 } |
726 | 747 |
727 LOCAL(int) | 748 LOCAL(int) |
728 checkpath(PyObject* tag) | 749 checkpath(PyObject* tag) |
729 { | 750 { |
730 Py_ssize_t i; | 751 Py_ssize_t i; |
731 int check = 1; | 752 int check = 1; |
732 | 753 |
733 /* check if a tag contains an xpath character */ | 754 /* check if a tag contains an xpath character */ |
734 | 755 |
735 #define PATHCHAR(ch) (ch == '/' || ch == '*' || ch == '[' || ch == '@') | 756 #define PATHCHAR(ch) \ |
757 (ch == '/' || ch == '*' || ch == '[' || ch == '@' || ch == '.') | |
736 | 758 |
737 #if defined(Py_USING_UNICODE) | 759 #if defined(Py_USING_UNICODE) |
738 if (PyUnicode_Check(tag)) { | 760 if (PyUnicode_Check(tag)) { |
739 Py_UNICODE *p = PyUnicode_AS_UNICODE(tag); | 761 Py_UNICODE *p = PyUnicode_AS_UNICODE(tag); |
740 for (i = 0; i < PyUnicode_GET_SIZE(tag); i++) { | 762 for (i = 0; i < PyUnicode_GET_SIZE(tag); i++) { |
741 if (p[i] == '{') | 763 if (p[i] == '{') |
742 check = 0; | 764 check = 0; |
743 else if (p[i] == '}') | 765 else if (p[i] == '}') |
744 check = 1; | 766 check = 1; |
745 else if (check && PATHCHAR(p[i])) | 767 else if (check && PATHCHAR(p[i])) |
(...skipping 12 matching lines...) Expand all Loading... | |
758 else if (check && PATHCHAR(p[i])) | 780 else if (check && PATHCHAR(p[i])) |
759 return 1; | 781 return 1; |
760 } | 782 } |
761 return 0; | 783 return 0; |
762 } | 784 } |
763 | 785 |
764 return 1; /* unknown type; might be path expression */ | 786 return 1; /* unknown type; might be path expression */ |
765 } | 787 } |
766 | 788 |
767 static PyObject* | 789 static PyObject* |
790 element_extend(ElementObject* self, PyObject* args) | |
791 { | |
792 PyObject* seq; | |
793 Py_ssize_t i, seqlen = 0; | |
794 | |
795 PyObject* seq_in; | |
796 if (!PyArg_ParseTuple(args, "O:extend", &seq_in)) | |
797 return NULL; | |
798 | |
799 seq = PySequence_Fast(seq_in, ""); | |
flox
2010/02/12 14:07:23
Don't miss this one, next time...
| |
800 if (!seq) | |
801 return NULL; | |
802 | |
803 seqlen = PySequence_Size(seq); | |
804 for (i = 0; i < seqlen; i++) { | |
805 PyObject* element = PySequence_Fast_GET_ITEM(seq, i); | |
806 if (element_add_subelement(self, element) < 0) { | |
807 Py_DECREF(seq); | |
808 return NULL; | |
809 } | |
810 } | |
811 | |
812 Py_DECREF(seq); | |
813 | |
814 Py_RETURN_NONE; | |
815 } | |
816 | |
817 static PyObject* | |
768 element_find(ElementObject* self, PyObject* args) | 818 element_find(ElementObject* self, PyObject* args) |
769 { | 819 { |
770 int i; | 820 int i; |
771 | 821 |
772 PyObject* tag; | 822 PyObject* tag; |
773 if (!PyArg_ParseTuple(args, "O:find", &tag)) | 823 if (!PyArg_ParseTuple(args, "O:find", &tag)) |
774 return NULL; | 824 return NULL; |
775 | 825 |
776 if (checkpath(tag)) | 826 if (checkpath(tag)) |
777 return PyObject_CallMethod( | 827 return PyObject_CallMethod( |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
825 } | 875 } |
826 | 876 |
827 Py_INCREF(default_value); | 877 Py_INCREF(default_value); |
828 return default_value; | 878 return default_value; |
829 } | 879 } |
830 | 880 |
831 static PyObject* | 881 static PyObject* |
832 element_findall(ElementObject* self, PyObject* args) | 882 element_findall(ElementObject* self, PyObject* args) |
833 { | 883 { |
834 int i; | 884 int i; |
835 PyObject* out; | 885 PyObject *out, *it; |
836 | 886 |
837 PyObject* tag; | 887 PyObject* tag; |
838 if (!PyArg_ParseTuple(args, "O:findall", &tag)) | 888 if (!PyArg_ParseTuple(args, "O:findall", &tag)) |
839 return NULL; | 889 return NULL; |
840 | 890 |
841 if (checkpath(tag)) | 891 if (checkpath(tag)) |
842 return PyObject_CallMethod( | 892 return PyObject_CallMethod( |
843 elementpath_obj, "findall", "OO", self, tag | 893 elementpath_obj, "findall", "OO", self, tag |
844 ); | 894 ); |
845 | 895 |
846 out = PyList_New(0); | 896 out = PyList_New(0); |
847 if (!out) | 897 if (!out) |
848 return NULL; | 898 return NULL; |
849 | 899 |
850 if (!self->extra) | 900 if (!self->extra) |
851 return out; | 901 return out; |
852 | 902 |
853 for (i = 0; i < self->extra->length; i++) { | 903 for (i = 0; i < self->extra->length; i++) { |
854 PyObject* item = self->extra->children[i]; | 904 PyObject* item = self->extra->children[i]; |
855 if (Element_CheckExact(item) && | 905 if (Element_CheckExact(item) && |
856 PyObject_Compare(((ElementObject*)item)->tag, tag) == 0) { | 906 PyObject_Compare(((ElementObject*)item)->tag, tag) == 0) { |
857 if (PyList_Append(out, item) < 0) { | 907 if (PyList_Append(out, item) < 0) { |
858 Py_DECREF(out); | 908 Py_DECREF(out); |
859 return NULL; | 909 return NULL; |
860 } | 910 } |
861 } | 911 } |
862 } | 912 } |
863 | 913 |
864 return out; | 914 it = PyObject_GetIter(out); |
915 Py_DECREF(out); | |
916 if (it == NULL) | |
917 return NULL; | |
Antoine Pitrou
2010/02/12 15:27:46
This conditional is quite useless, isn't it?
flox
2010/02/12 16:07:47
indeed, it is ...
| |
918 return it; | |
865 } | 919 } |
866 | 920 |
867 static PyObject* | 921 static PyObject* |
868 element_get(ElementObject* self, PyObject* args) | 922 element_get(ElementObject* self, PyObject* args) |
869 { | 923 { |
870 PyObject* value; | 924 PyObject* value; |
871 | 925 |
872 PyObject* key; | 926 PyObject* key; |
873 PyObject* default_value = Py_None; | 927 PyObject* default_value = Py_None; |
874 if (!PyArg_ParseTuple(args, "O|O:get", &key, &default_value)) | 928 if (!PyArg_ParseTuple(args, "O|O:get", &key, &default_value)) |
(...skipping 30 matching lines...) Expand all Loading... | |
905 for (i = 0; i < self->extra->length; i++) { | 959 for (i = 0; i < self->extra->length; i++) { |
906 PyObject* item = self->extra->children[i]; | 960 PyObject* item = self->extra->children[i]; |
907 Py_INCREF(item); | 961 Py_INCREF(item); |
908 PyList_SET_ITEM(list, i, item); | 962 PyList_SET_ITEM(list, i, item); |
909 } | 963 } |
910 | 964 |
911 return list; | 965 return list; |
912 } | 966 } |
913 | 967 |
914 static PyObject* | 968 static PyObject* |
915 element_getiterator(ElementObject* self, PyObject* args) | 969 element_iter(ElementObject* self, PyObject* args) |
916 { | 970 { |
917 PyObject* result; | 971 PyObject* result; |
918 ···· | 972 ···· |
919 PyObject* tag = Py_None; | 973 PyObject* tag = Py_None; |
920 if (!PyArg_ParseTuple(args, "|O:getiterator", &tag)) | 974 if (!PyArg_ParseTuple(args, "|O:iter", &tag)) |
921 return NULL; | 975 return NULL; |
922 | 976 |
923 if (!elementtree_getiterator_obj) { | 977 if (!elementtree_iter_obj) { |
924 PyErr_SetString( | 978 PyErr_SetString( |
925 PyExc_RuntimeError, | 979 PyExc_RuntimeError, |
926 "getiterator helper not found" | 980 "iter helper not found" |
927 ); | 981 ); |
928 return NULL; | 982 return NULL; |
929 } | 983 } |
930 | 984 |
931 args = PyTuple_New(2); | 985 args = PyTuple_New(2); |
932 if (!args) | 986 if (!args) |
933 return NULL; | 987 return NULL; |
934 | 988 |
935 Py_INCREF(self); PyTuple_SET_ITEM(args, 0, (PyObject*) self); | 989 Py_INCREF(self); PyTuple_SET_ITEM(args, 0, (PyObject*) self); |
936 Py_INCREF(tag); PyTuple_SET_ITEM(args, 1, (PyObject*) tag); | 990 Py_INCREF(tag); PyTuple_SET_ITEM(args, 1, (PyObject*) tag); |
937 | 991 |
938 result = PyObject_CallObject(elementtree_getiterator_obj, args); | 992 result = PyObject_CallObject(elementtree_iter_obj, args); |
939 | 993 |
940 Py_DECREF(args); | 994 Py_DECREF(args); |
941 | 995 |
996 return result; | |
997 } | |
998 | |
999 | |
1000 static PyObject* | |
1001 element_itertext(ElementObject* self, PyObject* args) | |
1002 { | |
1003 PyObject* result; | |
1004 ···· | |
1005 if (!PyArg_ParseTuple(args, ":itertext")) | |
1006 return NULL; | |
1007 | |
1008 if (!elementtree_itertext_obj) { | |
1009 PyErr_SetString( | |
1010 PyExc_RuntimeError, | |
1011 "itertext helper not found" | |
1012 ); | |
1013 return NULL; | |
1014 } | |
1015 | |
1016 args = PyTuple_New(1); | |
1017 if (!args) | |
1018 return NULL; | |
1019 | |
1020 Py_INCREF(self); PyTuple_SET_ITEM(args, 0, (PyObject*) self); | |
1021 | |
1022 result = PyObject_CallObject(elementtree_itertext_obj, args); | |
1023 | |
1024 Py_DECREF(args); | |
1025 | |
942 return result; | 1026 return result; |
943 } | 1027 } |
944 | 1028 |
945 static PyObject* | 1029 static PyObject* |
946 element_getitem(PyObject* self_, Py_ssize_t index) | 1030 element_getitem(PyObject* self_, Py_ssize_t index) |
947 { | 1031 { |
948 ElementObject* self = (ElementObject*) self_; | 1032 ElementObject* self = (ElementObject*) self_; |
949 | 1033 |
950 if (!self->extra || index < 0 || index >= self->extra->length) { | 1034 if (!self->extra || index < 0 || index >= self->extra->length) { |
951 PyErr_SetString( | 1035 PyErr_SetString( |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
999 | 1083 |
1000 int index; | 1084 int index; |
1001 PyObject* element; | 1085 PyObject* element; |
1002 if (!PyArg_ParseTuple(args, "iO!:insert", &index, | 1086 if (!PyArg_ParseTuple(args, "iO!:insert", &index, |
1003 &Element_Type, &element)) | 1087 &Element_Type, &element)) |
1004 return NULL; | 1088 return NULL; |
1005 | 1089 |
1006 if (!self->extra) | 1090 if (!self->extra) |
1007 element_new_extra(self, NULL); | 1091 element_new_extra(self, NULL); |
1008 | 1092 |
1009 if (index < 0) | 1093 if (index < 0) { |
1010 index = 0; | 1094 index += self->extra->length; |
1095 if (index < 0) | |
1096 index = 0; | |
1097 } | |
1011 if (index > self->extra->length) | 1098 if (index > self->extra->length) |
1012 index = self->extra->length; | 1099 index = self->extra->length; |
1013 | 1100 |
1014 if (element_resize(self, 1) < 0) | 1101 if (element_resize(self, 1) < 0) |
1015 return NULL; | 1102 return NULL; |
1016 | 1103 |
1017 for (i = self->extra->length; i > index; i--) | 1104 for (i = self->extra->length; i > index; i--) |
1018 self->extra->children[i] = self->extra->children[i-1]; | 1105 self->extra->children[i] = self->extra->children[i-1]; |
1019 | 1106 |
1020 Py_INCREF(element); | 1107 Py_INCREF(element); |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1181 if (!attrib) | 1268 if (!attrib) |
1182 return NULL; | 1269 return NULL; |
1183 | 1270 |
1184 if (PyDict_SetItem(attrib, key, value) < 0) | 1271 if (PyDict_SetItem(attrib, key, value) < 0) |
1185 return NULL; | 1272 return NULL; |
1186 | 1273 |
1187 Py_RETURN_NONE; | 1274 Py_RETURN_NONE; |
1188 } | 1275 } |
1189 | 1276 |
1190 static int | 1277 static int |
1191 element_setslice(PyObject* self_, Py_ssize_t start, Py_ssize_t end, PyObject* it em) | 1278 element_setslice(PyObject* self_, Py_ssize_t start, Py_ssize_t end, PyObject* se q_in) |
1192 { | 1279 { |
1193 ElementObject* self = (ElementObject*) self_; | 1280 ElementObject* self = (ElementObject*) self_; |
1194 Py_ssize_t i, new, old; | 1281 Py_ssize_t i, new, old; |
1195 PyObject* recycle = NULL; | 1282 PyObject* recycle = NULL; |
1283 PyObject* seq = NULL; | |
1196 | 1284 |
1197 if (!self->extra) | 1285 if (!self->extra) |
1198 element_new_extra(self, NULL); | 1286 element_new_extra(self, NULL); |
1199 | 1287 |
1200 /* standard clamping */ | 1288 /* standard clamping */ |
1201 if (start < 0) | 1289 if (start < 0) |
1202 start = 0; | 1290 start = 0; |
1203 if (end < 0) | 1291 if (end < 0) |
1204 end = 0; | 1292 end = 0; |
1205 if (end > self->extra->length) | 1293 if (end > self->extra->length) |
1206 end = self->extra->length; | 1294 end = self->extra->length; |
1207 if (start > end) | 1295 if (start > end) |
1208 start = end; | 1296 start = end; |
1209 | 1297 |
1210 old = end - start; | 1298 old = end - start; |
1211 | 1299 |
1212 if (item == NULL) | 1300 if (seq_in == NULL) |
1213 new = 0; | 1301 new = 0; |
1214 else if (PyList_CheckExact(item)) { | 1302 else { |
1215 new = PyList_GET_SIZE(item); | 1303 seq = PySequence_Fast(seq_in, "can only assign an iterable"); |
flox
2010/02/12 14:07:23
2nd argument is useless and can be reverted to emp
Antoine Pitrou
2010/02/12 15:27:46
Certainly, yes.
| |
1216 } else { | 1304 if (!seq) { |
1217 /* FIXME: support arbitrary sequences? */ | 1305 PyErr_Format( |
1218 PyErr_Format( | 1306 PyExc_TypeError, |
1219 PyExc_TypeError, | 1307 "expected sequence, not \"%.200s\"", Py_TYPE(seq_in)->tp_name |
1220 "expected list, not \"%.200s\"", Py_TYPE(item)->tp_name | 1308 ); |
1221 ); | 1309 return -1; |
1222 return -1; | 1310 } |
1311 new = PySequence_Size(seq); | |
1223 } | 1312 } |
1224 | 1313 |
1225 if (old > 0) { | 1314 if (old > 0) { |
1226 /* to avoid recursive calls to this method (via decref), move | 1315 /* to avoid recursive calls to this method (via decref), move |
1227 old items to the recycle bin here, and get rid of them when | 1316 old items to the recycle bin here, and get rid of them when |
1228 we're done modifying the element */ | 1317 we're done modifying the element */ |
1229 recycle = PyList_New(old); | 1318 recycle = PyList_New(old); |
1230 for (i = 0; i < old; i++) | 1319 for (i = 0; i < old; i++) |
1231 PyList_SET_ITEM(recycle, i, self->extra->children[i + start]); | 1320 PyList_SET_ITEM(recycle, i, self->extra->children[i + start]); |
1232 } | 1321 } |
1233 | 1322 |
1234 if (new < old) { | 1323 if (new < old) { |
1235 /* delete slice */ | 1324 /* delete slice */ |
1236 for (i = end; i < self->extra->length; i++) | 1325 for (i = end; i < self->extra->length; i++) |
1237 self->extra->children[i + new - old] = self->extra->children[i]; | 1326 self->extra->children[i + new - old] = self->extra->children[i]; |
1238 } else if (new > old) { | 1327 } else if (new > old) { |
1239 /* insert slice */ | 1328 /* insert slice */ |
1240 if (element_resize(self, new - old) < 0) | 1329 if (element_resize(self, new - old) < 0) { |
1330 if (seq) | |
1331 Py_DECREF(seq); | |
1241 return -1; | 1332 return -1; |
1333 } | |
1242 for (i = self->extra->length-1; i >= end; i--) | 1334 for (i = self->extra->length-1; i >= end; i--) |
1243 self->extra->children[i + new - old] = self->extra->children[i]; | 1335 self->extra->children[i + new - old] = self->extra->children[i]; |
1244 } | 1336 } |
1245 | 1337 |
1246 /* replace the slice */ | 1338 /* replace the slice */ |
1247 for (i = 0; i < new; i++) { | 1339 for (i = 0; i < new; i++) { |
1248 PyObject* element = PyList_GET_ITEM(item, i); | 1340 PyObject* element = PySequence_Fast_GET_ITEM(seq, i); |
1249 Py_INCREF(element); | 1341 Py_INCREF(element); |
1250 self->extra->children[i + start] = element; | 1342 self->extra->children[i + start] = element; |
1251 } | 1343 } |
1252 | 1344 |
1253 self->extra->length += new - old; | 1345 self->extra->length += new - old; |
1254 | 1346 |
1347 if (seq) | |
1348 Py_DECREF(seq); | |
1349 | |
1255 /* discard the recycle bin, and everything in it */ | 1350 /* discard the recycle bin, and everything in it */ |
1256 Py_XDECREF(recycle); | 1351 Py_XDECREF(recycle); |
1257 | 1352 |
1258 return 0; | 1353 return 0; |
1259 } | 1354 } |
1260 | 1355 |
1261 static int | 1356 static int |
1262 element_setitem(PyObject* self_, Py_ssize_t index, PyObject* item) | 1357 element_setitem(PyObject* self_, Py_ssize_t index, PyObject* item) |
1263 { | 1358 { |
1264 ElementObject* self = (ElementObject*) self_; | 1359 ElementObject* self = (ElementObject*) self_; |
(...skipping 16 matching lines...) Expand all Loading... | |
1281 self->extra->length--; | 1376 self->extra->length--; |
1282 for (i = index; i < self->extra->length; i++) | 1377 for (i = index; i < self->extra->length; i++) |
1283 self->extra->children[i] = self->extra->children[i+1]; | 1378 self->extra->children[i] = self->extra->children[i+1]; |
1284 } | 1379 } |
1285 | 1380 |
1286 Py_DECREF(old); | 1381 Py_DECREF(old); |
1287 | 1382 |
1288 return 0; | 1383 return 0; |
1289 } | 1384 } |
1290 | 1385 |
1386 static PyObject* | |
1387 element_subscr(PyObject* self_, PyObject* item) | |
1388 { | |
1389 ElementObject* self = (ElementObject*) self_; | |
1390 | |
1391 if (PyIndex_Check(item)) { | |
1392 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); | |
1393 if (i==-1 && PyErr_Occurred()) { | |
1394 return NULL; | |
1395 } | |
1396 if (i < 0 && self->extra) | |
1397 i += self->extra->length; | |
1398 return element_getitem(self_, i); | |
1399 } | |
1400 else if (PySlice_Check(item)) { | |
1401 Py_ssize_t start, stop, step, slicelen, cur, i; | |
1402 PyObject* list; | |
1403 | |
1404 if (!self->extra) | |
1405 return PyList_New(0); | |
1406 | |
1407 if (PySlice_GetIndicesEx((PySliceObject *)item, | |
1408 self->extra->length, | |
1409 &start, &stop, &step, &slicelen) < 0) { | |
1410 return NULL; | |
1411 } | |
1412 | |
1413 if (slicelen <= 0) | |
1414 return PyList_New(0); | |
1415 else { | |
1416 list = PyList_New(slicelen); | |
1417 if (!list) | |
1418 return NULL; | |
1419 | |
1420 for (cur = start, i = 0; i < slicelen; | |
1421 cur += step, i++) { | |
1422 PyObject* item = self->extra->children[cur]; | |
1423 Py_INCREF(item); | |
1424 PyList_SET_ITEM(list, i, item); | |
1425 } | |
1426 | |
1427 return list; | |
1428 } | |
1429 } | |
1430 else { | |
1431 PyErr_SetString(PyExc_TypeError, | |
1432 "element indices must be integers"); | |
1433 return NULL; | |
1434 } | |
1435 } | |
1436 | |
1437 static int | |
1438 element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value) | |
1439 { | |
1440 ElementObject* self = (ElementObject*) self_; | |
1441 | |
1442 if (PyIndex_Check(item)) { | |
1443 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); | |
1444 | |
1445 if (i==-1 && PyErr_Occurred()) { | |
1446 return -1; | |
1447 } | |
1448 if (i < 0 && self->extra) | |
1449 i += self->extra->length; | |
1450 return element_setitem(self_, i, value); | |
1451 } | |
1452 else if (PySlice_Check(item)) { | |
1453 Py_ssize_t start, stop, step, slicelen, newlen, cur, i; | |
1454 | |
1455 PyObject* recycle = NULL; | |
1456 PyObject* seq = NULL; | |
1457 | |
1458 if (!self->extra) | |
1459 element_new_extra(self, NULL); | |
1460 | |
1461 if (PySlice_GetIndicesEx((PySliceObject *)item, | |
1462 self->extra->length, | |
1463 &start, &stop, &step, &slicelen) < 0) { | |
1464 return -1; | |
1465 } | |
1466 | |
1467 if (value == NULL) | |
1468 newlen = 0; | |
1469 else { | |
1470 seq = PySequence_Fast(value, ""); | |
1471 if (!seq) { | |
1472 PyErr_Format( | |
1473 PyExc_TypeError, | |
1474 "expected sequence, not \"%.200s\"", Py_TYPE(value)->tp_name | |
1475 ); | |
1476 return -1; | |
1477 } | |
1478 newlen = PySequence_Size(seq); | |
1479 } | |
1480 | |
1481 if (step != 1 && newlen != slicelen) | |
1482 { | |
1483 PyErr_Format(PyExc_ValueError, | |
1484 "attempt to assign sequence of size %zd " | |
1485 "to extended slice of size %zd", | |
1486 newlen, slicelen | |
1487 ); | |
1488 return -1; | |
1489 } | |
1490 | |
1491 | |
1492 /* Resize before creating the recycle bin, to prevent refleaks. */ | |
1493 if (newlen > slicelen) { | |
1494 if (element_resize(self, newlen - slicelen) < 0) { | |
1495 if (seq) | |
1496 Py_DECREF(seq); | |
1497 return -1; | |
1498 } | |
1499 } | |
1500 | |
1501 if (slicelen > 0) { | |
1502 /* to avoid recursive calls to this method (via decref), move | |
1503 old items to the recycle bin here, and get rid of them when | |
1504 we're done modifying the element */ | |
1505 recycle = PyList_New(slicelen); | |
1506 if (!recycle) { | |
1507 if (seq) | |
1508 Py_DECREF(seq); | |
1509 return -1; | |
1510 } | |
1511 for (cur = start, i = 0; i < slicelen; | |
1512 cur += step, i++) | |
1513 PyList_SET_ITEM(recycle, i, self->extra->children[cur]); | |
1514 } | |
1515 | |
1516 if (newlen < slicelen) { | |
1517 /* delete slice */ | |
1518 for (i = stop; i < self->extra->length; i++) | |
1519 self->extra->children[i + newlen - slicelen] = self->extra->chil dren[i]; | |
1520 } else if (newlen > slicelen) { | |
1521 /* insert slice */ | |
1522 for (i = self->extra->length-1; i >= stop; i--) | |
1523 self->extra->children[i + newlen - slicelen] = self->extra->chil dren[i]; | |
1524 } | |
1525 | |
1526 /* replace the slice */ | |
1527 for (cur = start, i = 0; i < newlen; | |
1528 cur += step, i++) { | |
1529 PyObject* element = PySequence_Fast_GET_ITEM(seq, i); | |
1530 Py_INCREF(element); | |
1531 self->extra->children[cur] = element; | |
1532 } | |
1533 | |
1534 self->extra->length += newlen - slicelen; | |
1535 | |
1536 if (seq) | |
1537 Py_DECREF(seq); | |
1538 | |
1539 /* discard the recycle bin, and everything in it */ | |
1540 Py_XDECREF(recycle); | |
1541 | |
1542 return 0; | |
1543 } | |
1544 else { | |
1545 PyErr_SetString(PyExc_TypeError, | |
1546 "element indices must be integers"); | |
1547 return -1; | |
1548 } | |
1549 } | |
1550 | |
1291 static PyMethodDef element_methods[] = { | 1551 static PyMethodDef element_methods[] = { |
1292 | 1552 |
1293 {"clear", (PyCFunction) element_clear, METH_VARARGS}, | 1553 {"clear", (PyCFunction) element_clear, METH_VARARGS}, |
1294 | 1554 |
1295 {"get", (PyCFunction) element_get, METH_VARARGS}, | 1555 {"get", (PyCFunction) element_get, METH_VARARGS}, |
1296 {"set", (PyCFunction) element_set, METH_VARARGS}, | 1556 {"set", (PyCFunction) element_set, METH_VARARGS}, |
1297 | 1557 |
1298 {"find", (PyCFunction) element_find, METH_VARARGS}, | 1558 {"find", (PyCFunction) element_find, METH_VARARGS}, |
1299 {"findtext", (PyCFunction) element_findtext, METH_VARARGS}, | 1559 {"findtext", (PyCFunction) element_findtext, METH_VARARGS}, |
1300 {"findall", (PyCFunction) element_findall, METH_VARARGS}, | 1560 {"findall", (PyCFunction) element_findall, METH_VARARGS}, |
1301 | 1561 |
1302 {"append", (PyCFunction) element_append, METH_VARARGS}, | 1562 {"append", (PyCFunction) element_append, METH_VARARGS}, |
1563 {"extend", (PyCFunction) element_extend, METH_VARARGS}, | |
1303 {"insert", (PyCFunction) element_insert, METH_VARARGS}, | 1564 {"insert", (PyCFunction) element_insert, METH_VARARGS}, |
1304 {"remove", (PyCFunction) element_remove, METH_VARARGS}, | 1565 {"remove", (PyCFunction) element_remove, METH_VARARGS}, |
1305 | 1566 |
1306 {"getiterator", (PyCFunction) element_getiterator, METH_VARARGS}, | 1567 {"iter", (PyCFunction) element_iter, METH_VARARGS}, |
1568 {"itertext", (PyCFunction) element_itertext, METH_VARARGS}, | |
1569 | |
1570 {"getiterator", (PyCFunction) element_iter, METH_VARARGS}, | |
1307 {"getchildren", (PyCFunction) element_getchildren, METH_VARARGS}, | 1571 {"getchildren", (PyCFunction) element_getchildren, METH_VARARGS}, |
1308 | 1572 |
1309 {"items", (PyCFunction) element_items, METH_VARARGS}, | 1573 {"items", (PyCFunction) element_items, METH_VARARGS}, |
1310 {"keys", (PyCFunction) element_keys, METH_VARARGS}, | 1574 {"keys", (PyCFunction) element_keys, METH_VARARGS}, |
1311 | 1575 |
1312 {"makeelement", (PyCFunction) element_makeelement, METH_VARARGS}, | 1576 {"makeelement", (PyCFunction) element_makeelement, METH_VARARGS}, |
1313 | 1577 |
1314 {"__copy__", (PyCFunction) element_copy, METH_VARARGS}, | 1578 {"__copy__", (PyCFunction) element_copy, METH_VARARGS}, |
1315 {"__deepcopy__", (PyCFunction) element_deepcopy, METH_VARARGS}, | 1579 {"__deepcopy__", (PyCFunction) element_deepcopy, METH_VARARGS}, |
1316 | 1580 |
(...skipping 12 matching lines...) Expand all Loading... | |
1329 {NULL, NULL} | 1593 {NULL, NULL} |
1330 }; | 1594 }; |
1331 | 1595 |
1332 static PyObject*·· | 1596 static PyObject*·· |
1333 element_getattr(ElementObject* self, char* name) | 1597 element_getattr(ElementObject* self, char* name) |
1334 { | 1598 { |
1335 PyObject* res; | 1599 PyObject* res; |
1336 | 1600 |
1337 res = Py_FindMethod(element_methods, (PyObject*) self, name); | 1601 res = Py_FindMethod(element_methods, (PyObject*) self, name); |
1338 if (res) | 1602 if (res) |
1339 » return res; | 1603 return res; |
1340 | 1604 |
1341 PyErr_Clear(); | 1605 PyErr_Clear(); |
1342 | 1606 |
1343 if (strcmp(name, "tag") == 0) | 1607 if (strcmp(name, "tag") == 0) |
1344 » res = self->tag; | 1608 res = self->tag; |
1345 else if (strcmp(name, "text") == 0) | 1609 else if (strcmp(name, "text") == 0) |
1346 res = element_get_text(self); | 1610 res = element_get_text(self); |
1347 else if (strcmp(name, "tail") == 0) { | 1611 else if (strcmp(name, "tail") == 0) { |
1348 res = element_get_tail(self); | 1612 res = element_get_tail(self); |
1349 } else if (strcmp(name, "attrib") == 0) { | 1613 } else if (strcmp(name, "attrib") == 0) { |
1350 if (!self->extra) | 1614 if (!self->extra) |
1351 element_new_extra(self, NULL); | 1615 element_new_extra(self, NULL); |
1352 » res = element_get_attrib(self); | 1616 res = element_get_attrib(self); |
1353 } else { | 1617 } else { |
1354 PyErr_SetString(PyExc_AttributeError, name); | 1618 PyErr_SetString(PyExc_AttributeError, name); |
1355 return NULL; | 1619 return NULL; |
1356 } | 1620 } |
1357 | 1621 |
1358 if (!res) | 1622 if (!res) |
1359 return NULL; | 1623 return NULL; |
1360 | 1624 |
1361 Py_INCREF(res); | 1625 Py_INCREF(res); |
1362 return res; | 1626 return res; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1397 } | 1661 } |
1398 | 1662 |
1399 return 0; | 1663 return 0; |
1400 } | 1664 } |
1401 | 1665 |
1402 static PySequenceMethods element_as_sequence = { | 1666 static PySequenceMethods element_as_sequence = { |
1403 (lenfunc) element_length, | 1667 (lenfunc) element_length, |
1404 0, /* sq_concat */ | 1668 0, /* sq_concat */ |
1405 0, /* sq_repeat */ | 1669 0, /* sq_repeat */ |
1406 element_getitem, | 1670 element_getitem, |
1407 element_getslice, | 1671 0, |
1408 element_setitem, | 1672 element_setitem, |
1409 element_setslice, | 1673 0, |
Antoine Pitrou
2010/02/12 15:27:46
If element_setslice and element_getslice aren't us
flox
2010/02/12 16:07:47
* element_setslice is unused
* element_getslice i
| |
1674 }; | |
1675 | |
1676 static PyMappingMethods element_as_mapping = { | |
1677 (lenfunc) element_length, | |
1678 (binaryfunc) element_subscr, | |
1679 (objobjargproc) element_ass_subscr | |
1410 }; | 1680 }; |
1411 | 1681 |
1412 statichere PyTypeObject Element_Type = { | 1682 statichere PyTypeObject Element_Type = { |
1413 PyObject_HEAD_INIT(NULL) | 1683 PyObject_HEAD_INIT(NULL) |
1414 0, "Element", sizeof(ElementObject), 0, | 1684 0, "Element", sizeof(ElementObject), 0, |
1415 /* methods */ | 1685 /* methods */ |
1416 (destructor)element_dealloc, /* tp_dealloc */ | 1686 (destructor)element_dealloc, /* tp_dealloc */ |
1417 0, /* tp_print */ | 1687 0, /* tp_print */ |
1418 (getattrfunc)element_getattr, /* tp_getattr */ | 1688 (getattrfunc)element_getattr, /* tp_getattr */ |
1419 (setattrfunc)element_setattr, /* tp_setattr */ | 1689 (setattrfunc)element_setattr, /* tp_setattr */ |
1420 0, /* tp_compare */ | 1690 0, /* tp_compare */ |
1421 (reprfunc)element_repr, /* tp_repr */ | 1691 (reprfunc)element_repr, /* tp_repr */ |
1422 0, /* tp_as_number */ | 1692 0, /* tp_as_number */ |
1423 &element_as_sequence, /* tp_as_sequence */ | 1693 &element_as_sequence, /* tp_as_sequence */ |
1694 &element_as_mapping, /* tp_as_mapping */ | |
1424 }; | 1695 }; |
1425 | 1696 |
1697 /* -------------------------------------------------------------------- */ | |
1698 /* CAPI interface */ | |
1699 | |
1700 static int | |
1701 element_capi_assert(PyObject* elem) | |
1702 { | |
1703 if (Element_CheckExact(elem)) | |
1704 return 0; | |
1705 PyErr_Format( | |
1706 PyExc_TypeError, | |
1707 "expected cElementTree.Element, not \"%.200s\"", | |
1708 elem->ob_type->tp_name | |
1709 ); | |
1710 return -1; | |
1711 } | |
1712 | |
1713 static PyObject* | |
1714 element_capi_getitem(PyObject* self, int index) | |
1715 { | |
1716 ElementObject* elem = (ElementObject*) self; | |
1717 | |
1718 if (!elem->extra || index < 0 || index >= elem->extra->length) | |
1719 Py_RETURN_NONE; | |
1720 | |
1721 Py_INCREF(elem->extra->children[index]); | |
1722 return elem->extra->children[index]; | |
1723 } | |
1724 | |
1725 static int | |
1726 element_capi_snapshot(PyObject* self, struct cElementTree_Snapshot* snapshot, | |
1727 int mode) | |
1728 { | |
1729 ElementObject* elem = (ElementObject*) self; | |
1730 | |
1731 snapshot->tag = elem->tag; | |
1732 Py_INCREF(snapshot->tag); | |
1733 | |
1734 snapshot->text = element_get_text(elem); | |
1735 Py_INCREF(snapshot->text); | |
1736 | |
1737 snapshot->tail = element_get_tail(elem); | |
1738 Py_INCREF(snapshot->tail); | |
1739 | |
1740 if (elem->extra) | |
1741 snapshot->attrib = element_get_attrib(elem); | |
1742 else | |
1743 snapshot->attrib = Py_None; | |
1744 Py_INCREF(snapshot->attrib); | |
1745 | |
1746 if (!mode) | |
1747 return 0; | |
1748 | |
1749 if (elem->extra) { | |
1750 snapshot->children = element_getslice( | |
1751 (PyObject*) elem, 0, elem->extra->length | |
1752 ); | |
1753 /* FIXME: clean up if slice fails */ | |
1754 } else { | |
1755 snapshot->children = Py_None; | |
1756 Py_INCREF(snapshot->children); | |
1757 } | |
1758 ········ | |
1759 return 0; | |
1760 } | |
1761 | |
1426 /* ==================================================================== */ | 1762 /* ==================================================================== */ |
1427 /* the tree builder type */ | 1763 /* the tree builder type */ |
1428 | 1764 |
1429 typedef struct { | 1765 typedef struct { |
1430 PyObject_HEAD | 1766 PyObject_HEAD |
1431 | 1767 |
1432 PyObject* root; /* root node (first created node) */ | 1768 PyObject* root; /* root node (first created node) */ |
1433 | 1769 |
1434 ElementObject* this; /* current node */ | 1770 ElementObject* this; /* current node */ |
1435 ElementObject* last; /* most recently created node */ | 1771 ElementObject* last; /* most recently created node */ |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1551 return NULL; | 1887 return NULL; |
1552 | 1888 |
1553 this = (PyObject*) self->this; | 1889 this = (PyObject*) self->this; |
1554 | 1890 |
1555 if (this != Py_None) { | 1891 if (this != Py_None) { |
1556 if (element_add_subelement((ElementObject*) this, node) < 0) | 1892 if (element_add_subelement((ElementObject*) this, node) < 0) |
1557 goto error; | 1893 goto error; |
1558 } else { | 1894 } else { |
1559 if (self->root) { | 1895 if (self->root) { |
1560 PyErr_SetString( | 1896 PyErr_SetString( |
1561 PyExc_SyntaxError, | 1897 elementtree_parseerror_obj, |
1562 "multiple elements on top level" | 1898 "multiple elements on top level" |
1563 ); | 1899 ); |
1564 goto error; | 1900 goto error; |
1565 } | 1901 } |
1566 Py_INCREF(node); | 1902 Py_INCREF(node); |
1567 self->root = node; | 1903 self->root = node; |
1568 } | 1904 } |
1569 | 1905 |
1570 if (self->index < PyList_GET_SIZE(self->stack)) { | 1906 if (self->index < PyList_GET_SIZE(self->stack)) { |
1571 if (PyList_SetItem(self->stack, self->index, this) < 0) | 1907 if (PyList_SetItem(self->stack, self->index, this) < 0) |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1850 PyObject_HEAD | 2186 PyObject_HEAD |
1851 | 2187 |
1852 XML_Parser parser; | 2188 XML_Parser parser; |
1853 | 2189 |
1854 PyObject* target; | 2190 PyObject* target; |
1855 PyObject* entity; | 2191 PyObject* entity; |
1856 | 2192 |
1857 PyObject* names; | 2193 PyObject* names; |
1858 | 2194 |
1859 PyObject* handle_xml; | 2195 PyObject* handle_xml; |
2196 | |
1860 PyObject* handle_start; | 2197 PyObject* handle_start; |
1861 PyObject* handle_data; | 2198 PyObject* handle_data; |
1862 PyObject* handle_end; | 2199 PyObject* handle_end; |
1863 | 2200 |
1864 PyObject* handle_comment; | 2201 PyObject* handle_comment; |
1865 PyObject* handle_pi; | 2202 PyObject* handle_pi; |
1866 | 2203 |
2204 PyObject* handle_close; | |
2205 | |
1867 } XMLParserObject; | 2206 } XMLParserObject; |
1868 | 2207 |
1869 staticforward PyTypeObject XMLParser_Type; | 2208 staticforward PyTypeObject XMLParser_Type; |
1870 | 2209 |
1871 /* helpers */ | 2210 /* helpers */ |
1872 | 2211 |
1873 #if defined(Py_USING_UNICODE) | 2212 #if defined(Py_USING_UNICODE) |
1874 LOCAL(int) | 2213 LOCAL(int) |
1875 checkstring(const char* string, int size) | 2214 checkstring(const char* string, int size) |
1876 { | 2215 { |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1964 Py_DECREF(key); | 2303 Py_DECREF(key); |
1965 Py_DECREF(value); | 2304 Py_DECREF(value); |
1966 return NULL; | 2305 return NULL; |
1967 } | 2306 } |
1968 } | 2307 } |
1969 | 2308 |
1970 Py_DECREF(key); | 2309 Py_DECREF(key); |
1971 return value; | 2310 return value; |
1972 } | 2311 } |
1973 | 2312 |
2313 static void | |
2314 expat_set_error(const char* message, int line, int column) | |
2315 { | |
2316 PyObject *error; | |
2317 PyObject *position; | |
2318 char buffer[256]; | |
2319 | |
2320 sprintf(buffer, "%s: line %d, column %d", message, line, column); | |
2321 | |
2322 error = PyObject_CallFunction(elementtree_parseerror_obj, "s", buffer); | |
2323 if (!error) | |
2324 return; | |
2325 | |
2326 /* add position attribute */ | |
2327 position = Py_BuildValue("(ii)", line, column); | |
2328 if (!position) { | |
2329 Py_DECREF(error); | |
2330 return; | |
2331 } | |
2332 if (PyObject_SetAttrString(error, "position", position) == -1) { | |
2333 Py_DECREF(error); | |
2334 Py_DECREF(position); | |
2335 return; | |
2336 } | |
2337 Py_DECREF(position); | |
2338 | |
2339 PyErr_SetObject(elementtree_parseerror_obj, error); | |
2340 Py_DECREF(error); | |
2341 } | |
2342 | |
1974 /* -------------------------------------------------------------------- */ | 2343 /* -------------------------------------------------------------------- */ |
1975 /* handlers */ | 2344 /* handlers */ |
1976 | 2345 |
1977 static void | 2346 static void |
1978 expat_default_handler(XMLParserObject* self, const XML_Char* data_in, | 2347 expat_default_handler(XMLParserObject* self, const XML_Char* data_in, |
1979 int data_len) | 2348 int data_len) |
1980 { | 2349 { |
1981 PyObject* key; | 2350 PyObject* key; |
1982 PyObject* value; | 2351 PyObject* value; |
1983 PyObject* res; | 2352 PyObject* res; |
(...skipping 10 matching lines...) Expand all Loading... | |
1994 if (value) { | 2363 if (value) { |
1995 if (TreeBuilder_CheckExact(self->target)) | 2364 if (TreeBuilder_CheckExact(self->target)) |
1996 res = treebuilder_handle_data( | 2365 res = treebuilder_handle_data( |
1997 (TreeBuilderObject*) self->target, value | 2366 (TreeBuilderObject*) self->target, value |
1998 ); | 2367 ); |
1999 else if (self->handle_data) | 2368 else if (self->handle_data) |
2000 res = PyObject_CallFunction(self->handle_data, "O", value); | 2369 res = PyObject_CallFunction(self->handle_data, "O", value); |
2001 else | 2370 else |
2002 res = NULL; | 2371 res = NULL; |
2003 Py_XDECREF(res); | 2372 Py_XDECREF(res); |
2004 } else { | 2373 } else if (!PyErr_Occurred()) { |
2005 PyErr_Format( | 2374 /* Report the first error, not the last */ |
2006 PyExc_SyntaxError, "undefined entity &%s;: line %ld, column %ld", | 2375 char message[128]; |
2007 PyString_AS_STRING(key), | 2376 sprintf(message, "undefined entity &%.100s;", PyString_AS_STRING(key)); |
2377 expat_set_error( | |
2378 message,· | |
2008 EXPAT(GetErrorLineNumber)(self->parser), | 2379 EXPAT(GetErrorLineNumber)(self->parser), |
2009 EXPAT(GetErrorColumnNumber)(self->parser) | 2380 EXPAT(GetErrorColumnNumber)(self->parser) |
2010 ); | 2381 ); |
2011 } | 2382 } |
2012 | 2383 |
2013 Py_DECREF(key); | 2384 Py_DECREF(key); |
2014 } | 2385 } |
2015 | 2386 |
2016 static void | 2387 static void |
2017 expat_start_handler(XMLParserObject* self, const XML_Char* tag_in, | 2388 expat_start_handler(XMLParserObject* self, const XML_Char* tag_in, |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2052 } | 2423 } |
2053 } else { | 2424 } else { |
2054 Py_INCREF(Py_None); | 2425 Py_INCREF(Py_None); |
2055 attrib = Py_None; | 2426 attrib = Py_None; |
2056 } | 2427 } |
2057 | 2428 |
2058 if (TreeBuilder_CheckExact(self->target)) | 2429 if (TreeBuilder_CheckExact(self->target)) |
2059 /* shortcut */ | 2430 /* shortcut */ |
2060 res = treebuilder_handle_start((TreeBuilderObject*) self->target, | 2431 res = treebuilder_handle_start((TreeBuilderObject*) self->target, |
2061 tag, attrib); | 2432 tag, attrib); |
2062 else if (self->handle_start) | 2433 else if (self->handle_start) { |
2434 if (attrib == Py_None) { | |
2435 Py_DECREF(attrib); | |
2436 attrib = PyDict_New(); | |
2437 if (!attrib) | |
2438 return; | |
2439 } | |
2063 res = PyObject_CallFunction(self->handle_start, "OO", tag, attrib); | 2440 res = PyObject_CallFunction(self->handle_start, "OO", tag, attrib); |
2064 else | 2441 } else |
2065 res = NULL; | 2442 res = NULL; |
2066 | 2443 |
2067 Py_DECREF(tag); | 2444 Py_DECREF(tag); |
2068 Py_DECREF(attrib); | 2445 Py_DECREF(attrib); |
2069 | 2446 |
2070 Py_XDECREF(res); | 2447 Py_XDECREF(res); |
2071 } | 2448 } |
2072 | 2449 |
2073 static void | 2450 static void |
2074 expat_data_handler(XMLParserObject* self, const XML_Char* data_in, | 2451 expat_data_handler(XMLParserObject* self, const XML_Char* data_in, |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2193 return XML_STATUS_ERROR; | 2570 return XML_STATUS_ERROR; |
2194 | 2571 |
2195 if (PyUnicode_GET_SIZE(u) != 256) { | 2572 if (PyUnicode_GET_SIZE(u) != 256) { |
2196 Py_DECREF(u); | 2573 Py_DECREF(u); |
2197 return XML_STATUS_ERROR; | 2574 return XML_STATUS_ERROR; |
2198 } | 2575 } |
2199 | 2576 |
2200 p = PyUnicode_AS_UNICODE(u); | 2577 p = PyUnicode_AS_UNICODE(u); |
2201 | 2578 |
2202 for (i = 0; i < 256; i++) { | 2579 for (i = 0; i < 256; i++) { |
2203 » if (p[i] != Py_UNICODE_REPLACEMENT_CHARACTER) | 2580 if (p[i] != Py_UNICODE_REPLACEMENT_CHARACTER) |
2204 » info->map[i] = p[i]; | 2581 info->map[i] = p[i]; |
2205 else | 2582 else |
2206 » info->map[i] = -1; | 2583 info->map[i] = -1; |
2207 } | 2584 } |
2208 | 2585 |
2209 Py_DECREF(u); | 2586 Py_DECREF(u); |
2210 | 2587 |
2211 return XML_STATUS_OK; | 2588 return XML_STATUS_OK; |
2212 } | 2589 } |
2213 #endif | 2590 #endif |
2214 | 2591 |
2215 /* -------------------------------------------------------------------- */ | 2592 /* -------------------------------------------------------------------- */ |
2216 /* constructor and destructor */ | 2593 /* constructor and destructor */ |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2281 } else | 2658 } else |
2282 Py_INCREF(target); | 2659 Py_INCREF(target); |
2283 self->target = target; | 2660 self->target = target; |
2284 | 2661 |
2285 self->handle_xml = PyObject_GetAttrString(target, "xml"); | 2662 self->handle_xml = PyObject_GetAttrString(target, "xml"); |
2286 self->handle_start = PyObject_GetAttrString(target, "start"); | 2663 self->handle_start = PyObject_GetAttrString(target, "start"); |
2287 self->handle_data = PyObject_GetAttrString(target, "data"); | 2664 self->handle_data = PyObject_GetAttrString(target, "data"); |
2288 self->handle_end = PyObject_GetAttrString(target, "end"); | 2665 self->handle_end = PyObject_GetAttrString(target, "end"); |
2289 self->handle_comment = PyObject_GetAttrString(target, "comment"); | 2666 self->handle_comment = PyObject_GetAttrString(target, "comment"); |
2290 self->handle_pi = PyObject_GetAttrString(target, "pi"); | 2667 self->handle_pi = PyObject_GetAttrString(target, "pi"); |
2668 self->handle_close = PyObject_GetAttrString(target, "close"); | |
2291 | 2669 |
2292 PyErr_Clear(); | 2670 PyErr_Clear(); |
2293 | 2671 |
2294 /* configure parser */ | 2672 /* configure parser */ |
2295 EXPAT(SetUserData)(self->parser, self); | 2673 EXPAT(SetUserData)(self->parser, self); |
2296 EXPAT(SetElementHandler)( | 2674 EXPAT(SetElementHandler)( |
2297 self->parser, | 2675 self->parser, |
2298 (XML_StartElementHandler) expat_start_handler, | 2676 (XML_StartElementHandler) expat_start_handler, |
2299 (XML_EndElementHandler) expat_end_handler | 2677 (XML_EndElementHandler) expat_end_handler |
2300 ); | 2678 ); |
(...skipping 25 matching lines...) Expand all Loading... | |
2326 ALLOC(sizeof(XMLParserObject), "create expatparser"); | 2704 ALLOC(sizeof(XMLParserObject), "create expatparser"); |
2327 | 2705 |
2328 return (PyObject*) self; | 2706 return (PyObject*) self; |
2329 } | 2707 } |
2330 | 2708 |
2331 static void | 2709 static void |
2332 xmlparser_dealloc(XMLParserObject* self) | 2710 xmlparser_dealloc(XMLParserObject* self) |
2333 { | 2711 { |
2334 EXPAT(ParserFree)(self->parser); | 2712 EXPAT(ParserFree)(self->parser); |
2335 | 2713 |
2714 Py_XDECREF(self->handle_close); | |
2336 Py_XDECREF(self->handle_pi); | 2715 Py_XDECREF(self->handle_pi); |
2337 Py_XDECREF(self->handle_comment); | 2716 Py_XDECREF(self->handle_comment); |
2338 Py_XDECREF(self->handle_end); | 2717 Py_XDECREF(self->handle_end); |
2339 Py_XDECREF(self->handle_data); | 2718 Py_XDECREF(self->handle_data); |
2340 Py_XDECREF(self->handle_start); | 2719 Py_XDECREF(self->handle_start); |
2341 Py_XDECREF(self->handle_xml); | 2720 Py_XDECREF(self->handle_xml); |
2342 | 2721 |
2343 Py_DECREF(self->target); | 2722 Py_DECREF(self->target); |
2344 Py_DECREF(self->entity); | 2723 Py_DECREF(self->entity); |
2345 Py_DECREF(self->names); | 2724 Py_DECREF(self->names); |
(...skipping 10 matching lines...) Expand all Loading... | |
2356 expat_parse(XMLParserObject* self, char* data, int data_len, int final) | 2735 expat_parse(XMLParserObject* self, char* data, int data_len, int final) |
2357 { | 2736 { |
2358 int ok; | 2737 int ok; |
2359 | 2738 |
2360 ok = EXPAT(Parse)(self->parser, data, data_len, final); | 2739 ok = EXPAT(Parse)(self->parser, data, data_len, final); |
2361 | 2740 |
2362 if (PyErr_Occurred()) | 2741 if (PyErr_Occurred()) |
2363 return NULL; | 2742 return NULL; |
2364 | 2743 |
2365 if (!ok) { | 2744 if (!ok) { |
2366 PyErr_Format( | 2745 expat_set_error( |
2367 PyExc_SyntaxError, "%s: line %ld, column %ld", | |
2368 EXPAT(ErrorString)(EXPAT(GetErrorCode)(self->parser)), | 2746 EXPAT(ErrorString)(EXPAT(GetErrorCode)(self->parser)), |
2369 EXPAT(GetErrorLineNumber)(self->parser), | 2747 EXPAT(GetErrorLineNumber)(self->parser), |
2370 EXPAT(GetErrorColumnNumber)(self->parser) | 2748 EXPAT(GetErrorColumnNumber)(self->parser) |
2371 ); | 2749 ); |
2372 return NULL; | 2750 return NULL; |
2373 } | 2751 } |
2374 | 2752 |
2375 Py_RETURN_NONE; | 2753 Py_RETURN_NONE; |
2376 } | 2754 } |
2377 | 2755 |
2378 static PyObject* | 2756 static PyObject* |
2379 xmlparser_close(XMLParserObject* self, PyObject* args) | 2757 xmlparser_close(XMLParserObject* self, PyObject* args) |
2380 { | 2758 { |
2381 /* end feeding data to parser */ | 2759 /* end feeding data to parser */ |
2382 | 2760 |
2383 PyObject* res; | 2761 PyObject* res; |
2384 if (!PyArg_ParseTuple(args, ":close")) | 2762 if (!PyArg_ParseTuple(args, ":close")) |
2385 return NULL; | 2763 return NULL; |
2386 | 2764 |
2387 res = expat_parse(self, "", 0, 1); | 2765 res = expat_parse(self, "", 0, 1); |
2766 if (!res) | |
2767 return NULL; | |
2388 | 2768 |
2389 if (res && TreeBuilder_CheckExact(self->target)) { | 2769 if (TreeBuilder_CheckExact(self->target)) { |
2390 Py_DECREF(res); | 2770 Py_DECREF(res); |
2391 return treebuilder_done((TreeBuilderObject*) self->target); | 2771 return treebuilder_done((TreeBuilderObject*) self->target); |
2392 } | 2772 } if (self->handle_close) { |
2393 | 2773 Py_DECREF(res); |
2394 return res; | 2774 return PyObject_CallFunction(self->handle_close, ""); |
2775 } else | |
2776 return res; | |
2395 } | 2777 } |
2396 | 2778 |
2397 static PyObject* | 2779 static PyObject* |
2398 xmlparser_feed(XMLParserObject* self, PyObject* args) | 2780 xmlparser_feed(XMLParserObject* self, PyObject* args) |
2399 { | 2781 { |
2400 /* feed data to parser */ | 2782 /* feed data to parser */ |
2401 | 2783 |
2402 char* data; | 2784 char* data; |
2403 int data_len; | 2785 int data_len; |
2404 if (!PyArg_ParseTuple(args, "s#:feed", &data, &data_len)) | 2786 if (!PyArg_ParseTuple(args, "s#:feed", &data, &data_len)) |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2568 {NULL, NULL} | 2950 {NULL, NULL} |
2569 }; | 2951 }; |
2570 | 2952 |
2571 static PyObject*·· | 2953 static PyObject*·· |
2572 xmlparser_getattr(XMLParserObject* self, char* name) | 2954 xmlparser_getattr(XMLParserObject* self, char* name) |
2573 { | 2955 { |
2574 PyObject* res; | 2956 PyObject* res; |
2575 | 2957 |
2576 res = Py_FindMethod(xmlparser_methods, (PyObject*) self, name); | 2958 res = Py_FindMethod(xmlparser_methods, (PyObject*) self, name); |
2577 if (res) | 2959 if (res) |
2578 » return res; | 2960 return res; |
2579 | 2961 |
2580 PyErr_Clear(); | 2962 PyErr_Clear(); |
2581 | 2963 |
2582 if (strcmp(name, "entity") == 0) | 2964 if (strcmp(name, "entity") == 0) |
2583 » res = self->entity; | 2965 res = self->entity; |
2584 else if (strcmp(name, "target") == 0) | 2966 else if (strcmp(name, "target") == 0) |
2585 » res = self->target; | 2967 res = self->target; |
2586 else if (strcmp(name, "version") == 0) { | 2968 else if (strcmp(name, "version") == 0) { |
2587 char buffer[100]; | 2969 char buffer[100]; |
2588 sprintf(buffer, "Expat %d.%d.%d", XML_MAJOR_VERSION, | 2970 sprintf(buffer, "Expat %d.%d.%d", XML_MAJOR_VERSION, |
2589 XML_MINOR_VERSION, XML_MICRO_VERSION); | 2971 XML_MINOR_VERSION, XML_MICRO_VERSION); |
2590 return PyString_FromString(buffer); | 2972 return PyString_FromString(buffer); |
2591 } else { | 2973 } else { |
2592 PyErr_SetString(PyExc_AttributeError, name); | 2974 PyErr_SetString(PyExc_AttributeError, name); |
2593 return NULL; | 2975 return NULL; |
2594 } | 2976 } |
2595 | 2977 |
(...skipping 25 matching lines...) Expand all Loading... | |
2621 #endif | 3003 #endif |
2622 {NULL, NULL} | 3004 {NULL, NULL} |
2623 }; | 3005 }; |
2624 | 3006 |
2625 DL_EXPORT(void) | 3007 DL_EXPORT(void) |
2626 init_elementtree(void) | 3008 init_elementtree(void) |
2627 { | 3009 { |
2628 PyObject* m; | 3010 PyObject* m; |
2629 PyObject* g; | 3011 PyObject* g; |
2630 char* bootstrap; | 3012 char* bootstrap; |
2631 #if defined(USE_PYEXPAT_CAPI) | 3013 static struct cElementTree_CAPI capi; |
2632 struct PyExpat_CAPI* capi; | 3014 PyObject* capi_object; |
2633 #endif | |
2634 | 3015 |
2635 /* Patch object type */ | 3016 /* Patch object type */ |
2636 Py_TYPE(&Element_Type) = Py_TYPE(&TreeBuilder_Type) = &PyType_Type; | 3017 Py_TYPE(&Element_Type) = Py_TYPE(&TreeBuilder_Type) = &PyType_Type; |
2637 #if defined(USE_EXPAT) | 3018 #if defined(USE_EXPAT) |
2638 Py_TYPE(&XMLParser_Type) = &PyType_Type; | 3019 Py_TYPE(&XMLParser_Type) = &PyType_Type; |
2639 #endif | 3020 #endif |
2640 | 3021 |
2641 m = Py_InitModule("_elementtree", _functions); | 3022 m = Py_InitModule("_elementtree", _functions); |
2642 if (!m) | 3023 if (!m) |
2643 return; | 3024 return; |
(...skipping 22 matching lines...) Expand all Loading... | |
2666 "del ElementTree\n" | 3047 "del ElementTree\n" |
2667 | 3048 |
2668 "import _elementtree as cElementTree\n" | 3049 "import _elementtree as cElementTree\n" |
2669 | 3050 |
2670 "try:\n" /* check if copy works as is */ | 3051 "try:\n" /* check if copy works as is */ |
2671 " copy(cElementTree.Element('x'))\n" | 3052 " copy(cElementTree.Element('x'))\n" |
2672 "except:\n" | 3053 "except:\n" |
2673 " def copyelement(elem):\n" | 3054 " def copyelement(elem):\n" |
2674 " return elem\n" | 3055 " return elem\n" |
2675 | 3056 |
2676 "def Comment(text=None):\n" /* public */ | 3057 "class CommentProxy:\n" |
3058 " def __call__(self, text=None):\n" | |
2677 " element = cElementTree.Element(ET.Comment)\n" | 3059 " element = cElementTree.Element(ET.Comment)\n" |
2678 " element.text = text\n" | 3060 " element.text = text\n" |
2679 " return element\n" | 3061 " return element\n" |
2680 "cElementTree.Comment = Comment\n" | 3062 " def __cmp__(self, other):\n" |
3063 " return cmp(ET.Comment, other)\n" | |
3064 "cElementTree.Comment = CommentProxy()\n" | |
2681 | 3065 |
2682 "class ElementTree(ET.ElementTree):\n" /* public */ | 3066 "class ElementTree(ET.ElementTree):\n" /* public */ |
2683 " def parse(self, source, parser=None):\n" | 3067 " def parse(self, source, parser=None):\n" |
2684 " if not hasattr(source, 'read'):\n" | 3068 " if not hasattr(source, 'read'):\n" |
2685 " source = open(source, 'rb')\n" | 3069 " source = open(source, 'rb')\n" |
2686 " if parser is not None:\n" | 3070 " if parser is not None:\n" |
2687 " while 1:\n" | 3071 " while 1:\n" |
2688 " data = source.read(65536)\n" | 3072 " data = source.read(65536)\n" |
2689 " if not data:\n" | 3073 " if not data:\n" |
2690 " break\n" | 3074 " break\n" |
2691 " parser.feed(data)\n" | 3075 " parser.feed(data)\n" |
2692 " self._root = parser.close()\n" | 3076 " self._root = parser.close()\n" |
2693 " else:\n"· | 3077 " else:\n"· |
2694 " parser = cElementTree.XMLParser()\n" | 3078 " parser = cElementTree.XMLParser()\n" |
2695 " self._root = parser._parse(source)\n" | 3079 " self._root = parser._parse(source)\n" |
2696 " return self._root\n" | 3080 " return self._root\n" |
2697 "cElementTree.ElementTree = ElementTree\n" | 3081 "cElementTree.ElementTree = ElementTree\n" |
2698 | 3082 |
2699 "def getiterator(node, tag=None):\n" /* helper */ | 3083 "def iter(node, tag=None):\n" /* helper */ |
2700 " if tag == '*':\n" | 3084 " if tag == '*':\n" |
2701 " tag = None\n" | 3085 " tag = None\n" |
2702 #if (PY_VERSION_HEX < 0x02020000) | 3086 #if (PY_VERSION_HEX < 0x02020000) |
2703 " nodes = []\n" /* 2.1 doesn't have yield */ | 3087 " nodes = []\n" /* 2.1 doesn't have yield */ |
2704 " if tag is None or node.tag == tag:\n" | 3088 " if tag is None or node.tag == tag:\n" |
2705 " nodes.append(node)\n" | 3089 " nodes.append(node)\n" |
2706 " for node in node:\n" | 3090 " for node in node:\n" |
2707 " nodes.extend(getiterator(node, tag))\n" | 3091 " nodes.extend(iter(node, tag))\n" |
2708 " return nodes\n" | 3092 " return nodes\n" |
2709 #else | 3093 #else |
2710 " if tag is None or node.tag == tag:\n" | 3094 " if tag is None or node.tag == tag:\n" |
2711 " yield node\n" | 3095 " yield node\n" |
2712 " for node in node:\n" | 3096 " for node in node:\n" |
2713 " for node in getiterator(node, tag):\n" | 3097 " for node in iter(node, tag):\n" |
2714 " yield node\n" | 3098 " yield node\n" |
2715 #endif | 3099 #endif |
2716 | 3100 |
3101 "def itertext(node):\n" /* helper */ | |
3102 " if node.text:\n" | |
3103 " yield node.text\n" | |
3104 " for e in node:\n" | |
3105 " for s in e.itertext():\n" | |
3106 " yield s\n" | |
3107 " if e.tail:\n" | |
3108 " yield e.tail\n" | |
3109 | |
2717 "def parse(source, parser=None):\n" /* public */ | 3110 "def parse(source, parser=None):\n" /* public */ |
2718 " tree = ElementTree()\n" | 3111 " tree = ElementTree()\n" |
2719 " tree.parse(source, parser)\n" | 3112 " tree.parse(source, parser)\n" |
2720 " return tree\n" | 3113 " return tree\n" |
2721 "cElementTree.parse = parse\n" | 3114 "cElementTree.parse = parse\n" |
2722 | 3115 |
2723 #if (PY_VERSION_HEX < 0x02020000) | 3116 #if (PY_VERSION_HEX < 0x02020000) |
2724 "if hasattr(ET, 'iterparse'):\n" | 3117 "if hasattr(ET, 'iterparse'):\n" |
2725 " cElementTree.iterparse = ET.iterparse\n" /* delegate on 2.1 */ | 3118 " cElementTree.iterparse = ET.iterparse\n" /* delegate on 2.1 */ |
2726 #else | 3119 #else |
2727 "class iterparse(object):\n" | 3120 "class iterparse(object):\n" |
2728 " root = None\n" | 3121 " root = None\n" |
2729 " def __init__(self, file, events=None):\n" | 3122 " def __init__(self, file, events=None):\n" |
2730 " if not hasattr(file, 'read'):\n" | 3123 " if not hasattr(file, 'read'):\n" |
2731 " file = open(file, 'rb')\n" | 3124 " file = open(file, 'rb')\n" |
2732 " self._file = file\n" | 3125 " self._file = file\n" |
2733 " self._events = events\n" | 3126 " self._events = []\n" |
2734 " def __iter__(self):\n" | 3127 " self._index = 0\n" |
2735 " events = []\n" | 3128 " self.root = self._root = None\n" |
2736 " b = cElementTree.TreeBuilder()\n" | 3129 " b = cElementTree.TreeBuilder()\n" |
2737 " p = cElementTree.XMLParser(b)\n" | 3130 " self._parser = cElementTree.XMLParser(b)\n" |
2738 " p._setevents(events, self._events)\n" | 3131 " self._parser._setevents(self._events, events)\n" |
3132 " def next(self):\n" | |
2739 " while 1:\n" | 3133 " while 1:\n" |
2740 " data = self._file.read(16384)\n" | 3134 " try:\n" |
2741 " if not data:\n" | 3135 " item = self._events[self._index]\n" |
2742 " break\n" | 3136 " except IndexError:\n" |
2743 " p.feed(data)\n" | 3137 " if self._parser is None:\n" |
2744 " for event in events:\n" | 3138 " self.root = self._root\n" |
2745 " yield event\n" | 3139 " raise StopIteration\n" |
2746 " del events[:]\n" | 3140 " # load event buffer\n" |
2747 " root = p.close()\n" | 3141 " del self._events[:]\n" |
2748 " for event in events:\n" | 3142 " self._index = 0\n" |
2749 " yield event\n" | 3143 " data = self._file.read(16384)\n" |
2750 " self.root = root\n" | 3144 " if data:\n" |
3145 " self._parser.feed(data)\n" | |
3146 " else:\n" | |
3147 " self._root = self._parser.close()\n" | |
3148 " self._parser = None\n" | |
3149 " else:\n" | |
3150 " self._index = self._index + 1\n" | |
3151 " return item\n" | |
3152 " def __iter__(self):\n" | |
3153 " return self\n" | |
2751 "cElementTree.iterparse = iterparse\n" | 3154 "cElementTree.iterparse = iterparse\n" |
2752 #endif | 3155 #endif |
2753 | 3156 |
2754 "def PI(target, text=None):\n" /* public */ | 3157 "class PIProxy:\n" |
2755 " element = cElementTree.Element(ET.ProcessingInstruction)\n" | 3158 " def __call__(self, target, text=None):\n" |
3159 " element = cElementTree.Element(ET.PI)\n" | |
2756 " element.text = target\n" | 3160 " element.text = target\n" |
2757 " if text:\n" | 3161 " if text:\n" |
2758 " element.text = element.text + ' ' + text\n" | 3162 " element.text = element.text + ' ' + text\n" |
2759 " return element\n" | 3163 " return element\n" |
2760 | 3164 " def __cmp__(self, other):\n" |
2761 " elem = cElementTree.Element(ET.PI)\n" | 3165 " return cmp(ET.PI, other)\n" |
2762 " elem.text = text\n" | 3166 "cElementTree.PI = cElementTree.ProcessingInstruction = PIProxy()\n" |
2763 " return elem\n" | |
2764 "cElementTree.PI = cElementTree.ProcessingInstruction = PI\n" | |
2765 | 3167 |
2766 "def XML(text):\n" /* public */ | 3168 "def XML(text):\n" /* public */ |
2767 " parser = cElementTree.XMLParser()\n" | 3169 " parser = cElementTree.XMLParser()\n" |
2768 " parser.feed(text)\n" | 3170 " parser.feed(text)\n" |
2769 " return parser.close()\n" | 3171 " return parser.close()\n" |
2770 "cElementTree.XML = cElementTree.fromstring = XML\n" | 3172 "cElementTree.XML = cElementTree.fromstring = XML\n" |
2771 | 3173 |
2772 "def XMLID(text):\n" /* public */ | 3174 "def XMLID(text):\n" /* public */ |
2773 " tree = XML(text)\n" | 3175 " tree = XML(text)\n" |
2774 " ids = {}\n" | 3176 " ids = {}\n" |
2775 " for elem in tree.getiterator():\n" | 3177 " for elem in tree.getiterator():\n" |
2776 " id = elem.get('id')\n" | 3178 " id = elem.get('id')\n" |
2777 " if id:\n" | 3179 " if id:\n" |
2778 " ids[id] = elem\n" | 3180 " ids[id] = elem\n" |
2779 " return tree, ids\n" | 3181 " return tree, ids\n" |
2780 "cElementTree.XMLID = XMLID\n" | 3182 "cElementTree.XMLID = XMLID\n" |
2781 | 3183 |
3184 "try:\n" | |
3185 " register_namespace = ET.register_namespace\n" | |
3186 "except AttributeError:\n" | |
3187 " def register_namespace(prefix, uri):\n" | |
3188 " ET._namespace_map[uri] = prefix\n" | |
3189 "cElementTree.register_namespace = register_namespace\n" | |
3190 | |
2782 "cElementTree.dump = ET.dump\n" | 3191 "cElementTree.dump = ET.dump\n" |
2783 "cElementTree.ElementPath = ElementPath = ET.ElementPath\n" | 3192 "cElementTree.ElementPath = ElementPath = ET.ElementPath\n" |
2784 "cElementTree.iselement = ET.iselement\n" | 3193 "cElementTree.iselement = ET.iselement\n" |
2785 "cElementTree.QName = ET.QName\n" | 3194 "cElementTree.QName = ET.QName\n" |
2786 "cElementTree.tostring = ET.tostring\n" | 3195 "cElementTree.tostring = ET.tostring\n" |
3196 "cElementTree.fromstringlist = ET.fromstringlist\n" | |
3197 "cElementTree.tostringlist = ET.tostringlist\n" | |
2787 "cElementTree.VERSION = '" VERSION "'\n" | 3198 "cElementTree.VERSION = '" VERSION "'\n" |
2788 "cElementTree.__version__ = '" VERSION "'\n" | 3199 "cElementTree.__version__ = '" VERSION "'\n" |
2789 "cElementTree.XMLParserError = SyntaxError\n" | |
2790 | 3200 |
2791 ); | 3201 ); |
2792 | 3202 |
2793 PyRun_String(bootstrap, Py_file_input, g, NULL); | 3203 if (!PyRun_String(bootstrap, Py_file_input, g, NULL)) |
3204 return; | |
2794 | 3205 |
2795 elementpath_obj = PyDict_GetItemString(g, "ElementPath"); | 3206 elementpath_obj = PyDict_GetItemString(g, "ElementPath"); |
2796 | 3207 |
2797 elementtree_copyelement_obj = PyDict_GetItemString(g, "copyelement"); | 3208 elementtree_copyelement_obj = PyDict_GetItemString(g, "copyelement"); |
2798 if (elementtree_copyelement_obj) { | 3209 if (elementtree_copyelement_obj) { |
2799 /* reduce hack needed; enable reduce method */ | 3210 /* reduce hack needed; enable reduce method */ |
2800 PyMethodDef* mp; | 3211 PyMethodDef* mp; |
2801 for (mp = element_methods; mp->ml_name; mp++) | 3212 for (mp = element_methods; mp->ml_name; mp++) |
2802 if (mp->ml_meth == (PyCFunction) element_reduce) { | 3213 if (mp->ml_meth == (PyCFunction) element_reduce) { |
2803 mp->ml_name = "__reduce__"; | 3214 mp->ml_name = "__reduce__"; |
2804 break; | 3215 break; |
2805 } | 3216 } |
2806 } else | 3217 } else |
2807 PyErr_Clear(); | 3218 PyErr_Clear(); |
3219 | |
2808 elementtree_deepcopy_obj = PyDict_GetItemString(g, "deepcopy"); | 3220 elementtree_deepcopy_obj = PyDict_GetItemString(g, "deepcopy"); |
2809 elementtree_getiterator_obj = PyDict_GetItemString(g, "getiterator"); | 3221 elementtree_iter_obj = PyDict_GetItemString(g, "iter"); |
3222 elementtree_itertext_obj = PyDict_GetItemString(g, "itertext"); | |
2810 | 3223 |
2811 #if defined(USE_PYEXPAT_CAPI) | 3224 #if defined(USE_PYEXPAT_CAPI) |
2812 /* link against pyexpat, if possible */ | 3225 /* link against pyexpat, if possible */ |
2813 capi = PyCObject_Import("pyexpat", "expat_CAPI"); | 3226 expat_capi = PyCObject_Import("pyexpat", "expat_CAPI"); |
2814 if (capi && | 3227 if (expat_capi) { |
2815 strcmp(capi->magic, PyExpat_CAPI_MAGIC) == 0 && | 3228 /* check that it's usable */ |
2816 capi->size <= sizeof(*expat_capi) && | 3229 if (strcmp(expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 || |
2817 capi->MAJOR_VERSION == XML_MAJOR_VERSION && | 3230 expat_capi->size < sizeof(struct PyExpat_CAPI) || |
2818 capi->MINOR_VERSION == XML_MINOR_VERSION && | 3231 expat_capi->MAJOR_VERSION != XML_MAJOR_VERSION || |
2819 capi->MICRO_VERSION == XML_MICRO_VERSION) | 3232 expat_capi->MINOR_VERSION != XML_MINOR_VERSION || |
2820 expat_capi = capi; | 3233 expat_capi->MICRO_VERSION != XML_MICRO_VERSION) |
2821 else | 3234 expat_capi = NULL; |
2822 expat_capi = NULL; | 3235 } |
2823 #endif | 3236 #endif |
2824 | 3237 |
3238 elementtree_parseerror_obj = PyErr_NewException( | |
3239 "cElementTree.ParseError", PyExc_SyntaxError, NULL | |
3240 ); | |
3241 Py_INCREF(elementtree_parseerror_obj); | |
3242 PyModule_AddObject(m, "ParseError", elementtree_parseerror_obj); | |
3243 | |
3244 capi.size = sizeof(capi); | |
3245 capi.magic = cElementTree_CAPI_MAGIC; | |
3246 capi.version = cElementTree_CAPI_VERSION; | |
3247 capi.type = (PyObject*) &Element_Type; | |
3248 capi.assert = element_capi_assert; | |
3249 capi.snapshot = element_capi_snapshot; | |
3250 capi.getitem = element_capi_getitem; | |
3251 | |
3252 /* export as cobject */ | |
3253 capi_object = PyCObject_FromVoidPtr(&capi, NULL); | |
3254 if (capi_object) | |
3255 PyModule_AddObject(m, "CAPI", capi_object); | |
2825 } | 3256 } |
OLD | NEW |