Skip to content

Commit e64fed9

Browse files
authored
Fix XML context reporting (#144)
* Fix XML context reporting This affects HTML and other plugins derived from XML * Add test
1 parent 670f36b commit e64fed9

File tree

4 files changed

+121
-3
lines changed

4 files changed

+121
-3
lines changed

docs/src/markdown/about/changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## 2.7.3
4+
5+
- **FIX**: Fix context reporting in the XML, HTML, and other filters derived from XML the filter.
6+
37
## 2.7.2
48

59
- **FIX**: Add note in `--help` option about `--source` behavior.

pyspelling/filters/xml.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,13 +198,18 @@ def extract_string(self, node, is_comments):
198198
self._block_text[self._current_block].append(string)
199199
self._block_text[self._current_block].append(' ')
200200

201-
def set_block(self, node, force=False):
202-
"""Set the current block."""
201+
def pop_block(self, node, force=False):
202+
"""Pop block if the current blocks sibling is found."""
203203

204-
if not force and node is self._block_stack[-1][1]:
204+
while self._block_stack and node is self._block_stack[-1][1]:
205205
self._block_stack.pop(-1)
206206
self._current_block = self._block_stack[-1][0]
207207

208+
def set_block(self, node, force=False):
209+
"""Set the current block."""
210+
211+
self.pop_block(node, force)
212+
208213
if force or self.is_break_tag(node):
209214
self._block_stack.append((node, self.get_last_descendant(node)))
210215
self._block_text[node] = []
@@ -265,6 +270,8 @@ def to_text(self, root):
265270
if next_good is None:
266271
break
267272
else:
273+
self.pop_block(node)
274+
268275
# Handle test nodes: normal text and comments
269276
is_comments = isinstance(node, bs4.Comment)
270277
if (self.comments and is_comments) or (not is_comments and not isinstance(node, NON_CONTENT)):

tests/filters/test_html.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,3 +1498,62 @@ def test_html_after_text(self):
14981498

14991499
self.mktemp('test.txt', template, 'utf-8')
15001500
self.assert_spellcheck('.html.yml', bad_words)
1501+
1502+
1503+
class TestHTMLContext(util.PluginTestCase):
1504+
"""Test HTML plugin with default `lxml` (HTML) mode."""
1505+
1506+
def setup_fs(self):
1507+
"""Setup file system."""
1508+
1509+
config = self.dedent(
1510+
"""
1511+
matrix:
1512+
- name: html
1513+
sources:
1514+
- '{}/**/*.txt'
1515+
aspell:
1516+
lang: en
1517+
d: en_US
1518+
hunspell:
1519+
d: en_US
1520+
pipeline:
1521+
- pyspelling.filters.html:
1522+
attributes:
1523+
- alt
1524+
ignores:
1525+
- ':is(code, pre)'
1526+
- 'span:matches(.some-class, #some-id)'
1527+
"""
1528+
).format(self.tempdir)
1529+
self.mktemp('.html.yml', config, 'utf-8')
1530+
1531+
def test_html_context(self):
1532+
"""Test HTML context."""
1533+
1534+
template = self.dedent(
1535+
"""
1536+
<html>
1537+
<head>
1538+
</head>
1539+
<body>
1540+
<ol>
1541+
<li>
1542+
<p>Some <code>dkdd</code> text
1543+
flga</p>
1544+
<div><pre><code>kdjk</code></pre></div>
1545+
helo
1546+
</li>
1547+
</ol>
1548+
</html>
1549+
"""
1550+
)
1551+
1552+
self.mktemp('test.txt', template, 'utf-8')
1553+
self.assert_context(
1554+
'.html.yml',
1555+
[
1556+
'test.txt: html>body>ol>li',
1557+
'test.txt: html>body>ol>li>p'
1558+
]
1559+
)

tests/util.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,54 @@ def assert_spell_required(self, running):
135135
"'{}', is not compatible with '{}'".format(running, required)
136136
)
137137

138+
def assert_context(self, config_file, expected, names=None, groups=None, sources=None, verbose=4):
139+
"""Check context."""
140+
141+
hunspell_location = which(HUNSPELL)
142+
aspell_location = which(ASPELL)
143+
if hunspell_location and aspell_location:
144+
running = "both"
145+
elif hunspell_location:
146+
running = "hunspell"
147+
elif aspell_location:
148+
running = "aspell"
149+
else:
150+
running = "none"
151+
self.assert_spell_required(running)
152+
153+
if hunspell_location:
154+
context = []
155+
for results in spellcheck(
156+
os.path.join(self.tempdir, config_file),
157+
names=names,
158+
groups=groups,
159+
sources=sources,
160+
checker='hunspell',
161+
binary=hunspell_location,
162+
debug=True,
163+
verbose=verbose
164+
):
165+
if results.error:
166+
print(results.error)
167+
context.append(results.context)
168+
self.assertEqual([('{}/{}'.format(self.tempdir, i) if i else i) for i in expected[:]], context)
169+
if aspell_location:
170+
context = []
171+
for results in spellcheck(
172+
os.path.join(self.tempdir, config_file),
173+
names=names,
174+
groups=groups,
175+
sources=sources,
176+
checker='aspell',
177+
binary=aspell_location,
178+
debug=True,
179+
verbose=verbose
180+
):
181+
if results.error:
182+
print(results.error)
183+
context.append(results.context)
184+
self.assertEqual([('{}/{}'.format(self.tempdir, i) if i else i) for i in expected[:]], context)
185+
138186
def assert_spellcheck(self, config_file, expected, names=None, groups=None, sources=None, verbose=4):
139187
"""Spell check."""
140188

0 commit comments

Comments
 (0)