[Lxml-checkins] r51341 - in lxml/trunk: . src/lxml
scoder at codespeak.net
scoder at codespeak.net
Fri Feb 8 19:44:12 CET 2008
Author: scoder
Date: Fri Feb 8 19:44:11 2008
New Revision: 51341
Modified:
lxml/trunk/ (props changed)
lxml/trunk/src/lxml/lxml.objectify.pyx
Log:
r3438 at delle: sbehnel | 2008-02-08 19:43:35 +0100
another rewrite of objectify._setSlice() to fix the handling of slice-overlapping elements
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 19:44:11 2008
@@ -503,6 +503,17 @@
cdef _setSlice(slice, _Element target, items):
cdef _Element parent
+ cdef tree.xmlNode* c_node
+ cdef Py_ssize_t c_step, c_start, pos
+ # collect existing slice
+ if (<python.slice>slice).step is None:
+ c_step = 1
+ else:
+ c_step = (<python.slice>slice).step
+ if c_step == 0:
+ raise ValueError("Invalid slice")
+ del_items = target[slice]
+
# collect new values
new_items = []
tag = target.tag
@@ -512,33 +523,58 @@
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)
+ python.PyList_Append(new_items, new_element)
+
+ # sanity check - raise what a list would raise
+ if c_step != 1 and \
+ python.PyList_GET_SIZE(del_items) != python.PyList_GET_SIZE(new_items):
+ raise ValueError(
+ "attempt to assign sequence of size %d to extended slice of size %d" % (
+ python.PyList_GET_SIZE(new_items),
+ python.PyList_GET_SIZE(del_items)))
# replace existing items
- new_items = iter(new_items)
- del_items = iter(target[slice])
+ pos = 0
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:
+ replace = parent.replace
+ while pos < python.PyList_GET_SIZE(new_items) and \
+ pos < python.PyList_GET_SIZE(del_items):
+ replace(del_items[pos], new_items[pos])
+ pos += 1
+ # remove leftover items
+ if pos < python.PyList_GET_SIZE(del_items):
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)
+ while pos < python.PyList_GET_SIZE(del_items):
+ remove(del_items[pos])
+ pos += 1
+ # append remaining new items
+ if pos < python.PyList_GET_SIZE(new_items):
+ # the sanity check above guarantees (step == 1)
+ if pos > 0:
+ item = new_items[pos-1]
+ else:
+ if (<python.slice>slice).start > 0:
+ c_node = parent._c_node.children
+ else:
+ c_node = parent._c_node.last
+ c_node = _findFollowingSibling(
+ c_node, tree._getNs(target._c_node), target._c_node.name,
+ (<python.slice>slice).start - 1)
+ if c_node is NULL:
+ while pos < python.PyList_GET_SIZE(new_items):
+ cetree.appendChild(parent, new_items[pos])
+ pos += 1
+ return
+ item = cetree.elementFactory(parent._doc, c_node)
+ while pos < python.PyList_GET_SIZE(new_items):
+ add = item.addnext
+ item = new_items[pos]
+ add(item)
+ pos += 1
################################################################################
# Data type support in subclasses
More information about the lxml-checkins
mailing list