Ignore:
Timestamp:
Mar 19, 2014, 11:31:01 PM (11 years ago)
Author:
dmik
Message:

python: Merge vendor 2.7.6 to trunk.

Location:
python/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • python/trunk

  • python/trunk/Modules/_elementtree.c

    r2 r391  
    11/*
    22 * ElementTree
    3  * $Id: _elementtree.c 2657 2006-03-12 20:50:32Z fredrik $
     3 * $Id: _elementtree.c 3473 2009-01-11 22:53:55Z fredrik $
    44 *
    55 * elementtree accelerator
     
    88 * 1999-06-20 fl  created (as part of sgmlop)
    99 * 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
    1210 * 2003-02-27 fl  elementtree edition (alpha)
    1311 * 2004-06-03 fl  updates for elementtree 1.2
    14  * 2005-01-05 fl  added universal name cache, Element/SubElement factories
    15  * 2005-01-06 fl  moved python helpers into C module; removed 1.5.2 support
    16  * 2005-01-07 fl  added 2.1 support; work around broken __copy__ in 2.3
    17  * 2005-01-08 fl  added makeelement method; fixed path support
    18  * 2005-01-10 fl  optimized memory usage
     12 * 2005-01-05 fl  major optimization effort
    1913 * 2005-01-11 fl  first public release (cElementTree 0.8)
    2014 * 2005-01-12 fl  split element object into base and extras
     
    3630 * 2006-03-08 fl  fixed a couple of potential null-refs and leaks
    3731 * 2006-03-12 fl  merge in 2.5 ssize_t changes
     32 * 2007-08-25 fl  call custom builder's close method from XMLParser
     33 * 2007-08-31 fl  added iter, extend from ET 1.3
     34 * 2007-09-01 fl  fixed ParseError exception, setslice source type, etc
     35 * 2007-09-03 fl  fixed handling of negative insert indexes
     36 * 2007-09-04 fl  added itertext from ET 1.3
     37 * 2007-09-06 fl  added position attribute to ParseError exception
     38 * 2008-06-06 fl  delay error reporting in iterparse (from Hrvoje Niksic)
    3839 *
    39  * Copyright (c) 1999-2006 by Secret Labs AB.  All rights reserved.
    40  * Copyright (c) 1999-2006 by Fredrik Lundh.
     40 * Copyright (c) 1999-2009 by Secret Labs AB.  All rights reserved.
     41 * Copyright (c) 1999-2009 by Fredrik Lundh.
    4142 *
    4243 * info@pythonware.com
     
    4546
    4647/* Licensed to PSF under a Contributor Agreement. */
    47 /* See http://www.python.org/2.4/license for licensing details. */
     48/* See http://www.python.org/psf/license for licensing details. */
    4849
    4950#include "Python.h"
     
    5758#define USE_EXPAT
    5859
    59 /* Define to to all expat calls via pyexpat's embedded expat library */
     60/* Define to do all expat calls via pyexpat's embedded expat library */
    6061/* #define USE_PYEXPAT_CAPI */
    6162
     
    9596
    9697/* 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
    97103#if (PY_VERSION_HEX < 0x02050000)
    98104typedef int Py_ssize_t;
     
    102108#if (PY_VERSION_HEX < 0x02040000)
    103109#define PyDict_CheckExact PyDict_Check
    104 #if (PY_VERSION_HEX < 0x02020000)
    105 #define PyList_CheckExact PyList_Check
    106 #define PyString_CheckExact PyString_Check
    107 #if (PY_VERSION_HEX >= 0x01060000)
    108 #define Py_USING_UNICODE /* always enabled for 2.0 and 2.1 */
    109 #endif
    110 #endif
    111 #endif
    112110
    113111#if !defined(Py_RETURN_NONE)
    114112#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
     113#endif
    115114#endif
    116115
     
    124123
    125124/* glue functions (see the init function for details) */
     125static PyObject* elementtree_parseerror_obj;
    126126static PyObject* elementtree_copyelement_obj;
    127127static PyObject* elementtree_deepcopy_obj;
    128 static PyObject* elementtree_getiterator_obj;
     128static PyObject* elementtree_iter_obj;
     129static PyObject* elementtree_itertext_obj;
    129130static PyObject* elementpath_obj;
    130131
     
    210211}
    211212
    212 #if (PY_VERSION_HEX < 0x02020000)
    213 LOCAL(int)
    214 PyDict_Update(PyObject* dict, PyObject* other)
    215 {
    216     /* PyDict_Update emulation for 2.1 and earlier */
    217 
    218     PyObject* res;
    219    
    220     res = PyObject_CallMethod(dict, "update", "O", other);
    221     if (!res)
    222         return -1;
    223 
    224     Py_DECREF(res);
    225     return 0;
    226 }
    227 #endif
    228 
    229213/* -------------------------------------------------------------------- */
    230214/* the element type */
     
    331315            PyObject_Del(self);
    332316            return NULL;
    333         }
     317        }
    334318
    335319        self->extra->length = 0;
     
    429413
    430414    if (res == Py_None) {
     415        Py_DECREF(res);
    431416        /* create missing dictionary */
    432417        res = PyDict_New();
     
    710695    /* add object to memo dictionary (so deepcopy won't visit it again) */
    711696    id = PyInt_FromLong((Py_uintptr_t) self);
     697    if (!id)
     698        goto error;
    712699
    713700    i = PyDict_SetItem(memo, id, (PyObject*) element);
     
    733720    /* check if a tag contains an xpath character */
    734721
    735 #define PATHCHAR(ch) (ch == '/' || ch == '*' || ch == '[' || ch == '@')
     722#define PATHCHAR(ch) \
     723    (ch == '/' || ch == '*' || ch == '[' || ch == '@' || ch == '.')
    736724
    737725#if defined(Py_USING_UNICODE)
     
    766754
    767755static PyObject*
     756element_extend(ElementObject* self, PyObject* args)
     757{
     758    PyObject* seq;
     759    Py_ssize_t i, seqlen = 0;
     760
     761    PyObject* seq_in;
     762    if (!PyArg_ParseTuple(args, "O:extend", &seq_in))
     763        return NULL;
     764
     765    seq = PySequence_Fast(seq_in, "");
     766    if (!seq) {
     767        PyErr_Format(
     768            PyExc_TypeError,
     769            "expected sequence, not \"%.200s\"", Py_TYPE(seq_in)->tp_name
     770            );
     771        return NULL;
     772    }
     773
     774    seqlen = PySequence_Size(seq);
     775    for (i = 0; i < seqlen; i++) {
     776        PyObject* element = PySequence_Fast_GET_ITEM(seq, i);
     777        if (element_add_subelement(self, element) < 0) {
     778            Py_DECREF(seq);
     779            return NULL;
     780        }
     781    }
     782
     783    Py_DECREF(seq);
     784
     785    Py_RETURN_NONE;
     786}
     787
     788static PyObject*
    768789element_find(ElementObject* self, PyObject* args)
    769790{
     
    771792
    772793    PyObject* tag;
    773     if (!PyArg_ParseTuple(args, "O:find", &tag))
    774         return NULL;
    775 
    776     if (checkpath(tag))
     794    PyObject* namespaces = Py_None;
     795    if (!PyArg_ParseTuple(args, "O|O:find", &tag, &namespaces))
     796        return NULL;
     797
     798    if (checkpath(tag) || namespaces != Py_None)
    777799        return PyObject_CallMethod(
    778             elementpath_obj, "find", "OO", self, tag
     800            elementpath_obj, "find", "OOO", self, tag, namespaces
    779801            );
    780802
     
    801823    PyObject* tag;
    802824    PyObject* default_value = Py_None;
    803     if (!PyArg_ParseTuple(args, "O|O:findtext", &tag, &default_value))
    804         return NULL;
    805 
    806     if (checkpath(tag))
     825    PyObject* namespaces = Py_None;
     826    if (!PyArg_ParseTuple(args, "O|OO:findtext", &tag, &default_value, &namespaces))
     827        return NULL;
     828
     829    if (checkpath(tag) || namespaces != Py_None)
    807830        return PyObject_CallMethod(
    808             elementpath_obj, "findtext", "OOO", self, tag, default_value
     831            elementpath_obj, "findtext", "OOOO", self, tag, default_value, namespaces
    809832            );
    810833
     
    836859
    837860    PyObject* tag;
    838     if (!PyArg_ParseTuple(args, "O:findall", &tag))
    839         return NULL;
    840 
    841     if (checkpath(tag))
     861    PyObject* namespaces = Py_None;
     862    if (!PyArg_ParseTuple(args, "O|O:findall", &tag, &namespaces))
     863        return NULL;
     864
     865    if (checkpath(tag) || namespaces != Py_None)
    842866        return PyObject_CallMethod(
    843             elementpath_obj, "findall", "OO", self, tag
     867            elementpath_obj, "findall", "OOO", self, tag, namespaces
    844868            );
    845869
     
    866890
    867891static PyObject*
     892element_iterfind(ElementObject* self, PyObject* args)
     893{
     894    PyObject* tag;
     895    PyObject* namespaces = Py_None;
     896    if (!PyArg_ParseTuple(args, "O|O:iterfind", &tag, &namespaces))
     897        return NULL;
     898
     899    return PyObject_CallMethod(
     900        elementpath_obj, "iterfind", "OOO", self, tag, namespaces
     901        );
     902}
     903
     904static PyObject*
    868905element_get(ElementObject* self, PyObject* args)
    869906{
     
    893930    PyObject* list;
    894931
     932    /* FIXME: report as deprecated? */
     933
    895934    if (!PyArg_ParseTuple(args, ":getchildren"))
    896935        return NULL;
     
    913952
    914953static PyObject*
    915 element_getiterator(ElementObject* self, PyObject* args)
     954element_iter(ElementObject* self, PyObject* args)
    916955{
    917956    PyObject* result;
    918957   
    919958    PyObject* tag = Py_None;
    920     if (!PyArg_ParseTuple(args, "|O:getiterator", &tag))
    921         return NULL;
    922 
    923     if (!elementtree_getiterator_obj) {
     959    if (!PyArg_ParseTuple(args, "|O:iter", &tag))
     960        return NULL;
     961
     962    if (!elementtree_iter_obj) {
    924963        PyErr_SetString(
    925964            PyExc_RuntimeError,
    926             "getiterator helper not found"
     965            "iter helper not found"
    927966            );
    928967        return NULL;
     
    936975    Py_INCREF(tag);  PyTuple_SET_ITEM(args, 1, (PyObject*) tag);
    937976
    938     result = PyObject_CallObject(elementtree_getiterator_obj, args);
     977    result = PyObject_CallObject(elementtree_iter_obj, args);
     978
     979    Py_DECREF(args);
     980
     981    return result;
     982}
     983
     984
     985static PyObject*
     986element_itertext(ElementObject* self, PyObject* args)
     987{
     988    PyObject* result;
     989   
     990    if (!PyArg_ParseTuple(args, ":itertext"))
     991        return NULL;
     992
     993    if (!elementtree_itertext_obj) {
     994        PyErr_SetString(
     995            PyExc_RuntimeError,
     996            "itertext helper not found"
     997            );
     998        return NULL;
     999    }
     1000
     1001    args = PyTuple_New(1);
     1002    if (!args)
     1003        return NULL;
     1004
     1005    Py_INCREF(self); PyTuple_SET_ITEM(args, 0, (PyObject*) self);
     1006
     1007    result = PyObject_CallObject(elementtree_itertext_obj, args);
    9391008
    9401009    Py_DECREF(args);
     
    9611030
    9621031static PyObject*
    963 element_getslice(PyObject* self_, Py_ssize_t start, Py_ssize_t end)
    964 {
    965     ElementObject* self = (ElementObject*) self_;
    966     Py_ssize_t i;
    967     PyObject* list;
    968 
    969     if (!self->extra)
    970         return PyList_New(0);
    971 
    972     /* standard clamping */
    973     if (start < 0)
    974         start = 0;
    975     if (end < 0)
    976         end = 0;
    977     if (end > self->extra->length)
    978         end = self->extra->length;
    979     if (start > end)
    980         start = end;
    981 
    982     list = PyList_New(end - start);
    983     if (!list)
    984         return NULL;
    985 
    986     for (i = start; i < end; i++) {
    987         PyObject* item = self->extra->children[i];
    988         Py_INCREF(item);
    989         PyList_SET_ITEM(list, i - start, item);
    990     }
    991 
    992     return list;
    993 }
    994 
    995 static PyObject*
    9961032element_insert(ElementObject* self, PyObject* args)
    9971033{
     
    10071043        element_new_extra(self, NULL);
    10081044
    1009     if (index < 0)
    1010         index = 0;
     1045    if (index < 0) {
     1046        index += self->extra->length;
     1047        if (index < 0)
     1048            index = 0;
     1049    }
    10111050    if (index > self->extra->length)
    10121051        index = self->extra->length;
     
    11521191element_repr(ElementObject* self)
    11531192{
    1154     PyObject* repr;
    1155     char buffer[100];
    1156    
    1157     repr = PyString_FromString("<Element ");
    1158 
    1159     PyString_ConcatAndDel(&repr, PyObject_Repr(self->tag));
    1160 
    1161     sprintf(buffer, " at %p>", self);
    1162     PyString_ConcatAndDel(&repr, PyString_FromString(buffer));
     1193    PyObject *repr, *tag;
     1194
     1195    tag = PyObject_Repr(self->tag);
     1196    if (!tag)
     1197        return NULL;
     1198
     1199    repr = PyString_FromFormat("<Element %s at %p>",
     1200                               PyString_AS_STRING(tag), self);
     1201
     1202    Py_DECREF(tag);
    11631203
    11641204    return repr;
     
    11861226
    11871227    Py_RETURN_NONE;
    1188 }
    1189 
    1190 static int
    1191 element_setslice(PyObject* self_, Py_ssize_t start, Py_ssize_t end, PyObject* item)
    1192 {
    1193     ElementObject* self = (ElementObject*) self_;
    1194     Py_ssize_t i, new, old;
    1195     PyObject* recycle = NULL;
    1196 
    1197     if (!self->extra)
    1198         element_new_extra(self, NULL);
    1199 
    1200     /* standard clamping */
    1201     if (start < 0)
    1202         start = 0;
    1203     if (end < 0)
    1204         end = 0;
    1205     if (end > self->extra->length)
    1206         end = self->extra->length;
    1207     if (start > end)
    1208         start = end;
    1209 
    1210     old = end - start;
    1211 
    1212     if (item == NULL)
    1213         new = 0;
    1214     else if (PyList_CheckExact(item)) {
    1215         new = PyList_GET_SIZE(item);
    1216     } else {
    1217         /* FIXME: support arbitrary sequences? */
    1218         PyErr_Format(
    1219             PyExc_TypeError,
    1220             "expected list, not \"%.200s\"", Py_TYPE(item)->tp_name
    1221             );
    1222         return -1;
    1223     }
    1224 
    1225     if (old > 0) {
    1226         /* to avoid recursive calls to this method (via decref), move
    1227            old items to the recycle bin here, and get rid of them when
    1228            we're done modifying the element */
    1229         recycle = PyList_New(old);
    1230         for (i = 0; i < old; i++)
    1231             PyList_SET_ITEM(recycle, i, self->extra->children[i + start]);
    1232     }
    1233 
    1234     if (new < old) {
    1235         /* delete slice */
    1236         for (i = end; i < self->extra->length; i++)
    1237             self->extra->children[i + new - old] = self->extra->children[i];
    1238     } else if (new > old) {
    1239         /* insert slice */
    1240         if (element_resize(self, new - old) < 0)
    1241             return -1;
    1242         for (i = self->extra->length-1; i >= end; i--)
    1243             self->extra->children[i + new - old] = self->extra->children[i];
    1244     }
    1245 
    1246     /* replace the slice */
    1247     for (i = 0; i < new; i++) {
    1248         PyObject* element = PyList_GET_ITEM(item, i);
    1249         Py_INCREF(element);
    1250         self->extra->children[i + start] = element;
    1251     }
    1252 
    1253     self->extra->length += new - old;
    1254 
    1255     /* discard the recycle bin, and everything in it */
    1256     Py_XDECREF(recycle);
    1257 
    1258     return 0;
    12591228}
    12601229
     
    12891258}
    12901259
     1260static PyObject*
     1261element_subscr(PyObject* self_, PyObject* item)
     1262{
     1263    ElementObject* self = (ElementObject*) self_;
     1264
     1265#if (PY_VERSION_HEX < 0x02050000)
     1266    if (PyInt_Check(item) || PyLong_Check(item)) {
     1267        long i = PyInt_AsLong(item);
     1268#else
     1269    if (PyIndex_Check(item)) {
     1270        Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
     1271#endif
     1272
     1273        if (i == -1 && PyErr_Occurred()) {
     1274            return NULL;
     1275        }
     1276        if (i < 0 && self->extra)
     1277            i += self->extra->length;
     1278        return element_getitem(self_, i);
     1279    }
     1280    else if (PySlice_Check(item)) {
     1281        Py_ssize_t start, stop, step, slicelen, cur, i;
     1282        PyObject* list;
     1283
     1284        if (!self->extra)
     1285            return PyList_New(0);
     1286
     1287        if (PySlice_GetIndicesEx((PySliceObject *)item,
     1288                self->extra->length,
     1289                &start, &stop, &step, &slicelen) < 0) {
     1290            return NULL;
     1291        }
     1292
     1293        if (slicelen <= 0)
     1294            return PyList_New(0);
     1295        else {
     1296            list = PyList_New(slicelen);
     1297            if (!list)
     1298                return NULL;
     1299
     1300            for (cur = start, i = 0; i < slicelen;
     1301                 cur += step, i++) {
     1302                PyObject* item = self->extra->children[cur];
     1303                Py_INCREF(item);
     1304                PyList_SET_ITEM(list, i, item);
     1305            }
     1306
     1307            return list;
     1308        }
     1309    }
     1310    else {
     1311        PyErr_SetString(PyExc_TypeError,
     1312                "element indices must be integers");
     1313        return NULL;
     1314    }
     1315}
     1316
     1317static int
     1318element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
     1319{
     1320    ElementObject* self = (ElementObject*) self_;
     1321
     1322#if (PY_VERSION_HEX < 0x02050000)
     1323    if (PyInt_Check(item) || PyLong_Check(item)) {
     1324        long i = PyInt_AsLong(item);
     1325#else
     1326    if (PyIndex_Check(item)) {
     1327        Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
     1328#endif
     1329
     1330        if (i == -1 && PyErr_Occurred()) {
     1331            return -1;
     1332        }
     1333        if (i < 0 && self->extra)
     1334            i += self->extra->length;
     1335        return element_setitem(self_, i, value);
     1336    }
     1337    else if (PySlice_Check(item)) {
     1338        Py_ssize_t start, stop, step, slicelen, newlen, cur, i;
     1339
     1340        PyObject* recycle = NULL;
     1341        PyObject* seq = NULL;
     1342
     1343        if (!self->extra)
     1344            element_new_extra(self, NULL);
     1345
     1346        if (PySlice_GetIndicesEx((PySliceObject *)item,
     1347                self->extra->length,
     1348                &start, &stop, &step, &slicelen) < 0) {
     1349            return -1;
     1350        }
     1351
     1352        if (value == NULL)
     1353            newlen = 0;
     1354        else {
     1355            seq = PySequence_Fast(value, "");
     1356            if (!seq) {
     1357                PyErr_Format(
     1358                    PyExc_TypeError,
     1359                    "expected sequence, not \"%.200s\"", Py_TYPE(value)->tp_name
     1360                    );
     1361                return -1;
     1362            }
     1363            newlen = PySequence_Size(seq);
     1364        }
     1365
     1366        if (step !=  1 && newlen != slicelen)
     1367        {
     1368            PyErr_Format(PyExc_ValueError,
     1369#if (PY_VERSION_HEX < 0x02050000)
     1370                "attempt to assign sequence of size %d "
     1371                "to extended slice of size %d",
     1372#else
     1373                "attempt to assign sequence of size %zd "
     1374                "to extended slice of size %zd",
     1375#endif
     1376                newlen, slicelen
     1377                );
     1378            return -1;
     1379        }
     1380
     1381
     1382        /* Resize before creating the recycle bin, to prevent refleaks. */
     1383        if (newlen > slicelen) {
     1384            if (element_resize(self, newlen - slicelen) < 0) {
     1385                if (seq) {
     1386                    Py_DECREF(seq);
     1387                }
     1388                return -1;
     1389            }
     1390        }
     1391
     1392        if (slicelen > 0) {
     1393            /* to avoid recursive calls to this method (via decref), move
     1394               old items to the recycle bin here, and get rid of them when
     1395               we're done modifying the element */
     1396            recycle = PyList_New(slicelen);
     1397            if (!recycle) {
     1398                if (seq) {
     1399                    Py_DECREF(seq);
     1400                }
     1401                return -1;
     1402            }
     1403            for (cur = start, i = 0; i < slicelen;
     1404                 cur += step, i++)
     1405                PyList_SET_ITEM(recycle, i, self->extra->children[cur]);
     1406        }
     1407
     1408        if (newlen < slicelen) {
     1409            /* delete slice */
     1410            for (i = stop; i < self->extra->length; i++)
     1411                self->extra->children[i + newlen - slicelen] = self->extra->children[i];
     1412        } else if (newlen > slicelen) {
     1413            /* insert slice */
     1414            for (i = self->extra->length-1; i >= stop; i--)
     1415                self->extra->children[i + newlen - slicelen] = self->extra->children[i];
     1416        }
     1417
     1418        /* replace the slice */
     1419        for (cur = start, i = 0; i < newlen;
     1420             cur += step, i++) {
     1421            PyObject* element = PySequence_Fast_GET_ITEM(seq, i);
     1422            Py_INCREF(element);
     1423            self->extra->children[cur] = element;
     1424        }
     1425
     1426        self->extra->length += newlen - slicelen;
     1427
     1428        if (seq) {
     1429            Py_DECREF(seq);
     1430        }
     1431
     1432        /* discard the recycle bin, and everything in it */
     1433        Py_XDECREF(recycle);
     1434
     1435        return 0;
     1436    }
     1437    else {
     1438        PyErr_SetString(PyExc_TypeError,
     1439                "element indices must be integers");
     1440        return -1;
     1441    }
     1442}
     1443
    12911444static PyMethodDef element_methods[] = {
    12921445
     
    13011454
    13021455    {"append", (PyCFunction) element_append, METH_VARARGS},
     1456    {"extend", (PyCFunction) element_extend, METH_VARARGS},
    13031457    {"insert", (PyCFunction) element_insert, METH_VARARGS},
    13041458    {"remove", (PyCFunction) element_remove, METH_VARARGS},
    13051459
    1306     {"getiterator", (PyCFunction) element_getiterator, METH_VARARGS},
     1460    {"iter", (PyCFunction) element_iter, METH_VARARGS},
     1461    {"itertext", (PyCFunction) element_itertext, METH_VARARGS},
     1462    {"iterfind", (PyCFunction) element_iterfind, METH_VARARGS},
     1463
     1464    {"getiterator", (PyCFunction) element_iter, METH_VARARGS},
    13071465    {"getchildren", (PyCFunction) element_getchildren, METH_VARARGS},
    13081466
     
    13351493    PyObject* res;
    13361494
     1495    /* handle common attributes first */
     1496    if (strcmp(name, "tag") == 0) {
     1497        res = self->tag;
     1498        Py_INCREF(res);
     1499        return res;
     1500    } else if (strcmp(name, "text") == 0) {
     1501        res = element_get_text(self);
     1502        Py_INCREF(res);
     1503        return res;
     1504    }
     1505
     1506    /* methods */
    13371507    res = Py_FindMethod(element_methods, (PyObject*) self, name);
    13381508    if (res)
    1339         return res;
     1509        return res;
    13401510
    13411511    PyErr_Clear();
    13421512
    1343     if (strcmp(name, "tag") == 0)
    1344         res = self->tag;
    1345     else if (strcmp(name, "text") == 0)
    1346         res = element_get_text(self);
    1347     else if (strcmp(name, "tail") == 0) {
     1513    /* less common attributes */
     1514    if (strcmp(name, "tail") == 0) {
    13481515        res = element_get_tail(self);
    13491516    } else if (strcmp(name, "attrib") == 0) {
    13501517        if (!self->extra)
    13511518            element_new_extra(self, NULL);
    1352         res = element_get_attrib(self);
     1519        res = element_get_attrib(self);
    13531520    } else {
    13541521        PyErr_SetString(PyExc_AttributeError, name);
     
    14051572    0, /* sq_repeat */
    14061573    element_getitem,
    1407     element_getslice,
     1574    0,
    14081575    element_setitem,
    1409     element_setslice,
     1576    0,
     1577};
     1578
     1579static PyMappingMethods element_as_mapping = {
     1580    (lenfunc) element_length,
     1581    (binaryfunc) element_subscr,
     1582    (objobjargproc) element_ass_subscr,
    14101583};
    14111584
     
    14221595    0, /* tp_as_number */
    14231596    &element_as_sequence, /* tp_as_sequence */
     1597    &element_as_mapping, /* tp_as_mapping */
    14241598};
    14251599
     
    15591733        if (self->root) {
    15601734            PyErr_SetString(
    1561                 PyExc_SyntaxError,
     1735                elementtree_parseerror_obj,
    15621736                "multiple elements on top level"
    15631737                );
     
    17001874LOCAL(void)
    17011875treebuilder_handle_namespace(TreeBuilderObject* self, int start,
    1702                              const char* prefix, const char *uri)
     1876                             PyObject *prefix, PyObject *uri)
    17031877{
    17041878    PyObject* res;
     
    17131887            return;
    17141888        action = self->start_ns_event_obj;
    1715         /* FIXME: prefix and uri use utf-8 encoding! */
    1716         parcel = Py_BuildValue("ss", (prefix) ? prefix : "", uri);
     1889        parcel = Py_BuildValue("OO", prefix, uri);
    17171890        if (!parcel)
    17181891            return;
     
    18582031
    18592032    PyObject* handle_xml;
     2033
    18602034    PyObject* handle_start;
    18612035    PyObject* handle_data;
     
    18642038    PyObject* handle_comment;
    18652039    PyObject* handle_pi;
     2040
     2041    PyObject* handle_close;
    18662042
    18672043} XMLParserObject;
     
    19722148}
    19732149
     2150static void
     2151expat_set_error(const char* message, int line, int column)
     2152{
     2153    PyObject *error;
     2154    PyObject *position;
     2155    char buffer[256];
     2156
     2157    sprintf(buffer, "%s: line %d, column %d", message, line, column);
     2158
     2159    error = PyObject_CallFunction(elementtree_parseerror_obj, "s", buffer);
     2160    if (!error)
     2161        return;
     2162
     2163    /* add position attribute */
     2164    position = Py_BuildValue("(ii)", line, column);
     2165    if (!position) {
     2166        Py_DECREF(error);
     2167        return;
     2168    }
     2169    if (PyObject_SetAttrString(error, "position", position) == -1) {
     2170        Py_DECREF(error);
     2171        Py_DECREF(position);
     2172        return;
     2173    }
     2174    Py_DECREF(position);
     2175
     2176    PyErr_SetObject(elementtree_parseerror_obj, error);
     2177    Py_DECREF(error);
     2178}
     2179
    19742180/* -------------------------------------------------------------------- */
    19752181/* handlers */
     
    20022208            res = NULL;
    20032209        Py_XDECREF(res);
    2004     } else {
    2005         PyErr_Format(
    2006             PyExc_SyntaxError, "undefined entity &%s;: line %ld, column %ld",
    2007             PyString_AS_STRING(key),
     2210    } else if (!PyErr_Occurred()) {
     2211        /* Report the first error, not the last */
     2212        char message[128];
     2213        sprintf(message, "undefined entity &%.100s;", PyString_AS_STRING(key));
     2214        expat_set_error(
     2215            message,
    20082216            EXPAT(GetErrorLineNumber)(self->parser),
    20092217            EXPAT(GetErrorColumnNumber)(self->parser)
     
    20602268        res = treebuilder_handle_start((TreeBuilderObject*) self->target,
    20612269                                       tag, attrib);
    2062     else if (self->handle_start)
     2270    else if (self->handle_start) {
     2271        if (attrib == Py_None) {
     2272            Py_DECREF(attrib);
     2273            attrib = PyDict_New();
     2274            if (!attrib)
     2275                return;
     2276        }
    20632277        res = PyObject_CallFunction(self->handle_start, "OO", tag, attrib);
    2064     else
     2278    } else
    20652279        res = NULL;
    20662280
     
    21222336                       const XML_Char *uri)
    21232337{
     2338    PyObject* sprefix = NULL;
     2339    PyObject* suri = NULL;
     2340
     2341    suri = makestring(uri, strlen(uri));
     2342    if (!suri)
     2343        return;
     2344
     2345    if (prefix)
     2346        sprefix = makestring(prefix, strlen(prefix));
     2347    else
     2348        sprefix = PyString_FromStringAndSize("", 0);
     2349    if (!sprefix) {
     2350        Py_DECREF(suri);
     2351        return;
     2352    }
     2353
    21242354    treebuilder_handle_namespace(
    2125         (TreeBuilderObject*) self->target, 1, prefix, uri
     2355        (TreeBuilderObject*) self->target, 1, sprefix, suri
    21262356        );
     2357
     2358    Py_DECREF(sprefix);
     2359    Py_DECREF(suri);
    21272360}
    21282361
     
    21952428    if (PyUnicode_GET_SIZE(u) != 256) {
    21962429        Py_DECREF(u);
     2430        PyErr_SetString(PyExc_ValueError,
     2431                        "multi-byte encodings are not supported");
    21972432        return XML_STATUS_ERROR;
    21982433    }
     
    22012436
    22022437    for (i = 0; i < 256; i++) {
    2203         if (p[i] != Py_UNICODE_REPLACEMENT_CHARACTER)
    2204             info->map[i] = p[i];
     2438        if (p[i] != Py_UNICODE_REPLACEMENT_CHARACTER)
     2439            info->map[i] = p[i];
    22052440        else
    2206             info->map[i] = -1;
     2441            info->map[i] = -1;
    22072442    }
    22082443
     
    22892524    self->handle_comment = PyObject_GetAttrString(target, "comment");
    22902525    self->handle_pi = PyObject_GetAttrString(target, "pi");
     2526    self->handle_close = PyObject_GetAttrString(target, "close");
    22912527
    22922528    PyErr_Clear();
     
    23342570    EXPAT(ParserFree)(self->parser);
    23352571
     2572    Py_XDECREF(self->handle_close);
    23362573    Py_XDECREF(self->handle_pi);
    23372574    Py_XDECREF(self->handle_comment);
     
    23642601
    23652602    if (!ok) {
    2366         PyErr_Format(
    2367             PyExc_SyntaxError, "%s: line %ld, column %ld",
     2603        expat_set_error(
    23682604            EXPAT(ErrorString)(EXPAT(GetErrorCode)(self->parser)),
    23692605            EXPAT(GetErrorLineNumber)(self->parser),
     
    23862622
    23872623    res = expat_parse(self, "", 0, 1);
    2388 
    2389     if (res && TreeBuilder_CheckExact(self->target)) {
     2624    if (!res)
     2625        return NULL;
     2626
     2627    if (TreeBuilder_CheckExact(self->target)) {
    23902628        Py_DECREF(res);
    23912629        return treebuilder_done((TreeBuilderObject*) self->target);
    2392     }
    2393 
    2394     return res;
     2630    } if (self->handle_close) {
     2631        Py_DECREF(res);
     2632        return PyObject_CallFunction(self->handle_close, "");
     2633    } else
     2634        return res;
    23952635}
    23962636
     
    25762816    res = Py_FindMethod(xmlparser_methods, (PyObject*) self, name);
    25772817    if (res)
    2578         return res;
     2818        return res;
    25792819
    25802820    PyErr_Clear();
    25812821
    25822822    if (strcmp(name, "entity") == 0)
    2583         res = self->entity;
     2823        res = self->entity;
    25842824    else if (strcmp(name, "target") == 0)
    2585         res = self->target;
     2825        res = self->target;
    25862826    else if (strcmp(name, "version") == 0) {
    25872827        char buffer[100];
     
    26292869    PyObject* g;
    26302870    char* bootstrap;
    2631 #if defined(USE_PYEXPAT_CAPI)
    2632     struct PyExpat_CAPI* capi;
    2633 #endif
    26342871
    26352872    /* Patch object type */
     
    26522889
    26532890    bootstrap = (
    2654 
    2655 #if (PY_VERSION_HEX >= 0x02020000 && PY_VERSION_HEX < 0x02030000)
    2656         "from __future__ import generators\n" /* enable yield under 2.2 */
    2657 #endif
    26582891
    26592892        "from copy import copy, deepcopy\n"
     
    26742907        "    return elem\n"
    26752908
    2676         "def Comment(text=None):\n" /* public */
     2909        "class CommentProxy:\n"
     2910        " def __call__(self, text=None):\n"
    26772911        "  element = cElementTree.Element(ET.Comment)\n"
    26782912        "  element.text = text\n"
    26792913        "  return element\n"
    2680         "cElementTree.Comment = Comment\n"
     2914        " def __cmp__(self, other):\n"
     2915        "  return cmp(ET.Comment, other)\n"
     2916        "cElementTree.Comment = CommentProxy()\n"
    26812917
    26822918        "class ElementTree(ET.ElementTree):\n" /* public */
    26832919        "  def parse(self, source, parser=None):\n"
     2920        "    close_source = False\n"
    26842921        "    if not hasattr(source, 'read'):\n"
    26852922        "      source = open(source, 'rb')\n"
    2686         "    if parser is not None:\n"
    2687         "      while 1:\n"
    2688         "        data = source.read(65536)\n"
    2689         "        if not data:\n"
    2690         "          break\n"
    2691         "        parser.feed(data)\n"
    2692         "      self._root = parser.close()\n"
    2693         "    else:\n"
    2694         "      parser = cElementTree.XMLParser()\n"
    2695         "      self._root = parser._parse(source)\n"
    2696         "    return self._root\n"
     2923        "      close_source = False\n"
     2924        "    try:\n"
     2925        "      if parser is not None:\n"
     2926        "        while 1:\n"
     2927        "          data = source.read(65536)\n"
     2928        "          if not data:\n"
     2929        "            break\n"
     2930        "          parser.feed(data)\n"
     2931        "        self._root = parser.close()\n"
     2932        "      else:\n"
     2933        "        parser = cElementTree.XMLParser()\n"
     2934        "        self._root = parser._parse(source)\n"
     2935        "      return self._root\n"
     2936        "    finally:\n"
     2937        "      if close_source:\n"
     2938        "        source.close()\n"
    26972939        "cElementTree.ElementTree = ElementTree\n"
    26982940
    2699         "def getiterator(node, tag=None):\n" /* helper */
     2941        "def iter(node, tag=None):\n" /* helper */
    27002942        "  if tag == '*':\n"
    27012943        "    tag = None\n"
    2702 #if (PY_VERSION_HEX < 0x02020000)
    2703         "  nodes = []\n" /* 2.1 doesn't have yield */
    2704         "  if tag is None or node.tag == tag:\n"
    2705         "    nodes.append(node)\n"
    2706         "  for node in node:\n"
    2707         "    nodes.extend(getiterator(node, tag))\n"
    2708         "  return nodes\n"
    2709 #else
    27102944        "  if tag is None or node.tag == tag:\n"
    27112945        "    yield node\n"
    27122946        "  for node in node:\n"
    2713         "    for node in getiterator(node, tag):\n"
     2947        "    for node in iter(node, tag):\n"
    27142948        "      yield node\n"
    2715 #endif
     2949
     2950        "def itertext(node):\n" /* helper */
     2951        "  if node.text:\n"
     2952        "    yield node.text\n"
     2953        "  for e in node:\n"
     2954        "    for s in e.itertext():\n"
     2955        "      yield s\n"
     2956        "    if e.tail:\n"
     2957        "      yield e.tail\n"
    27162958
    27172959        "def parse(source, parser=None):\n" /* public */
     
    27212963        "cElementTree.parse = parse\n"
    27222964
    2723 #if (PY_VERSION_HEX < 0x02020000)
    2724         "if hasattr(ET, 'iterparse'):\n"
    2725         "    cElementTree.iterparse = ET.iterparse\n" /* delegate on 2.1 */
    2726 #else
    27272965        "class iterparse(object):\n"
    27282966        " root = None\n"
    27292967        " def __init__(self, file, events=None):\n"
     2968        "  self._close_file = False\n"
    27302969        "  if not hasattr(file, 'read'):\n"
    27312970        "    file = open(file, 'rb')\n"
     2971        "    self._close_file = True\n"
    27322972        "  self._file = file\n"
    2733         "  self._events = events\n"
    2734         " def __iter__(self):\n"
    2735         "  events = []\n"
     2973        "  self._events = []\n"
     2974        "  self._index = 0\n"
     2975        "  self._error = None\n"
     2976        "  self.root = self._root = None\n"
    27362977        "  b = cElementTree.TreeBuilder()\n"
    2737         "  p = cElementTree.XMLParser(b)\n"
    2738         "  p._setevents(events, self._events)\n"
     2978        "  self._parser = cElementTree.XMLParser(b)\n"
     2979        "  self._parser._setevents(self._events, events)\n"
     2980        " def next(self):\n"
    27392981        "  while 1:\n"
     2982        "    try:\n"
     2983        "      item = self._events[self._index]\n"
     2984        "      self._index += 1\n"
     2985        "      return item\n"
     2986        "    except IndexError:\n"
     2987        "      pass\n"
     2988        "    if self._error:\n"
     2989        "      e = self._error\n"
     2990        "      self._error = None\n"
     2991        "      raise e\n"
     2992        "    if self._parser is None:\n"
     2993        "      self.root = self._root\n"
     2994        "      if self._close_file:\n"
     2995        "        self._file.close()\n"
     2996        "      raise StopIteration\n"
     2997        "    # load event buffer\n"
     2998        "    del self._events[:]\n"
     2999        "    self._index = 0\n"
    27403000        "    data = self._file.read(16384)\n"
    2741         "    if not data:\n"
    2742         "      break\n"
    2743         "    p.feed(data)\n"
    2744         "    for event in events:\n"
    2745         "      yield event\n"
    2746         "    del events[:]\n"
    2747         "  root = p.close()\n"
    2748         "  for event in events:\n"
    2749         "    yield event\n"
    2750         "  self.root = root\n"
     3001        "    if data:\n"
     3002        "      try:\n"
     3003        "        self._parser.feed(data)\n"
     3004        "      except SyntaxError as exc:\n"
     3005        "        self._error = exc\n"
     3006        "    else:\n"
     3007        "      self._root = self._parser.close()\n"
     3008        "      self._parser = None\n"
     3009        " def __iter__(self):\n"
     3010        "  return self\n"
    27513011        "cElementTree.iterparse = iterparse\n"
    2752 #endif
    2753 
    2754         "def PI(target, text=None):\n" /* public */
    2755         "  element = cElementTree.Element(ET.ProcessingInstruction)\n"
     3012
     3013        "class PIProxy:\n"
     3014        " def __call__(self, target, text=None):\n"
     3015        "  element = cElementTree.Element(ET.PI)\n"
    27563016        "  element.text = target\n"
    27573017        "  if text:\n"
    27583018        "    element.text = element.text + ' ' + text\n"
    27593019        "  return element\n"
    2760 
    2761         "  elem = cElementTree.Element(ET.PI)\n"
    2762         "  elem.text = text\n"
    2763         "  return elem\n"
    2764         "cElementTree.PI = cElementTree.ProcessingInstruction = PI\n"
     3020        " def __cmp__(self, other):\n"
     3021        "  return cmp(ET.PI, other)\n"
     3022        "cElementTree.PI = cElementTree.ProcessingInstruction = PIProxy()\n"
    27653023
    27663024        "def XML(text):\n" /* public */
     
    27733031        "  tree = XML(text)\n"
    27743032        "  ids = {}\n"
    2775         "  for elem in tree.getiterator():\n"
     3033        "  for elem in tree.iter():\n"
    27763034        "    id = elem.get('id')\n"
    27773035        "    if id:\n"
     
    27803038        "cElementTree.XMLID = XMLID\n"
    27813039
     3040        "try:\n"
     3041        " register_namespace = ET.register_namespace\n"
     3042        "except AttributeError:\n"
     3043        " def register_namespace(prefix, uri):\n"
     3044        "  ET._namespace_map[uri] = prefix\n"
     3045        "cElementTree.register_namespace = register_namespace\n"
     3046
    27823047        "cElementTree.dump = ET.dump\n"
    27833048        "cElementTree.ElementPath = ElementPath = ET.ElementPath\n"
     
    27853050        "cElementTree.QName = ET.QName\n"
    27863051        "cElementTree.tostring = ET.tostring\n"
     3052        "cElementTree.fromstringlist = ET.fromstringlist\n"
     3053        "cElementTree.tostringlist = ET.tostringlist\n"
    27873054        "cElementTree.VERSION = '" VERSION "'\n"
    27883055        "cElementTree.__version__ = '" VERSION "'\n"
    2789         "cElementTree.XMLParserError = SyntaxError\n"
    27903056
    27913057       );
    27923058
    2793     PyRun_String(bootstrap, Py_file_input, g, NULL);
     3059    if (!PyRun_String(bootstrap, Py_file_input, g, NULL))
     3060        return;
    27943061
    27953062    elementpath_obj = PyDict_GetItemString(g, "ElementPath");
     
    28063073    } else
    28073074        PyErr_Clear();
     3075
    28083076    elementtree_deepcopy_obj = PyDict_GetItemString(g, "deepcopy");
    2809     elementtree_getiterator_obj = PyDict_GetItemString(g, "getiterator");
     3077    elementtree_iter_obj = PyDict_GetItemString(g, "iter");
     3078    elementtree_itertext_obj = PyDict_GetItemString(g, "itertext");
    28103079
    28113080#if defined(USE_PYEXPAT_CAPI)
    28123081    /* link against pyexpat, if possible */
    2813     capi = PyCObject_Import("pyexpat", "expat_CAPI");
    2814     if (capi &&
    2815         strcmp(capi->magic, PyExpat_CAPI_MAGIC) == 0 &&
    2816         capi->size <= sizeof(*expat_capi) &&
    2817         capi->MAJOR_VERSION == XML_MAJOR_VERSION &&
    2818         capi->MINOR_VERSION == XML_MINOR_VERSION &&
    2819         capi->MICRO_VERSION == XML_MICRO_VERSION)
    2820         expat_capi = capi;
    2821     else
    2822         expat_capi = NULL;
     3082    expat_capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0);
     3083    if (expat_capi) {
     3084        /* check that it's usable */
     3085        if (strcmp(expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 ||
     3086            expat_capi->size < sizeof(struct PyExpat_CAPI) ||
     3087            expat_capi->MAJOR_VERSION != XML_MAJOR_VERSION ||
     3088            expat_capi->MINOR_VERSION != XML_MINOR_VERSION ||
     3089            expat_capi->MICRO_VERSION != XML_MICRO_VERSION)
     3090            expat_capi = NULL;
     3091    }
    28233092#endif
    28243093
    2825 }
     3094    elementtree_parseerror_obj = PyErr_NewException(
     3095        "cElementTree.ParseError", PyExc_SyntaxError, NULL
     3096        );
     3097    Py_INCREF(elementtree_parseerror_obj);
     3098    PyModule_AddObject(m, "ParseError", elementtree_parseerror_obj);
     3099}
Note: See TracChangeset for help on using the changeset viewer.