#! /usr/bin/env/python # -*- coding: iso-8859-1 -*- ## Copyright 1999-2006 by LivingLogic AG, Bayreuth/Germany. ## Copyright 1999-2006 by Walter Dörwald ## ## All Rights Reserved ## ## See xist/__init__.py for the license import py.test from ll import misc from ll.xist import xsc, xfind, parsers from ll.xist.ns import html def xfindnode(): return xsc.Frag( html.div( html.h1("The ", html.em("important"), " headline"), html.p("The ", html.em("first"), " paragraph."), html.p("The ", html.em("second"), " ", html.em("important"), " paragraph."), align="left", ), html.div( html.h1("The headline"), html.p("The ", html.em("first"), " paragraph."), html.div( html.h2("The ", html.em("important"), " headline"), html.p("The ", html.em("second"), " ", html.em("important"), " paragraph."), id="id42", ), class_="foo", ), ) def test_levels(): def check(expr, ids): assert "".join(str(e["id"]) for e in expr) == ids ds = [html.div(id=id) for id in xrange(8)] ds[1].append(ds[4:7]) ds[2].append(ds[7]) ds[0].append(ds[1:4]) # ____0____ # / | \ # _1_ 2 3 # / | \ | # 4 5 6 7 tests = [ (ds[0]//html.div, "1234567"), (ds[0]/html.div, "123"), (ds[0]/html.div/html.div, "4567"), (ds[0]/html.div/html.div/html.div, ""), (ds[0]//xfind.contains(html.div), "012"), ] for (got, exp) in tests: yield check, got, exp def test_hasattr(): node = xfindnode() res = list(node//xfind.hasattr(html.div.Attrs.id, html.div.Attrs.align)) assert len(res) == 2 assert res[0] is node[0] assert res[1] is node[1][-1] def test_hasattrnamed(): node = xfindnode() res = list(node//xfind.hasattrnamed("class_")) assert len(res) == 1 assert res[0] is node[1] res = list(node//xfind.hasattrnamed("class", xml=True)) assert len(res) == 1 assert res[0] is node[1] def test_is(): node = xfindnode() res = list(node//xfind.is_(html.h1, html.h2)) assert len(res) == 3 assert res[0] is node[0][0] assert res[1] is node[1][0] assert res[2] is node[1][-1][0] res = list(node//html.h1/xfind.is_(html.h1, html.h2)) assert len(res) == 2 assert res[0] is node[0][0] assert res[1] is node[1][0] def test_isnot(): node = xfindnode() res = list(node//xfind.isnot(xsc.Text, html.p, html.div, html.em)) assert len(res) == 3 assert res[0] is node[0][0] assert res[1] is node[1][0] assert res[2] is node[1][-1][0] def test_contains(): node = xfindnode() res = list(node//xfind.is_(html.h1, html.h2)/xfind.contains(html.em)) assert len(res) == 2 assert res[0] is node[0][0] assert res[1] is node[1][-1][0] def test_child(): node = xfindnode() res = list(node//html.h1/xfind.child(html.em)) assert len(res) == 1 assert res[0] is node[0][0][1] def test_attr(): node = xfindnode() res = list(node//xfind.attr(html.div.Attrs.id, html.div.Attrs.align)) assert len(res) == 2 assert res[0] is node[0]["align"] assert res[1] is node[1][-1]["id"] def test_attrnamed(): node = xfindnode() res = list(node//xfind.attrnamed("class_")) assert len(res) == 1 assert res[0] is node[1]["class_"] res = list(node//xfind.attrnamed("class", xml=True)) assert len(res) == 1 assert res[0] is node[1]["class_"] def test_frag(): e = parsers.parseString("das ist klaus. das ist erich", prefixes=xsc.Prefixes(html)) # The following won't generate any nodes, because e/xfind.all iterates all # nodes in the tree (but not the Frag root) and ../html.b filters the bold # *children*, but there are none. assert u"".join(map(unicode, e//html.b)) == u"" # The following *will* produce these nodes assert u"".join(map(unicode, e//xfind.is_(html.b))) == u"klauserich" def test_multiall(): def check(expr, ids): assert "".join(str(e["id"]) for e in expr) == ids # ____0____ # / \ # _1_ _2_ # / \ / \ # 3 4 5 6 # / \ / \ / \ / \ # 7 8 9 a b c d e ds = [html.div(id=hex(id).lower()[2:]) for id in xrange(15)] for i in xrange(7): ds[i].append(ds[2*i+1:2*i+3]) # Using // multiple times might produce certain nodes twice check(ds[0]//html.div//html.div, "34789a56bcde789abcde") def test_itemsslices(): def check(expr, ids): assert "".join(str(e["id"]) for e in expr) == ids # ____0____ # / | \ # _1_ _2_ _3_ # / \ / \ / \ # 4 5 6 7 ds = [html.div(id=id) for id in xrange(8)] ds[0].append(ds[1], ds[2], ds[3]) ds[1].append(ds[4], ds[5]) ds[2].append(ds[5], ds[6]) ds[3].append(ds[6], ds[7]) tests = [ (ds[0]/html.div[0]/html.div[-1], "5"), (ds[0]/html.div/html.div[-1], "567"), (ds[0]/html.div[-1]/html.div, "67"), (ds[0]/(html.div/html.div), "455667"), # we get 5 and 6 twice (ds[0]/(html.div/html.div)[2], "5"), # we get 5 and 6 twice (ds[0]/html.div[:]/html.div[:], "455667"), (ds[0]/html.div/html.p[0], ""), (ds[0]/html.p[0]/html.p[0], ""), # The following might be a surprise, but is perfectly normal: # each node is visited and the div children are yielded. # div(id=0) does have div children and those will be yielded. # This is why the sequence starts with "12" and not "14" (ds[0]//html.div, "123455667"), (ds[0]/html.div[1:2], "2"), (ds[0]/html.div[1:-1]/html.div[1:-1], ""), (ds[0]/html.div[1:-1]/html.div[-1:], "6"), ] for (got, exp) in tests: yield check, got, exp def test_item(): e = html.div(xrange(10)) assert str(e[xsc.Text][0]) == "0" assert str(e[xsc.Text][9]) == "9" assert str(e[xsc.Text][-1]) == "9" assert str(e[xsc.Text][-10]) == "0" py.test.raises(IndexError, e[xsc.Text].__getitem__, 10) py.test.raises(IndexError, e[xsc.Text].__getitem__, -11) assert str(misc.item(e[xsc.Text], 10, "x")) == "x" assert str(misc.item(e[xsc.Text], -11, "x")) == "x"