[Lxml-checkins] r51328 - in lxml/trunk: . src/lxml

scoder at codespeak.net scoder at codespeak.net
Fri Feb 8 09:12:38 CET 2008


Author: scoder
Date: Fri Feb  8 09:12:38 2008
New Revision: 51328

Modified:
   lxml/trunk/   (props changed)
   lxml/trunk/src/lxml/lxml.objectify.pyx
Log:
 r3427 at delle:  sbehnel | 2008-02-08 09:11:45 +0100
 rewrite of OE.__setitem__() in objectify: copy all elements *before* setting the slice


Modified: lxml/trunk/src/lxml/lxml.objectify.pyx
==============================================================================
--- lxml/trunk/src/lxml/lxml.objectify.pyx	(original)
+++ lxml/trunk/src/lxml/lxml.objectify.pyx	Fri Feb  8 09:12:38 2008
@@ -269,7 +269,8 @@
 
     def __setitem__(self, key, value):
         """Set the value of a sibling, counting from the first child of the
-        parent.
+        parent.  Implements key assignment, item assignment and slice
+        assignment.
 
         * If argument is an integer, sets the sibling at that position.
 
@@ -280,12 +281,7 @@
           items to the siblings.
         """
         cdef _Element element
-        cdef _Element parent
-        cdef _Element new_element
-        cdef tree.xmlNode* c_self_node
-        cdef tree.xmlNode* c_parent
         cdef tree.xmlNode* c_node
-        cdef Py_ssize_t start, stop, step, slicelength
         if python._isString(key):
             key = _buildChildTag(self, key)
             element = _lookupChild(self, key)
@@ -295,48 +291,21 @@
                 _replaceElement(element, value)
             return
 
-        c_self_node = self._c_node
-        c_parent = c_self_node.parent
-        if c_parent is NULL:
+        if self._c_node.parent is NULL:
             # the 'root[i] = ...' case
             raise TypeError("assignment to root element is invalid")
 
         if python.PySlice_Check(key):
             # slice assignment
-            python.PySlice_GetIndicesEx(
-                key, _countSiblings(self._c_node),
-                &start, &stop, &step, &slicelength)
-            # replace existing items
-            new_items = iter(value)
-            if step < 0:
-                del_items = list(self)[start:stop:step]
-            else:
-                del_items = list(islice(self, start, stop, step))
-            del_items = iter(del_items)
-            parent = self.getparent()
-            try:
-                for el in del_items:
-                    item = new_items.next()
-                    _replaceElement(el, item)
-            except StopIteration:
-                remove = parent.remove
-                remove(el)
-                for el in del_items:
-                    remove(el)
-                return
-            else:
-                # append remaining new items
-                tag = self.tag
-                for item in new_items:
-                    _appendValue(parent, tag, item)
+            _setSlice(key, self, value)
         else:
             # normal index assignment
             if key < 0:
-                c_node = c_parent.last
+                c_node = self._c_node.parent.last
             else:
-                c_node = c_parent.children
+                c_node = self._c_node.parent.children
             c_node = _findFollowingSibling(
-                c_node, tree._getNs(c_self_node), c_self_node.name, key)
+                c_node, tree._getNs(self._c_node), self._c_node.name, key)
             if c_node is NULL:
                 raise IndexError(key)
             element = elementFactory(self._doc, c_node)
@@ -538,6 +507,45 @@
                                           PYTYPE_ATTRIBUTE_NAME)
     cetree.setNodeText(element._c_node, value)
 
+cdef _setSlice(slice, _Element target, items):
+    cdef _Element parent
+    # collect new values
+    new_items = []
+    tag = target.tag
+    for item in items:
+        if isinstance(item, _Element):
+            # deep copy the new element
+            new_element = cetree.deepcopyNodeToDocument(
+                target._doc, (<_Element>item)._c_node)
+            new_element.tag = tag
+            python.PyList_Append(new_items, new_element)
+        else:
+            new_element = cetree.makeElement(
+                tag, target._doc, None, None, None, None, None)
+            _setElementValue(new_element, item)
+            python.PyList_Append(new_items, new_element)
+
+    # replace existing items
+    new_items = iter(new_items)
+    del_items = iter(target[slice])
+    parent = target.getparent()
+    try:
+        next_item = new_items.next
+        replace = parent.replace
+        for el in del_items:
+            item = next_item()
+            replace(el, item)
+    except StopIteration:
+        remove = parent.remove
+        remove(el)
+        for el in del_items:
+            remove(el)
+        return
+    else:
+        # append remaining new items
+        for item in new_items:
+            _appendValue(parent, tag, item)
+
 ################################################################################
 # Data type support in subclasses
 


More information about the lxml-checkins mailing list