root/livinglogic.python.xist/test/test_parse.py @ 2590:7b6bba35f3a0

Revision 2590:7b6bba35f3a0, 7.6 KB (checked in by Walter Doerwald <walter@…>, 13 years ago)

htmlspecials.pixel() now no longer uses colored pixels, instead color is
done via CSS. The URL for the one remaining transparent pixel can now be
specified via src (either as an XML attribute or via the converter context).

Rename attrs methods with() and without() to withnames() and withoutnames()
(for Python 2.5 compatibility).

Use elinks instead of w3m for asText() and move/rename this method to a
function ll.xist.ns.html.astext().

Try to make XIST independent from PyXML (however PyXML is still required
for parsing via expat and for dtd2xsc.py (because this requires xmlproc)).

Remove the long dperecated method withSep().

Use Py_ssize_t in the C source where appropriate.

  • Property exe set to *
Line 
1#! /usr/bin/env/python
2# -*- coding: iso-8859-1 -*-
3
4## Copyright 1999-2006 by LivingLogic AG, Bayreuth/Germany.
5## Copyright 1999-2006 by Walter Dörwald
6##
7## All Rights Reserved
8##
9## See xist/__init__.py for the license
10
11
12import warnings
13
14import py.test
15
16from xml import sax
17from xml.parsers import expat
18
19from ll import url
20from ll.xist import xsc, parsers
21from ll.xist.ns import chars, html, ihtml, specials, ruby
22
23
24oldfilters = None
25
26
27def raisesSAX(exception, func, *args, **kwargs):
28    # assert that func(*args, **kwargs) raises exception either directly or wrapped in a SAXParseException
29    try:
30        func(*args, **kwargs)
31    except exception:
32        pass
33    except sax.SAXParseException, exc:
34        realexc = exc.getException()
35        assert isinstance(realexc, exception)
36    else:
37        raise py.test.fail("exception not raised")
38
39
40class __ns__(xsc.Namespace):
41    xmlname = "foo"
42    xmlurl = "http://www.foo.com/foo"
43    class a(xsc.Element):
44        class Attrs(xsc.Element.Attrs):
45            class title(xsc.TextAttr): pass
46    class foo(xsc.Entity):
47        def __unicode__(self):
48            return u"FOO"
49    class bar(xsc.CharRef):
50        codepoint = 0x42
51
52
53def check_parseentities(source, result, **parseargs):
54    node = parsers.parseString("""<a title="%s">%s</a>""" % (source, source), **parseargs)
55    node = node.walknode(xsc.FindType(xsc.Element))[0]
56    assert unicode(node) == result
57    assert unicode(node["title"]) == result
58
59
60def check_parsestrictentities(source, result, parserfactory):
61    prefixes = xsc.Prefixes([__ns__, chars])
62    check_parseentities(source, result, prefixes=prefixes, saxparser=parserfactory)
63
64    warnings.filterwarnings("error", category=xsc.MalformedCharRefWarning)
65    for bad in ("&", "&#x", "&&", "&#x;", "&#fg;", "&#999999999;", "&#;", "&#y;", "&#x;", "&#xy;"):
66        raisesSAX((xsc.MalformedCharRefWarning, expat.ExpatError), check_parseentities, bad, u"", prefixes=prefixes, saxparser=parserfactory)
67    raisesSAX(xsc.IllegalEntityError, check_parseentities, "&baz;", u"", prefixes=prefixes, saxparser=parserfactory)
68
69
70def check_parsebadentities(parserfactory):
71    prefixes = xsc.Prefixes([__ns__, chars])
72    tests = [
73        ("&amp;", u"&"),
74        ("&amp;amp;", u"&amp;"),
75        ("x&foo;&bar;y", u"xFOO\x42y"),
76        ("x&foobar;y", u"x&foobar;y"),
77        ("&uuml;", u"ü"),
78        ("x&x", u"x&x"),
79        ("x&x;", u"x&x;"),
80        ("a&amp;b&lt;c&gt;d&quot;e&apos;f", u"a&b<c>d\"e'f"),
81        ("x&#;y", u"x&#;y"),
82        ("x&#32;y", u"x y"),
83        ("x&#x20;y", u"x y"),
84        ("x&#-32;y", u"x&#-32;y"),
85        ("x&#999999999;y", "x&#999999999;y"),
86        ("x&#xffffffff;y", "x&#xffffffff;y"),
87        ("x&#xffffffff;y", "x&#xffffffff;y"),
88        ("x&#xffffffff;y&#", "x&#xffffffff;y&#")
89    ]
90    for (source, result) in tests:
91        check_parseentities(source, result, prefixes=prefixes, saxparser=parserfactory)
92
93
94class Test:
95    def setup_method(self, method):
96        global oldfilters
97        oldfilters = warnings.filters[:]
98
99    def teardown_method(self, method):
100        warnings.filters = oldfilters
101
102    def test_parselocationsgmlop(self):
103        # Check that SGMLOP gets the location info right (at least the line numbers)
104        node = parsers.parseString("<z>gurk&amp;hurz&#42;hinz&#x666;hunz</z>", saxparser=parsers.SGMLOPParser)
105        assert len(node) == 1
106        assert len(node[0]) == 1
107        assert node[0][0].startloc.getSystemId() == "STRING"
108        assert node[0][0].startloc.getLineNumber() == 1
109
110    def test_parselocationexpat(self):
111        # Check that expat gets the location info right
112        node = parsers.parseString("<z>gurk&amp;hurz&#42;hinz&#x666;hunz</z>", saxparser=parsers.ExpatParser)
113        assert len(node) == 1
114        assert len(node[0]) == 1
115        assert node[0][0].startloc.getSystemId() == "STRING"
116        assert node[0][0].startloc.getLineNumber() == 1
117        assert node[0][0].startloc.getColumnNumber() == 3
118
119    def test_nsparse(self):
120        # A prepopulated prefix mapping and xmlns attributes should work together
121        xml = """
122            <x:a>
123                <x:a xmlns:x='http://www.w3.org/1999/xhtml'>
124                    <x:a xmlns:x='http://www.nttdocomo.co.jp/imode'>gurk</x:a>
125                </x:a>
126            </x:a>
127        """
128        check = ihtml.a(
129            html.a(
130                ihtml.a(
131                    "gurk"
132                )
133            )
134        )
135        prefixes = xsc.Prefixes(x=ihtml)
136        node = parsers.parseString(xml, prefixes=prefixes)
137        node = node.walknode(xsc.FindType(xsc.Element))[0].compact() # get rid of the Frag and whitespace
138        assert node == check
139
140    def test_parseurls(self):
141        # Check proper URL handling when parsing URLAttr or StyleAttr attributes
142        prefixes = xsc.Prefixes(html)
143        node = parsers.parseString('<a href="4.html" style="background-image: url(3.gif);"/>', base="root:1/2.html", prefixes=prefixes)
144        assert str(node[0]["style"]) == "background-image: url(root:1/3.gif);"
145        assert node[0]["style"].urls() == [url.URL("root:1/3.gif")]
146        assert str(node[0]["href"]) == "root:1/4.html"
147        assert node[0]["href"].forInput(root="gurk/hurz.html") == url.URL("gurk/1/4.html")
148
149    def test_parserequiredattrs(self):
150        # Parser should complain about required attributes that are missing
151        class __ns__(xsc.Namespace):
152            class Test(xsc.Element):
153                class Attrs(xsc.Element.Attrs):
154                    class required(xsc.TextAttr): required = True
155
156        prefixes = xsc.Prefixes(__ns__)
157        node = parsers.parseString('<Test required="foo"/>', prefixes=prefixes)
158        assert str(node[0]["required"]) == "foo"
159
160        warnings.filterwarnings("error", category=xsc.RequiredAttrMissingWarning)
161        raisesSAX(xsc.RequiredAttrMissingWarning, parsers.parseString, '<Test/>', prefixes=prefixes)
162
163    def test_parsevalueattrs(self):
164        # Parser should complain about attributes with illegal values, when a set of values is specified
165        class __ns__(xsc.Namespace):
166            class Test(xsc.Element):
167                class Attrs(xsc.Element.Attrs):
168                    class withvalues(xsc.TextAttr): values = ("foo", "bar")
169
170        prefixes = xsc.Prefixes(__ns__)
171
172        node = parsers.parseString('<Test withvalues="bar"/>', prefixes=prefixes)
173        assert str(node[0]["withvalues"]) == "bar"
174
175        warnings.filterwarnings("error", category=xsc.IllegalAttrValueWarning)
176        raisesSAX(xsc.IllegalAttrValueWarning, parsers.parseString, '<Test withvalues="baz"/>', prefixes=prefixes)
177
178    def test_parsestrictentities_sgmlop(self):
179        check_parsestrictentities(
180            "a&amp;b&foo;&bar;c&#32;d&#x20;&#30000;;&lt;&gt;&quot;&apos;",
181            u"""a&bFOO\x42c d %c;<>"'""" % 30000,
182            parsers.SGMLOPParser
183        )
184
185    def test_parsestrictentities_expat(self):
186        check_parsestrictentities(
187            "a&amp;bc&#32;d&#x20;&#30000;;&lt;&gt;&quot;&apos;",
188            u"""a&bc d %c;<>"'""" % 30000,
189            parsers.ExpatParser
190        )
191
192    def test_parsebadentities_badentity(self):
193        check_parsebadentities(parsers.BadEntityParser)
194
195    def test_parsebadentities_html(self):
196        check_parsebadentities(parsers.HTMLParser)
197
198    def test_multipleparsecalls(self):
199        def check(saxparser):
200            p = parsers.Parser(saxparser=saxparser)
201            for i in xrange(3):
202                try:
203                    p.parseString("<>gurk")
204                except Exception:
205                    pass
206                for j in xrange(3):
207                    assert p.parseString("<a>gurk</a>").asBytes() == "<a>gurk</a>"
208
209        # A Parser instance should be able to parse multiple XML sources, even when some of the parse calls fail
210        for saxparser in (parsers.SGMLOPParser, parsers.BadEntityParser, parsers.HTMLParser, parsers.ExpatParser):
211            yield check, saxparser
212
213    def test_sysid(self):
214        # Default system ids and explicitely specified system ids should end up in the location info of the resulting XML tree
215        node = parsers.parseString("gurk")
216        assert node[0].startloc.sysid == "STRING"
217
218        node = parsers.parseString("gurk", base="root:gurk.xmlxsc")
219        assert node[0].startloc.sysid == "root:gurk.xmlxsc"
220
221        node = parsers.parseString("gurk", base="root:gurk.xmlxsc", sysid="hurz")
222        assert node[0].startloc.sysid == "hurz"
223
224
225def test_xmlns():
226    s = '''
227    <z xmlns="http://xmlns.livinglogic.de/xist/ns/specials">
228    <rb xmlns="http://www.w3.org/TR/ruby/xhtml-ruby-1.mod"/>
229    <z/>
230    </z>
231    '''
232    # After the <rb/> element is left the parser must return to the proper previous mapping
233    parsers.parseString(s, nspool=xsc.NSPool(specials, ruby))
Note: See TracBrowser for help on using the browser.