summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2016-07-29 18:39:46 +0200
committerStefan Behnel <stefan_ml@behnel.de>2016-07-29 18:39:46 +0200
commit8132c755adad4a75ba855d985dd257493bccc7fd (patch)
tree5437b2d545e68a4b4f25cef8f979e33f09e87737
parent2feb26c2a412880c77adb10dfc382d22275813c8 (diff)
downloadpython-lxml-8132c755adad4a75ba855d985dd257493bccc7fd.tar.gz
allow el.set("attr") in HTML trees without having to specify an explicit None value
-rw-r--r--doc/lxmlhtml.txt11
-rw-r--r--src/lxml/html/__init__.py12
-rw-r--r--src/lxml/tests/test_htmlparser.py11
3 files changed, 24 insertions, 10 deletions
diff --git a/doc/lxmlhtml.txt b/doc/lxmlhtml.txt
index 6d9f63f4..93bb0c27 100644
--- a/doc/lxmlhtml.txt
+++ b/doc/lxmlhtml.txt
@@ -149,12 +149,13 @@ also include some extra methods:
Returns a set-like object that allows accessing and modifying the
names in the 'class' attribute of the element. (New in lxml 3.5).
-``.set('attribute', None)``:
- Creates a boolean attribute, like ``<form novalidate></form>``
- or ``<div custom-attribute></div>``. In XML attributes must
+``.set(key, value=None)``:
+ Sets an HTML attribute. If no value is given, or if the value is
+ ``None``, it creates a boolean attribute like ``<form novalidate></form>``
+ or ``<div custom-attribute></div>``. In XML, attributes must
have at least the empty string as their value like ``<form
- novalidate=""></form>``, but HTML boolean attributes can be either
- present or absent from an element.
+ novalidate=""></form>``, but HTML boolean attributes can also be
+ just present or absent from an element without having a value.
Running HTML doctests
=====================
diff --git a/src/lxml/html/__init__.py b/src/lxml/html/__init__.py
index ba36272d..9d5ae953 100644
--- a/src/lxml/html/__init__.py
+++ b/src/lxml/html/__init__.py
@@ -239,6 +239,15 @@ class Classes(MutableSet):
class HtmlMixin(object):
+ def set(self, key, value=None):
+ """set(self, key, value=None)
+
+ Sets an element attribute. If no value is provided, or if the value is None,
+ creates a 'boolean' attribute without value, e.g. "<form novalidate></form>"
+ for ``form.set('novalidate')``.
+ """
+ super(HtmlElement, self).set(key, value)
+
@property
def classes(self):
"""
@@ -682,8 +691,9 @@ class HtmlComment(etree.CommentBase, HtmlMixin):
class HtmlElement(etree.ElementBase, HtmlMixin):
- # Override etree.ElementBase.cssselect, despite the MRO
+ # Override etree.ElementBase.cssselect() and set(), despite the MRO (FIXME: change base order?)
cssselect = HtmlMixin.cssselect
+ set = HtmlMixin.set
class HtmlProcessingInstruction(etree.PIBase, HtmlMixin):
diff --git a/src/lxml/tests/test_htmlparser.py b/src/lxml/tests/test_htmlparser.py
index 6a436a6f..386c63f3 100644
--- a/src/lxml/tests/test_htmlparser.py
+++ b/src/lxml/tests/test_htmlparser.py
@@ -596,20 +596,23 @@ class HtmlParserTestCase(HelperTestCase):
# ability to serialize boolean attribute by setting value to None
form = html.Element('form')
form.set('novalidate', None)
- self.assertEqual(html.tostring(form),
- _bytes('<form novalidate></form>'))
+ self.assertEqual(html.tostring(form),
+ _bytes('<form novalidate></form>'))
+ form.set('custom')
+ self.assertEqual(html.tostring(form),
+ _bytes('<form novalidate custom></form>'))
def test_boolean_attribute_round_trip(self):
# ability to pass boolean attributes unmodified
fragment = '<tag attribute></tag>'
self.assertEqual(html.tostring(html.fragment_fromstring(fragment)),
- _bytes(fragment))
+ _bytes(fragment))
def test_boolean_attribute_xml_adds_empty_string(self):
# html serialized as xml converts boolean attributes to empty strings
fragment = '<tag attribute></tag>'
self.assertEqual(self.etree.tostring(html.fragment_fromstring(fragment)),
- _bytes('<tag attribute=""/>'))
+ _bytes('<tag attribute=""/>'))
def test_suite():