aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Dubost <karl+github@la-grange.net>2021-02-02 05:32:50 +0900
committerGitHub <noreply@github.com>2021-02-01 21:32:50 +0100
commit9eb11a139fac5514d8456626806a68b3e3b7eafb (patch)
tree060e3c9b600cf8279eb642aefec672c525b224b6
parentbpo-38307: Add end_lineno attribute to pyclbr Objects (GH-24348) (diff)
downloadcpython-9eb11a139fac5514d8456626806a68b3e3b7eafb.tar.gz
cpython-9eb11a139fac5514d8456626806a68b3e3b7eafb.tar.bz2
cpython-9eb11a139fac5514d8456626806a68b3e3b7eafb.zip
bpo-41748: Handles unquoted attributes with commas (#24072)
* bpo-41748: Adds tests for unquoted attributes with comma * bpo-41748: Handles unquoted attributes with comma * bpo-41748: Addresses review comments * bpo-41748: Addresses review comments * Adds more test cases * Simplifies the regex for handling spaces * bpo-41748: Moves attributes tests under the right class * bpo-41748: Addresses review about duplicate attributes * bpo-41748: Adds NEWS.d entry for this patch
-rw-r--r--Lib/html/parser.py2
-rw-r--r--Lib/test/test_htmlparser.py92
-rw-r--r--Misc/NEWS.d/next/Library/2021-01-05-21-26-29.bpo-41748.KdC0w3.rst2
3 files changed, 59 insertions, 37 deletions
diff --git a/Lib/html/parser.py b/Lib/html/parser.py
index 60830779816..9e49effca1f 100644
--- a/Lib/html/parser.py
+++ b/Lib/html/parser.py
@@ -46,7 +46,7 @@ locatestarttagend_tolerant = re.compile(r"""
|"[^"]*" # LIT-enclosed value
|(?!['"])[^>\s]* # bare value
)
- (?:\s*,)* # possibly followed by a comma
+ \s* # possibly followed by a space
)?(?:\s|/(?!>))*
)*
)?
diff --git a/Lib/test/test_htmlparser.py b/Lib/test/test_htmlparser.py
index a2bfb39d16a..12917755a56 100644
--- a/Lib/test/test_htmlparser.py
+++ b/Lib/test/test_htmlparser.py
@@ -452,42 +452,6 @@ text
self._run_check('<!spacer type="block" height="25">',
[('comment', 'spacer type="block" height="25"')])
- def test_with_unquoted_attributes(self):
- # see #12008
- html = ("<html><body bgcolor=d0ca90 text='181008'>"
- "<table cellspacing=0 cellpadding=1 width=100% ><tr>"
- "<td align=left><font size=-1>"
- "- <a href=/rabota/><span class=en> software-and-i</span></a>"
- "- <a href='/1/'><span class=en> library</span></a></table>")
- expected = [
- ('starttag', 'html', []),
- ('starttag', 'body', [('bgcolor', 'd0ca90'), ('text', '181008')]),
- ('starttag', 'table',
- [('cellspacing', '0'), ('cellpadding', '1'), ('width', '100%')]),
- ('starttag', 'tr', []),
- ('starttag', 'td', [('align', 'left')]),
- ('starttag', 'font', [('size', '-1')]),
- ('data', '- '), ('starttag', 'a', [('href', '/rabota/')]),
- ('starttag', 'span', [('class', 'en')]), ('data', ' software-and-i'),
- ('endtag', 'span'), ('endtag', 'a'),
- ('data', '- '), ('starttag', 'a', [('href', '/1/')]),
- ('starttag', 'span', [('class', 'en')]), ('data', ' library'),
- ('endtag', 'span'), ('endtag', 'a'), ('endtag', 'table')
- ]
- self._run_check(html, expected)
-
- def test_comma_between_attributes(self):
- self._run_check('<form action="/xxx.php?a=1&amp;b=2&amp", '
- 'method="post">', [
- ('starttag', 'form',
- [('action', '/xxx.php?a=1&b=2&'),
- (',', None), ('method', 'post')])])
-
- def test_weird_chars_in_unquoted_attribute_values(self):
- self._run_check('<form action=bogus|&#()value>', [
- ('starttag', 'form',
- [('action', 'bogus|&#()value')])])
-
def test_invalid_end_tags(self):
# A collection of broken end tags. <br> is used as separator.
# see http://www.w3.org/TR/html5/tokenization.html#end-tag-open-state
@@ -766,6 +730,62 @@ class AttributesTestCase(TestCaseBase):
[("href", "http://www.example.org/\">;")]),
("data", "spam"), ("endtag", "a")])
+ def test_with_unquoted_attributes(self):
+ # see #12008
+ html = ("<html><body bgcolor=d0ca90 text='181008'>"
+ "<table cellspacing=0 cellpadding=1 width=100% ><tr>"
+ "<td align=left><font size=-1>"
+ "- <a href=/rabota/><span class=en> software-and-i</span></a>"
+ "- <a href='/1/'><span class=en> library</span></a></table>")
+ expected = [
+ ('starttag', 'html', []),
+ ('starttag', 'body', [('bgcolor', 'd0ca90'), ('text', '181008')]),
+ ('starttag', 'table',
+ [('cellspacing', '0'), ('cellpadding', '1'), ('width', '100%')]),
+ ('starttag', 'tr', []),
+ ('starttag', 'td', [('align', 'left')]),
+ ('starttag', 'font', [('size', '-1')]),
+ ('data', '- '), ('starttag', 'a', [('href', '/rabota/')]),
+ ('starttag', 'span', [('class', 'en')]), ('data', ' software-and-i'),
+ ('endtag', 'span'), ('endtag', 'a'),
+ ('data', '- '), ('starttag', 'a', [('href', '/1/')]),
+ ('starttag', 'span', [('class', 'en')]), ('data', ' library'),
+ ('endtag', 'span'), ('endtag', 'a'), ('endtag', 'table')
+ ]
+ self._run_check(html, expected)
+
+ def test_comma_between_attributes(self):
+ # see bpo 41478
+ # HTMLParser preserves duplicate attributes, leaving the task of
+ # removing duplicate attributes to a conformant html tree builder
+ html = ('<div class=bar,baz=asd>' # between attrs (unquoted)
+ '<div class="bar",baz="asd">' # between attrs (quoted)
+ '<div class=bar, baz=asd,>' # after values (unquoted)
+ '<div class="bar", baz="asd",>' # after values (quoted)
+ '<div class="bar",>' # one comma values (quoted)
+ '<div class=,bar baz=,asd>' # before values (unquoted)
+ '<div class=,"bar" baz=,"asd">' # before values (quoted)
+ '<div ,class=bar ,baz=asd>' # before names
+ '<div class,="bar" baz,="asd">' # after names
+ )
+ expected = [
+ ('starttag', 'div', [('class', 'bar,baz=asd'),]),
+ ('starttag', 'div', [('class', 'bar'), (',baz', 'asd')]),
+ ('starttag', 'div', [('class', 'bar,'), ('baz', 'asd,')]),
+ ('starttag', 'div', [('class', 'bar'), (',', None),
+ ('baz', 'asd'), (',', None)]),
+ ('starttag', 'div', [('class', 'bar'), (',', None)]),
+ ('starttag', 'div', [('class', ',bar'), ('baz', ',asd')]),
+ ('starttag', 'div', [('class', ',"bar"'), ('baz', ',"asd"')]),
+ ('starttag', 'div', [(',class', 'bar'), (',baz', 'asd')]),
+ ('starttag', 'div', [('class,', 'bar'), ('baz,', 'asd')]),
+ ]
+ self._run_check(html, expected)
+
+ def test_weird_chars_in_unquoted_attribute_values(self):
+ self._run_check('<form action=bogus|&#()value>', [
+ ('starttag', 'form',
+ [('action', 'bogus|&#()value')])])
if __name__ == "__main__":
unittest.main()
diff --git a/Misc/NEWS.d/next/Library/2021-01-05-21-26-29.bpo-41748.KdC0w3.rst b/Misc/NEWS.d/next/Library/2021-01-05-21-26-29.bpo-41748.KdC0w3.rst
new file mode 100644
index 00000000000..52efa3ac3d4
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2021-01-05-21-26-29.bpo-41748.KdC0w3.rst
@@ -0,0 +1,2 @@
+Fix HTMLParser parsing rules for element attributes containing
+commas with spaces. Patch by Karl Dubost. \ No newline at end of file