[Lxml-checkins] r51473 - in lxml/trunk: . src/lxml src/lxml/tests
scoder at codespeak.net
scoder at codespeak.net
Thu Feb 14 09:19:44 CET 2008
Author: scoder
Date: Thu Feb 14 09:19:43 2008
New Revision: 51473
Modified:
lxml/trunk/ (props changed)
lxml/trunk/src/lxml/lxml.pyclasslookup.pyx
lxml/trunk/src/lxml/tests/test_pyclasslookup.py
Log:
r3497 at delle: sbehnel | 2008-02-14 09:17:23 +0100
iterchildren() method in lxml.pyclasslookup, faster proxy instantiation
Modified: lxml/trunk/src/lxml/lxml.pyclasslookup.pyx
==============================================================================
--- lxml/trunk/src/lxml/lxml.pyclasslookup.pyx (original)
+++ lxml/trunk/src/lxml/lxml.pyclasslookup.pyx Thu Feb 14 09:19:43 2008
@@ -1,9 +1,10 @@
"""
A whole-tree Element class lookup scheme for `lxml.etree`.
-This class lookup scheme allows access to the entire XML tree. To use
-it, let a class inherit from `PythonElementClassLookup` and
-re-implement the ``lookup(self, doc, root)`` method:
+This class lookup scheme allows access to the entire XML tree in
+read-only mode. To use it, let a class inherit from
+`PythonElementClassLookup` and re-implement the ``lookup(self, doc,
+root)`` method:
>>> from lxml import etree, pyclasslookup
>>>
@@ -21,6 +22,15 @@
... # delegate to default
... return None
+Note that the API of the Element objects is not complete. It is
+purely read-only and does not support all features of the normal
+`lxml.etree` API (such as XPath, extended slicing or some iteration
+methods).
+
+Also, you cannot wrap such a read-only Element in an ElementTree, and
+you must take care not to keep a reference to them outside of the
+`lookup()` method.
+
See http://codespeak.net/lxml/element_classes.html
"""
@@ -43,6 +53,7 @@
__version__ = etree.__version__
cdef class _ElementProxy:
+ "The main read-only Element proxy class (for internal use only!)."
cdef tree.xmlNode* _c_node
cdef object _source_proxy
cdef object _dependent_proxies
@@ -157,6 +168,18 @@
def __iter__(self):
return iter(self.getchildren())
+ def iterchildren(self, tag=None, *, reversed=False):
+ """iterchildren(self, tag=None, reversed=False)
+
+ Iterate over the children of this element.
+ """
+ children = self.getchildren()
+ if tag is not None:
+ children = [ el for el in children if el.tag == tag ]
+ if reversed:
+ children = children[::-1]
+ return iter(children)
+
def get(self, key, default=None):
"""Gets an element attribute.
"""
@@ -230,15 +253,21 @@
return _newProxy(self._source_proxy, c_node)
return None
+
+cdef extern from "etree_defs.h":
+ # macro call to 't->tp_new()' for fast instantiation
+ cdef _ElementProxy NEW_PROXY "PY_NEW" (object t)
+
cdef _ElementProxy _newProxy(_ElementProxy sourceProxy, tree.xmlNode* c_node):
cdef _ElementProxy el
- el = _ElementProxy()
+ el = NEW_PROXY(_ElementProxy)
el._c_node = c_node
if sourceProxy is None:
- sourceProxy = el
- el._dependent_proxies = []
- el._source_proxy = sourceProxy
- python.PyList_Append(sourceProxy._dependent_proxies, el)
+ el._source_proxy = el
+ el._dependent_proxies = [el]
+ else:
+ el._source_proxy = sourceProxy
+ python.PyList_Append(sourceProxy._dependent_proxies, el)
return el
cdef _freeProxies(_ElementProxy sourceProxy):
Modified: lxml/trunk/src/lxml/tests/test_pyclasslookup.py
==============================================================================
--- lxml/trunk/src/lxml/tests/test_pyclasslookup.py (original)
+++ lxml/trunk/src/lxml/tests/test_pyclasslookup.py Thu Feb 14 09:19:43 2008
@@ -259,6 +259,43 @@
self.assertEquals([ c.tag for c in root.getchildren() ],
child_tags)
+ def test_lookup_iterchildren(self):
+ el_class = self._buildElementClass()
+ el_class.CHILD_TAGS = None
+ def lookup(doc, el):
+ if el_class.CHILD_TAGS is None:
+ el_class.CHILD_TAGS = [ c.tag for c in el.iterchildren() ]
+ return el_class
+ self._setClassLookup(lookup)
+ root = self.XML(xml_str)
+ child_tags = root.CHILD_TAGS
+ self.assertNotEquals(None, child_tags)
+ self.assertEquals([ c.tag for c in root.getchildren() ],
+ child_tags)
+
+ def test_lookup_iterchildren_tag(self):
+ el_class = self._buildElementClass()
+ el_class.CHILD_TAGS = None
+ def lookup(doc, el):
+ if not el_class.CHILD_TAGS:
+ el_class.CHILD_TAGS = [
+ c.tag for c in el.iterchildren(tag='{objectified}c2') ]
+ return el_class
+ self._setClassLookup(lookup)
+
+ root = self.XML(xml_str)
+ child_tags = root.CHILD_TAGS
+ self.assertNotEquals(None, child_tags)
+ self.assertEquals([], child_tags)
+
+ c1 = root[0]
+ child_tags = root.CHILD_TAGS
+ self.assertNotEquals(None, child_tags)
+ self.assertNotEquals([], child_tags)
+ self.assertEquals(
+ [ c.tag for c in root[0].iterchildren(tag='{objectified}c2') ],
+ child_tags)
+
def test_lookup_getparent(self):
el_class = self._buildElementClass()
el_class.PARENT = None
More information about the lxml-checkins
mailing list