diff options
author | Jeffrey Yasskin <jyasskin@gmail.com> | 2012-02-15 09:16:35 -0800 |
---|---|---|
committer | Jeffrey Yasskin <jyasskin@gmail.com> | 2012-02-15 09:16:35 -0800 |
commit | ab8e7e8e6089c420c0718ed9c851a158712f2833 (patch) | |
tree | 58e23442b6d3ee5a95d7f420f57d0df9474c6e1a | |
parent | f1959a6a9866598e3ab9ec464f51a5b11e5075c9 (diff) | |
download | python-lxml-ab8e7e8e6089c420c0718ed9c851a158712f2833.tar.gz |
Teach the ElementMaker to add objects of types derived from types it
knows how to handle. This allows it to handle the result of string
xpath expressions, which inherit from bytes.
-rw-r--r-- | src/lxml/builder.py | 12 | ||||
-rw-r--r-- | src/lxml/tests/test_builder.py | 39 |
2 files changed, 49 insertions, 2 deletions
diff --git a/src/lxml/builder.py b/src/lxml/builder.py index c5c25b74..b7fcf406 100644 --- a/src/lxml/builder.py +++ b/src/lxml/builder.py @@ -212,12 +212,20 @@ class ElementMaker(object): for item in children: if callable(item): item = item() - t = get(type(item)) + for basetype in type(item).__mro__: + # __mro__ starts with the type itself, and then + # searches all supertypes. If typemap contains + # object, this will never fall back to appending an + # element. + t = get(basetype) + if t is not None: + break if t is None: if ET.iselement(item): elem.append(item) continue - raise TypeError("bad argument type: %r" % item) + raise TypeError("bad argument type: %s(%r)" % + (type(item).__name__, item)) else: v = t(elem, item) if v: diff --git a/src/lxml/tests/test_builder.py b/src/lxml/tests/test_builder.py new file mode 100644 index 00000000..b3a31488 --- /dev/null +++ b/src/lxml/tests/test_builder.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +import unittest + +""" +Tests that ElementMaker works properly. +""" + +import sys, os.path +from lxml import etree +from lxml.builder import E + +try: + import cStringIO + StringIO = cStringIO.StringIO +except ImportError: + from io import StringIO + +this_dir = os.path.dirname(__file__) +if this_dir not in sys.path: + sys.path.insert(0, this_dir) # needed for Py3 + +from common_imports import HelperTestCase + +class BuilderTestCase(HelperTestCase): + etree = etree + + def test_build_from_xpath_result(self): + elem = etree.parse(StringIO('<root><node>text</node></root>')) + wrapped = E.b(elem.xpath('string(node)')) + self.assertEquals(b'<b>text</b>', etree.tostring(wrapped)) + + +def test_suite(): + suite = unittest.TestSuite() + suite.addTests([unittest.makeSuite(BuilderTestCase)]) + return suite + +if __name__ == '__main__': + print('to test use test.py %s' % __file__) |