#! /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"