Skip to content

Commit 264aee3

Browse files
committed
Fix lxml walker for empty fragments
1 parent fd4f032 commit 264aee3

4 files changed

Lines changed: 30 additions & 3 deletions

File tree

‎AUTHORS.rst‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,5 @@ Patches and suggestions
6363
- Ville Skyttä
6464
- Hugo van Kemenade
6565
- Mark Vasilkov
66+
- shkyyy18
6667

‎CHANGES.rst‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ Features:
1818

1919
Bug fixes:
2020

21+
* Allow the lxml treewalker to serialize empty fragments without raising
22+
``IndexError``. (#343)
2123
* The sanitizer now permits ``<summary>`` tags. It used to allow ``<details>``
2224
already. (#423)
2325

‎html5lib/tests/test_treewalkers.py‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
from html5lib import html5parser, treewalkers
1717
from html5lib.filters.lint import Filter as Lint
18+
from html5lib.serializer import HTMLSerializer
1819

1920
import re
2021
attrlist = re.compile(r"^(\s+)\w+=.*(\n\1\w+=.*)+", re.M)
@@ -123,6 +124,28 @@ def test_fragment_single_char(tree, char):
123124
assert list(output) == expected
124125

125126

127+
@pytest.mark.parametrize("tree,intext",
128+
itertools.product(sorted(treeTypes.items()),
129+
["", "<!doctype html>"]))
130+
def test_fragment_empty(tree, intext):
131+
treeName, treeClass = tree
132+
if treeClass is None:
133+
pytest.skip("Treebuilder not loaded")
134+
135+
parser = html5parser.HTMLParser(tree=treeClass["builder"])
136+
document = parser.parseFragment(intext)
137+
document = treeClass.get("adapter", lambda x: x)(document)
138+
139+
assert list(Lint(treeClass["walker"](document))) == []
140+
assert "".join(HTMLSerializer().serialize(treeClass["walker"](document))) == ""
141+
142+
143+
@pytest.mark.skipif(treeTypes["lxml"] is None, reason="lxml not importable")
144+
def test_lxml_empty_list():
145+
walker = treewalkers.getTreeWalker('lxml')
146+
assert list(Lint(walker([]))) == []
147+
148+
126149
@pytest.mark.skipif(treeTypes["lxml"] is None, reason="lxml not importable")
127150
def test_lxml_xml():
128151
expected = [

‎html5lib/treewalkers/etree_lxml.py‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def getnext(self):
5555
return None
5656

5757
def __len__(self):
58-
return 1
58+
return len(self.children)
5959

6060

6161
class Doctype(object):
@@ -180,11 +180,12 @@ def getNodeDetails(self, node):
180180
def getFirstChild(self, node):
181181
assert not isinstance(node, tuple), "Text nodes have no children"
182182

183-
assert len(node) or node.text, "Node has no children"
184183
if node.text:
185184
return (node, "text")
186-
else:
185+
elif len(node):
187186
return node[0]
187+
else:
188+
return None
188189

189190
def getNextSibling(self, node):
190191
if isinstance(node, tuple): # Text node

0 commit comments

Comments
 (0)