Package lxml :: Package tests :: Module test_xpathevaluator

[hide private]
[frames] | no frames]

# Source Code for Module lxml.tests.test_xpathevaluator

      1  # -*- coding: utf-8 -*-
      2
      3  """
      4  Test cases related to XPath evaluation and the XPath class
      5  """
      6
      7  import unittest, sys, os.path
      8
      9  this_dir = os.path.dirname(__file__)
     10  if this_dir not in sys.path:
     11      sys.path.insert(0, this_dir) # needed for Py3
     12
     13  from common_imports import etree, HelperTestCase, _bytes, BytesIO
     14  from common_imports import doctest, make_doctest
     15
     16 -class ETreeXPathTestCase(HelperTestCase):
     17      """XPath tests etree"""
     18
     19 -    def test_xpath_boolean(self):
     20          tree = self.parse('<a><b></b><b></b></a>')
     21          self.assert_(tree.xpath('boolean(/a/b)'))
     22          self.assert_(not tree.xpath('boolean(/a/c)'))
     23
     24 -    def test_xpath_number(self):
     25          tree = self.parse('<a>1</a>')
     26          self.assertEquals(1.,
     27                            tree.xpath('number(/a)'))
     28          tree = self.parse('<a>A</a>')
     29          actual = str(tree.xpath('number(/a)'))
     30          expected = ['nan', '1.#qnan', 'nanq']
     31          if not actual.lower() in expected:
     32              self.fail('Expected a NAN value, got %s' % actual)
     33
     34 -    def test_xpath_string(self):
     35          tree = self.parse('<a>Foo</a>')
     36          self.assertEquals('Foo',
     37                            tree.xpath('string(/a/text())'))
     38
     39 -    def test_xpath_document_root(self):
     40          tree = self.parse('<a><b/></a>')
     41          self.assertEquals([],
     42                            tree.xpath('/'))
     43
     44 -    def test_xpath_namespace(self):
     45          tree = self.parse('<a xmlns="test" xmlns:p="myURI"/>')
     46          self.assert_((None, "test") in tree.xpath('namespace::*'))
     47          self.assert_(('p', 'myURI') in tree.xpath('namespace::*'))
     48
     49 -    def test_xpath_namespace_empty(self):
     50          tree = self.parse('<a/>')
     51          self.assertEquals([('xml', 'http://www.w3.org/XML/1998/namespace')],
     52                            tree.xpath('namespace::*'))
     53
     54 -    def test_xpath_list_elements(self):
     55          tree = self.parse('<a><b>Foo</b><b>Bar</b></a>')
     56          root = tree.getroot()
     57          self.assertEquals([root[0], root[1]],
     58                            tree.xpath('/a/b'))
     59
     60 -    def test_xpath_list_nothing(self):
     61          tree = self.parse('<a><b/></a>')
     62          self.assertEquals([],
     63                            tree.xpath('/a/c'))
     64          # this seems to pass a different code path, also should return nothing
     65          self.assertEquals([],
     66                            tree.xpath('/a/c/text()'))
     67
     68 -    def test_xpath_list_text(self):
     69          tree = self.parse('<a><b>Foo</b><b>Bar</b></a>')
     70          root = tree.getroot()
     71          self.assertEquals(['Foo', 'Bar'],
     72                            tree.xpath('/a/b/text()'))
     73
     74 -    def test_xpath_list_text_parent(self):
     75          tree = self.parse('<a><b>FooBar</b><b>BarFoo</b></a>')
     76          root = tree.getroot()
     77          self.assertEquals(['FooBar', 'BarFoo'],
     78                            tree.xpath('/a/b/text()'))
     79          self.assertEquals([root[0], root[1]],
     80                            [r.getparent() for r in tree.xpath('/a/b/text()')])
     81
     82 -    def test_xpath_list_text_parent_no_smart_strings(self):
     83          tree = self.parse('<a><b>FooBar</b><b>BarFoo</b></a>')
     84          root = tree.getroot()
     85          self.assertEquals(['FooBar', 'BarFoo'],
     86                            tree.xpath('/a/b/text()', smart_strings=True))
     87          self.assertEquals([root[0], root[1]],
     88                            [r.getparent() for r in
     89                             tree.xpath('/a/b/text()', smart_strings=True)])
     90
     91          self.assertEquals(['FooBar', 'BarFoo'],
     92                            tree.xpath('/a/b/text()', smart_strings=False))
     93          self.assertEquals([False, False],
     94                            [hasattr(r, 'getparent') for r in
     95                             tree.xpath('/a/b/text()', smart_strings=False)])
     96
     97 -    def test_xpath_list_unicode_text_parent(self):
     98          xml = _bytes('<a><b>FooBar\\u0680\\u3120</b><b>BarFoo\\u0680\\u3120</b></a>').decode("unicode_escape")
     99          tree = self.parse(xml.encode('utf-8'))
    100          root = tree.getroot()
    101          self.assertEquals([_bytes('FooBar\\u0680\\u3120').decode("unicode_escape"),
    102                             _bytes('BarFoo\\u0680\\u3120').decode("unicode_escape")],
    103                            tree.xpath('/a/b/text()'))
    104          self.assertEquals([root[0], root[1]],
    105                            [r.getparent() for r in tree.xpath('/a/b/text()')])
    106
    107 -    def test_xpath_list_attribute(self):
    108          tree = self.parse('<a b="B" c="C"/>')
    109          self.assertEquals(['B'],
    110                            tree.xpath('/a/@b'))
    111
    112 -    def test_xpath_list_attribute_parent(self):
    113          tree = self.parse('<a b="BaSdFgHjKl" c="CqWeRtZuI"/>')
    114          results = tree.xpath('/a/@c')
    115          self.assertEquals(1, len(results))
    116          self.assertEquals('CqWeRtZuI', results[0])
    117          self.assertEquals(tree.getroot().tag, results[0].getparent().tag)
    118
    119 -    def test_xpath_list_attribute_parent_no_smart_strings(self):
    120          tree = self.parse('<a b="BaSdFgHjKl" c="CqWeRtZuI"/>')
    121
    122          results = tree.xpath('/a/@c', smart_strings=True)
    123          self.assertEquals(1, len(results))
    124          self.assertEquals('CqWeRtZuI', results[0])
    125          self.assertEquals(tree.getroot().tag, results[0].getparent().tag)
    126
    127          results = tree.xpath('/a/@c', smart_strings=False)
    128          self.assertEquals(1, len(results))
    129          self.assertEquals('CqWeRtZuI', results[0])
    130          self.assertEquals(False, hasattr(results[0], 'getparent'))
    131
    132 -    def test_xpath_list_comment(self):
    133          tree = self.parse('<a><!-- Foo --></a>')
    134          self.assertEquals(['<!-- Foo -->'],
    135                            list(map(repr, tree.xpath('/a/node()'))))
    136
    137 -    def test_rel_xpath_boolean(self):
    138          root = etree.XML('<a><b><c/></b></a>')
    139          el = root[0]
    140          self.assert_(el.xpath('boolean(c)'))
    141          self.assert_(not el.xpath('boolean(d)'))
    142
    143 -    def test_rel_xpath_list_elements(self):
    144          tree = self.parse('<a><c><b>Foo</b><b>Bar</b></c><c><b>Hey</b></c></a>')
    145          root = tree.getroot()
    146          c = root[0]
    147          self.assertEquals([c[0], c[1]],
    148                            c.xpath('b'))
    149          self.assertEquals([c[0], c[1], root[1][0]],
    150                            c.xpath('//b'))
    151
    152 -    def test_xpath_ns(self):
    153          tree = self.parse('<a xmlns="uri:a"><b></b></a>')
    154          root = tree.getroot()
    155          self.assertEquals(
    156              [root[0]],
    157              tree.xpath('//foo:b', namespaces={'foo': 'uri:a'}))
    158          self.assertEquals(
    159              [],
    160              tree.xpath('//foo:b', namespaces={'foo': 'uri:c'}))
    161          self.assertEquals(
    162              [root[0]],
    163              root.xpath('//baz:b', namespaces={'baz': 'uri:a'}))
    164
    165 -    def test_xpath_ns_none(self):
    166          tree = self.parse('<a xmlns="uri:a"><b></b></a>')
    167          root = tree.getroot()
    168          self.assertRaises(
    169              TypeError,
    170              root.xpath, '//b', namespaces={None: 'uri:a'})
    171
    172 -    def test_xpath_ns_empty(self):
    173          tree = self.parse('<a xmlns="uri:a"><b></b></a>')
    174          root = tree.getroot()
    175          self.assertRaises(
    176              TypeError,
    177              root.xpath, '//b', namespaces={'': 'uri:a'})
    178
    179 -    def test_xpath_error(self):
    180          tree = self.parse('<a/>')
    181          self.assertRaises(etree.XPathEvalError, tree.xpath, '\\fad')
    182
    183 -    def test_xpath_class_error(self):
    184          self.assertRaises(SyntaxError, etree.XPath, '\\fad')
    185          self.assertRaises(etree.XPathSyntaxError, etree.XPath, '\\fad')
    186
    187 -    def test_xpath_prefix_error(self):
    188          tree = self.parse('<a/>')
    189          self.assertRaises(etree.XPathEvalError, tree.xpath, '/fa:d')
    190
    191 -    def test_xpath_class_prefix_error(self):
    192          tree = self.parse('<a/>')
    193          xpath = etree.XPath("/fa:d")
    194          self.assertRaises(etree.XPathEvalError, xpath, tree)
    195
    196 -    def test_elementtree_getpath(self):
    197          a  = etree.Element("a")
    198          b  = etree.SubElement(a, "b")
    199          c  = etree.SubElement(a, "c")
    200          d1 = etree.SubElement(c, "d")
    201          d2 = etree.SubElement(c, "d")
    202
    203          tree = etree.ElementTree(a)
    204          self.assertEqual('/a/c/d',
    205                           tree.getpath(d2)[:6])
    206          self.assertEqual([d2],
    207                           tree.xpath(tree.getpath(d2)))
    208
    209 -    def test_elementtree_getpath_partial(self):
    210          a  = etree.Element("a")
    211          b  = etree.SubElement(a, "b")
    212          c  = etree.SubElement(a, "c")
    213          d1 = etree.SubElement(c, "d")
    214          d2 = etree.SubElement(c, "d")
    215
    216          tree = etree.ElementTree(c)
    217          self.assertEqual('/c/d',
    218                           tree.getpath(d2)[:4])
    219          self.assertEqual([d2],
    220                           tree.xpath(tree.getpath(d2)))
    221
    222 -    def test_xpath_evaluator(self):
    223          tree = self.parse('<a><b><c></c></b></a>')
    224          e = etree.XPathEvaluator(tree)
    225          root = tree.getroot()
    226          self.assertEquals(
    227              [root],
    228              e('//a'))
    229
    230 -    def test_xpath_evaluator_tree(self):
    231          tree = self.parse('<a><b><c></c></b></a>')
    232          child_tree = etree.ElementTree(tree.getroot()[0])
    233          e = etree.XPathEvaluator(child_tree)
    234          self.assertEquals(
    235              [],
    236              e('a'))
    237          root = child_tree.getroot()
    238          self.assertEquals(
    239              [root[0]],
    240              e('c'))
    241
    242 -    def test_xpath_evaluator_tree_absolute(self):
    243          tree = self.parse('<a><b><c></c></b></a>')
    244          child_tree = etree.ElementTree(tree.getroot()[0])
    245          e = etree.XPathEvaluator(child_tree)
    246          self.assertEquals(
    247              [],
    248              e('/a'))
    249          root = child_tree.getroot()
    250          self.assertEquals(
    251              [root],
    252              e('/b'))
    253          self.assertEquals(
    254              [],
    255              e('/c'))
    256
    257 -    def test_xpath_evaluator_element(self):
    258          tree = self.parse('<a><b><c></c></b></a>')
    259          root = tree.getroot()
    260          e = etree.XPathEvaluator(root[0])
    261          self.assertEquals(
    262              [root[0][0]],
    263              e('c'))
    264
    265 -    def test_xpath_extensions(self):
    266          def foo(evaluator, a):
    267              return 'hello %s' % a
    268          extension = {(None, 'foo'): foo}
    269          tree = self.parse('<a><b></b></a>')
    270          e = etree.XPathEvaluator(tree, extensions=[extension])
    271          self.assertEquals(
    272              "hello you", e("foo('you')"))
    273
    274 -    def test_xpath_extensions_wrong_args(self):
    275          def foo(evaluator, a, b):
    276              return "hello %s and %s" % (a, b)
    277          extension = {(None, 'foo'): foo}
    278          tree = self.parse('<a><b></b></a>')
    279          e = etree.XPathEvaluator(tree, extensions=[extension])
    280          self.assertRaises(TypeError, e, "foo('you')")
    281
    282 -    def test_xpath_extensions_error(self):
    283          def foo(evaluator, a):
    284              return 1/0
    285          extension = {(None, 'foo'): foo}
    286          tree = self.parse('<a/>')
    287          e = etree.XPathEvaluator(tree, extensions=[extension])
    288          self.assertRaises(ZeroDivisionError, e, "foo('test')")
    289
    290 -    def test_xpath_extensions_nodes(self):
    291          def f(evaluator, arg):
    292              r = etree.Element('results')
    293              b = etree.SubElement(r, 'result')
    294              b.text = 'Hoi'
    295              b = etree.SubElement(r, 'result')
    296              b.text = 'Dag'
    297              return r
    298
    299          x = self.parse('<a/>')
    300          e = etree.XPathEvaluator(x, extensions=[{(None, 'foo'): f}])
    301          r = e("foo('World')/result")
    302          self.assertEquals(2, len(r))
    303          self.assertEquals('Hoi', r[0].text)
    304          self.assertEquals('Dag', r[1].text)
    305
    306 -    def test_xpath_extensions_nodes_append(self):
    307          def f(evaluator, nodes):
    308              r = etree.SubElement(nodes[0], 'results')
    309              b = etree.SubElement(r, 'result')
    310              b.text = 'Hoi'
    311              b = etree.SubElement(r, 'result')
    312              b.text = 'Dag'
    313              return r
    314
    315          x = self.parse('<a/>')
    316          e = etree.XPathEvaluator(x, extensions=[{(None, 'foo'): f}])
    317          r = e("foo(/*)/result")
    318          self.assertEquals(2, len(r))
    319          self.assertEquals('Hoi', r[0].text)
    320          self.assertEquals('Dag', r[1].text)
    321
    322 -    def test_xpath_extensions_nodes_append2(self):
    323          def f(evaluator, nodes):
    324              r = etree.Element('results')
    325              b = etree.SubElement(r, 'result')
    326              b.text = 'Hoi'
    327              b = etree.SubElement(r, 'result')
    328              b.text = 'Dag'
    329              r.append(nodes[0])
    330              return r
    331
    332          x = self.parse('<result>Honk</result>')
    333          e = etree.XPathEvaluator(x, extensions=[{(None, 'foo'): f}])
    334          r = e("foo(/*)/result")
    335          self.assertEquals(3, len(r))
    336          self.assertEquals('Hoi',  r[0].text)
    337          self.assertEquals('Dag',  r[1].text)
    338          self.assertEquals('Honk', r[2].text)
    339
    340 -    def test_xpath_context_node(self):
    341          tree = self.parse('<root><a/><b><c/></b></root>')
    342
    343          check_call = []
    344          def check_context(ctxt, nodes):
    345              self.assertEquals(len(nodes), 1)
    346              check_call.append(nodes[0].tag)
    347              self.assertEquals(ctxt.context_node, nodes[0])
    348              return True
    349
    350          find = etree.XPath("//*[p:foo(.)]",
    351                             namespaces={'p' : 'ns'},
    352                             extensions=[{('ns', 'foo') : check_context}])
    353          find(tree)
    354
    355          check_call.sort()
    356          self.assertEquals(check_call, ["a", "b", "c", "root"])
    357
    358 -    def test_xpath_eval_context_propagation(self):
    359          tree = self.parse('<root><a/><b><c/></b></root>')
    360
    361          check_call = {}
    362          def check_context(ctxt, nodes):
    363              self.assertEquals(len(nodes), 1)
    364              tag = nodes[0].tag
    365              # empty during the "b" call, a "b" during the "c" call
    366              check_call[tag] = ctxt.eval_context.get("b")
    367              ctxt.eval_context[tag] = tag
    368              return True
    369
    370          find = etree.XPath("//b[p:foo(.)]/c[p:foo(.)]",
    371                             namespaces={'p' : 'ns'},
    372                             extensions=[{('ns', 'foo') : check_context}])
    373          result = find(tree)
    374
    375          self.assertEquals(result, [tree.getroot()[1][0]])
    376          self.assertEquals(check_call, {'b':None, 'c':'b'})
    377
    378 -    def test_xpath_eval_context_clear(self):
    379          tree = self.parse('<root><a/><b><c/></b></root>')
    380
    381          check_call = {}
    382          def check_context(ctxt):
    383              check_call["done"] = True
    384              # context must be empty for each new evaluation
    385              self.assertEquals(len(ctxt.eval_context), 0)
    386              ctxt.eval_context["test"] = True
    387              return True
    388
    389          find = etree.XPath("//b[p:foo()]",
    390                             namespaces={'p' : 'ns'},
    391                             extensions=[{('ns', 'foo') : check_context}])
    392          result = find(tree)
    393
    394          self.assertEquals(result, [tree.getroot()[1]])
    395          self.assertEquals(check_call["done"], True)
    396
    397          check_call.clear()
    398          find = etree.XPath("//b[p:foo()]",
    399                             namespaces={'p' : 'ns'},
    400                             extensions=[{('ns', 'foo') : check_context}])
    401          result = find(tree)
    402
    403          self.assertEquals(result, [tree.getroot()[1]])
    404          self.assertEquals(check_call["done"], True)
    405
    406 -    def test_xpath_variables(self):
    407          x = self.parse('<a attr="true"/>')
    408          e = etree.XPathEvaluator(x)
    409
    410          expr = "/a[@attr=$aval]"
    411          r = e(expr, aval=1)
    412          self.assertEquals(0, len(r))
    413
    414          r = e(expr, aval="true")
    415          self.assertEquals(1, len(r))
    416          self.assertEquals("true", r[0].get('attr'))
    417
    418          r = e(expr, aval=True)
    419          self.assertEquals(1, len(r))
    420          self.assertEquals("true", r[0].get('attr'))
    421
    422 -    def test_xpath_variables_nodeset(self):
    423          x = self.parse('<a attr="true"/>')
    424          e = etree.XPathEvaluator(x)
    425
    426          element = etree.Element("test-el")
    427          etree.SubElement(element, "test-sub")
    428          expr = "$value"
    429          r = e(expr, value=element)
    430          self.assertEquals(1, len(r))
    431          self.assertEquals(element.tag, r[0].tag)
    432          self.assertEquals(element[0].tag, r[0][0].tag)
    433
    434 -    def test_xpath_extensions_mix(self):
    435          x = self.parse('<a attr="true"><test/></a>')
    436
    437          class LocalException(Exception):
    438              pass
    439
    440          def foo(evaluator, a, varval):
    441              etree.Element("DUMMY")
    442              if varval == 0:
    443                  raise LocalException
    444              elif varval == 1:
    445                  return ()
    446              elif varval == 2:
    447                  return None
    448              elif varval == 3:
    449                  return a[0][0]
    450              a = a[0]
    451              if a.get("attr") == str(varval):
    452                  return a
    453              else:
    454                  return etree.Element("NODE")
    455
    456          extension = {(None, 'foo'): foo}
    457          e = etree.XPathEvaluator(x, extensions=[extension])
    458          del x
    459
    460          self.assertRaises(LocalException, e, "foo(., 0)")
    461          self.assertRaises(LocalException, e, "foo(., $value)", value=0)
    462
    463          r = e("foo(., $value)", value=1)
    464          self.assertEqual(len(r), 0)
    465
    466          r = e("foo(.,  1)")
    467          self.assertEqual(len(r), 0)
    468
    469          r = e("foo(., $value)", value=2)
    470          self.assertEqual(len(r), 0)
    471
    472          r = e("foo(., $value)", value=3)
    473          self.assertEqual(len(r), 1)
    474          self.assertEqual(r[0].tag, "test")
    475
    476          r = e("foo(., $value)", value="false")
    477          self.assertEqual(len(r), 1)
    478          self.assertEqual(r[0].tag, "NODE")
    479
    480          r = e("foo(., 'false')")
    481          self.assertEqual(len(r), 1)
    482          self.assertEqual(r[0].tag, "NODE")
    483
    484          r = e("foo(., 'true')")
    485          self.assertEqual(len(r), 1)
    486          self.assertEqual(r[0].tag, "a")
    487          self.assertEqual(r[0][0].tag, "test")
    488
    489          r = e("foo(., $value)", value="true")
    490          self.assertEqual(len(r), 1)
    491          self.assertEqual(r[0].tag, "a")
    492
    493          self.assertRaises(LocalException, e, "foo(., 0)")
    494          self.assertRaises(LocalException, e, "foo(., $value)", value=0)
    495
    496
    497 -class ETreeXPathClassTestCase(HelperTestCase):
    498      "Tests for the XPath class"
    499 -    def test_xpath_compile_doc(self):
    500          x = self.parse('<a attr="true"/>')
    501
    502          expr = etree.XPath("/a[@attr != 'true']")
    503          r = expr(x)
    504          self.assertEquals(0, len(r))
    505
    506          expr = etree.XPath("/a[@attr = 'true']")
    507          r = expr(x)
    508          self.assertEquals(1, len(r))
    509
    510          expr = etree.XPath( expr.path )
    511          r = expr(x)
    512          self.assertEquals(1, len(r))
    513
    514 -    def test_xpath_compile_element(self):
    515          x = self.parse('<a><b/><c/></a>')
    516          root = x.getroot()
    517
    518          expr = etree.XPath("./b")
    519          r = expr(root)
    520          self.assertEquals(1, len(r))
    521          self.assertEquals('b', r[0].tag)
    522
    523          expr = etree.XPath("./*")
    524          r = expr(root)
    525          self.assertEquals(2, len(r))
    526
    527 -    def test_xpath_compile_vars(self):
    528          x = self.parse('<a attr="true"/>')
    529
    530          expr = etree.XPath("/a[@attr=$aval]")
    531          r = expr(x, aval=False)
    532          self.assertEquals(0, len(r))
    533
    534          r = expr(x, aval=True)
    535          self.assertEquals(1, len(r))
    536
    537 -    def test_xpath_compile_error(self):
    538          self.assertRaises(SyntaxError, etree.XPath, '\\fad')
    539
    540 -    def test_xpath_elementtree_error(self):
    541          self.assertRaises(ValueError, etree.XPath('*'), etree.ElementTree())
    542
    543 -class ETreeETXPathClassTestCase(HelperTestCase):
    544      "Tests for the ETXPath class"
    545 -    def test_xpath_compile_ns(self):
    546          x = self.parse('<a><b xmlns="nsa"/><b xmlns="nsb"/></a>')
    547
    548          expr = etree.ETXPath("/a/{nsa}b")
    549          r = expr(x)
    550          self.assertEquals(1, len(r))
    551          self.assertEquals('{nsa}b', r[0].tag)
    552
    553          expr = etree.ETXPath("/a/{nsb}b")
    554          r = expr(x)
    555          self.assertEquals(1, len(r))
    556          self.assertEquals('{nsb}b', r[0].tag)
    557
    558 -    def test_xpath_compile_unicode(self):
    559          x = self.parse(_bytes('<a><b xmlns="nsa\\uf8d2"/><b xmlns="nsb\\uf8d1"/></a>'
    560                                ).decode("unicode_escape"))
    561
    562          expr = etree.ETXPath(_bytes("/a/{nsa\\uf8d2}b").decode("unicode_escape"))
    563          r = expr(x)
    564          self.assertEquals(1, len(r))
    565          self.assertEquals(_bytes('{nsa\\uf8d2}b').decode("unicode_escape"), r[0].tag)
    566
    567          expr = etree.ETXPath(_bytes("/a/{nsb\\uf8d1}b").decode("unicode_escape"))
    568          r = expr(x)
    569          self.assertEquals(1, len(r))
    570          self.assertEquals(_bytes('{nsb\\uf8d1}b').decode("unicode_escape"), r[0].tag)
    571
    572  SAMPLE_XML = etree.parse(BytesIO("""
    573  <body>
    574    <tag>text</tag>
    575    <section>
    576      <tag>subtext</tag>
    577    </section>
    578    <tag />
    579    <tag />
    580  </body>
    581  """))
    582
    583 -def tag(elem):
    584      return elem.tag
    585
    586 -def stringTest(ctxt, s1):
    587      return "Hello "+s1
    588
    589 -def floatTest(ctxt, f1):
    590      return f1+4
    591
    592 -def booleanTest(ctxt, b1):
    593      return not b1
    594
    595 -def setTest(ctxt, st1):
    596      return st1[0]
    597
    598 -def setTest2(ctxt, st1):
    599      return st1[0:2]
    600
    601 -def argsTest1(ctxt, s, f, b, st):
    602      return ", ".join(map(str, (s, f, b, list(map(tag, st)))))
    603
    604 -def argsTest2(ctxt, st1, st2):
    605      st1.extend(st2)
    606      return st1
    607
    608 -def resultTypesTest(ctxt):
    609      return ["x","y"]
    610
    611 -def resultTypesTest2(ctxt):
    612      return resultTypesTest
    613
    614  uri = "http://www.example.com/"
    615
    616  extension = {(None, 'stringTest'): stringTest,
    617               (None, 'floatTest'): floatTest,
    618               (None, 'booleanTest'): booleanTest,
    619               (None, 'setTest'): setTest,
    620               (None, 'setTest2'): setTest2,
    621               (None, 'argsTest1'): argsTest1,
    622               (None, 'argsTest2'): argsTest2,
    623               (None, 'resultTypesTest'): resultTypesTest,
    624               (None, 'resultTypesTest2'): resultTypesTest2,}
    625
    626 -def xpath():
    627      """
    628      Test xpath extension functions.
    629
    630      >>> root = SAMPLE_XML
    631      >>> e = etree.XPathEvaluator(root, extensions=[extension])
    632      >>> e("stringTest('you')")
    633      'Hello you'
    634      >>> e(_bytes("stringTest('\\\\xe9lan')").decode("unicode_escape"))
    635      u'Hello \\xe9lan'
    636      >>> e("stringTest('you','there')")
    637      Traceback (most recent call last):
    638      ...
    639      TypeError: stringTest() takes exactly 2 arguments (3 given)
    640      >>> e("floatTest(2)")
    641      6.0
    642      >>> e("booleanTest(true())")
    643      False
    644      >>> list(map(tag, e("setTest(/body/tag)")))
    645      ['tag']
    646      >>> list(map(tag, e("setTest2(/body/*)")))
    647      ['tag', 'section']
    648      >>> e("argsTest1('a',1.5,true(),/body/tag)")
    649      "a, 1.5, True, ['tag', 'tag', 'tag']"
    650      >>> list(map(tag, e("argsTest2(/body/tag, /body/section)")))
    651      ['tag', 'section', 'tag', 'tag']
    652      >>> e("resultTypesTest()")
    653      Traceback (most recent call last):
    654      ...
    655      XPathResultError: This is not a node: 'x'
    656      >>> try:
    657      ...     e("resultTypesTest2()")
    658      ... except etree.XPathResultError:
    659      ...     print("Got error")
    660      Got error
    661      """
    662
    663  if sys.version_info[0] >= 3:
    664      xpath.__doc__ = xpath.__doc__.replace(" u'", " '")
    665      xpath.__doc__ = xpath.__doc__.replace(" XPathResultError",
    666                                            " lxml.etree.XPathResultError")
    667      xpath.__doc__ = xpath.__doc__.replace(" exactly 2 arguments",
    668                                            " exactly 2 positional arguments")
    669
    670 -def test_suite():
    671      suite = unittest.TestSuite()
    672      suite.addTests([unittest.makeSuite(ETreeXPathTestCase)])
    673      suite.addTests([unittest.makeSuite(ETreeXPathClassTestCase)])
    674      suite.addTests([unittest.makeSuite(ETreeETXPathClassTestCase)])
    675      suite.addTests([doctest.DocTestSuite()])
    676      suite.addTests(
    677          [make_doctest('../../../doc/xpathxslt.txt')])
    678      return suite
    679
    680  if __name__ == '__main__':
    681      print('to test use test.py %s' % __file__)
    682