[Lxml-checkins] r47968 - in lxml/trunk: . src/lxml
scoder at codespeak.net
scoder at codespeak.net
Thu Oct 25 19:27:03 CEST 2007
Author: scoder
Date: Thu Oct 25 19:27:03 2007
New Revision: 47968
Modified:
lxml/trunk/CHANGES.txt
lxml/trunk/src/lxml/lxml.objectify.pyx
Log:
extended slicing in objectify
Modified: lxml/trunk/CHANGES.txt
==============================================================================
--- lxml/trunk/CHANGES.txt (original)
+++ lxml/trunk/CHANGES.txt Thu Oct 25 19:27:03 2007
@@ -8,7 +8,8 @@
Features added
--------------
-* Extended slicing of Elements as in ``element[1:-1:2]``
+* Extended slicing of Elements as in ``element[1:-1:2]``, both in
+ etree and in objectify
* Resolvers can now provide a ``base_url`` keyword argument when
resolving a document as string data.
Modified: lxml/trunk/src/lxml/lxml.objectify.pyx
==============================================================================
--- lxml/trunk/src/lxml/lxml.objectify.pyx (original)
+++ lxml/trunk/src/lxml/lxml.objectify.pyx Thu Oct 25 19:27:03 2007
@@ -150,28 +150,7 @@
def __len__(self):
"""Count self and siblings with the same tag.
"""
- cdef tree.xmlNode* c_self_node
- cdef tree.xmlNode* c_node
- cdef char* c_href
- cdef char* c_tag
- cdef Py_ssize_t count
- c_self_node = self._c_node
- c_tag = c_self_node.name
- c_href = tree._getNs(c_self_node)
- count = 1
- c_node = c_self_node.next
- while c_node is not NULL:
- if c_node.type == tree.XML_ELEMENT_NODE and \
- cetree.tagMatches(c_node, c_href, c_tag):
- count = count + 1
- c_node = c_node.next
- c_node = c_self_node.prev
- while c_node is not NULL:
- if c_node.type == tree.XML_ELEMENT_NODE and \
- cetree.tagMatches(c_node, c_href, c_tag):
- count = count + 1
- c_node = c_node.prev
- return count
+ return _countSiblings(self._c_node)
def countchildren(self):
"""Return the number of children of this element, regardless of their
@@ -253,12 +232,24 @@
* If argument is a string, does the same as getattr(). This can be
used to provide namespaces for element lookup, or to look up
children with special names (``text`` etc.).
+
+ * If argument is a slice object, returns the matching slice.
"""
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):
return _lookupChildOrRaise(self, key)
+ elif python.PySlice_Check(key):
+ python.PySlice_GetIndicesEx(
+ key, _countSiblings(self._c_node),
+ &start, &stop, &step, &slicelength)
+ if step < 0:
+ return list(self)[start:stop:step]
+ else:
+ return list(islice(self, start, stop, step))
+ # normal item access
c_self_node = self._c_node
c_parent = c_self_node.parent
if c_parent is NULL:
@@ -289,10 +280,12 @@
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)
@@ -306,59 +299,73 @@
c_parent = c_self_node.parent
if c_parent is NULL:
# the 'root[i] = ...' case
- raise TypeError, "index assignment to root element is invalid"
- if key < 0:
- c_node = c_parent.last
- else:
- c_node = c_parent.children
- c_node = _findFollowingSibling(
- c_node, tree._getNs(c_self_node), c_self_node.name, key)
- if c_node is NULL:
- raise IndexError, key
- element = elementFactory(self._doc, c_node)
- _replaceElement(element, value)
+ raise TypeError, "assignment to root element is invalid"
- def __getslice__(self, Py_ssize_t start, Py_ssize_t end):
- return list(islice(self, start, end))
+ 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)
+ else:
+ # normal index assignment
+ if key < 0:
+ c_node = c_parent.last
+ else:
+ c_node = c_parent.children
+ c_node = _findFollowingSibling(
+ c_node, tree._getNs(c_self_node), c_self_node.name, key)
+ if c_node is NULL:
+ raise IndexError, key
+ element = elementFactory(self._doc, c_node)
+ _replaceElement(element, value)
- def __setslice__(self, Py_ssize_t start, Py_ssize_t end, values):
- cdef _Element el
- parent = self.getparent()
- if parent is None:
- raise TypeError, "deleting slices of root element not supported"
- # replace existing items
- new_items = iter(values)
- del_items = iter(list(islice(self, start, end)))
- try:
- for el in del_items:
- item = new_items.next()
- _replaceElement(el, item)
- except StopIteration:
+ def __delitem__(self, key):
+ cdef Py_ssize_t start, stop, step, slicelength
+ if python.PySlice_Check(key):
+ # slice deletion
+ python.PySlice_GetIndicesEx(
+ key, _countSiblings(self._c_node),
+ &start, &stop, &step, &slicelength)
+ parent = self.getparent()
+ if parent is None:
+ raise TypeError, "deleting slices of root element not supported"
+ if step < 0:
+ del_items = list(self)[start:stop:step]
+ else:
+ del_items = list(islice(self, start, stop, step))
remove = parent.remove
- remove(el)
for el in del_items:
remove(el)
- return
-
- # append remaining new items
- tag = self.tag
- for item in new_items:
- _appendValue(parent, tag, item)
-
- def __delslice__(self, Py_ssize_t start, Py_ssize_t end):
- parent = self.getparent()
- if parent is None:
- raise TypeError, "deleting slices of root element not supported"
- remove = parent.remove
- for el in list(islice(self, start, end)):
- remove(el)
-
- def __delitem__(self, key):
- parent = self.getparent()
- if parent is None:
- raise TypeError, "deleting items not supported by root element"
- sibling = self.__getitem__(key)
- parent.remove(sibling)
+ else:
+ # normal index deletion
+ parent = self.getparent()
+ if parent is None:
+ raise TypeError, "deleting items not supported by root element"
+ sibling = self.__getitem__(key)
+ parent.remove(sibling)
def iterfind(self, path):
# Reimplementation of Element.iterfind() to make it work without child
@@ -399,6 +406,28 @@
prefix = '.'.join(prefix)
return _buildDescendantPaths(self._c_node, prefix)
+cdef Py_ssize_t _countSiblings(tree.xmlNode* c_start_node):
+ cdef tree.xmlNode* c_node
+ cdef char* c_href
+ cdef char* c_tag
+ cdef Py_ssize_t count
+ c_tag = c_start_node.name
+ c_href = tree._getNs(c_start_node)
+ count = 1
+ c_node = c_start_node.next
+ while c_node is not NULL:
+ if c_node.type == tree.XML_ELEMENT_NODE and \
+ cetree.tagMatches(c_node, c_href, c_tag):
+ count = count + 1
+ c_node = c_node.next
+ c_node = c_start_node.prev
+ while c_node is not NULL:
+ if c_node.type == tree.XML_ELEMENT_NODE and \
+ cetree.tagMatches(c_node, c_href, c_tag):
+ count = count + 1
+ c_node = c_node.prev
+ return count
+
cdef tree.xmlNode* _findFollowingSibling(tree.xmlNode* c_node,
char* href, char* name,
Py_ssize_t index):
@@ -460,7 +489,7 @@
element._doc, (<_Element>value)._c_node)
new_element.tag = element.tag
elif python.PyList_Check(value) or python.PyTuple_Check(value):
- element.__setslice__(0, python.PY_SSIZE_T_MAX, value)
+ element[:] = value
return
else:
new_element = element.makeelement(element.tag)
More information about the lxml-checkins
mailing list