Module: check_mk
Branch: master
Commit: b221e6b0057ae107a9746413338142ac57cc9c5a
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=b221e6b0057ae1…
Author: Roland Halbig <rh(a)mathias-kettner.de>
Date: Fri Dec 9 09:29:23 2016 +0100
htmllib: rerefactoring HTML class.
---
tests/web/test_html.py | 61 +++++++++++++++++++++++----
tests/web/tools.py | 5 ++-
web/htdocs/htmllib.py | 110 +++++++++++++++++++++++++++++++++++++++----------
3 files changed, 145 insertions(+), 31 deletions(-)
diff --git a/tests/web/test_html.py b/tests/web/test_html.py
index fd4276b..07c30ec 100644
--- a/tests/web/test_html.py
+++ b/tests/web/test_html.py
@@ -1,4 +1,5 @@
#!/usr/bin/python
+# -*- coding: utf-8 -*-
# call using
# > py.test -s -k test_HTML_generator.py
@@ -11,14 +12,27 @@ sys.path.insert(0, "%s/web/htdocs" % cmk_path())
import re
# internal imports
+import json
+import htmllib
from htmllib import HTML
+try:
+ import simplejson as json
+except ImportError:
+ import json
+# Monkey patch in order to make the HTML class below json-serializable without changing
the default json calls.
+def _default(self, obj):
+ return getattr(obj.__class__, "to_json", _default.default)(obj)
+_default.default = json.JSONEncoder().default # Save unmodified default.
+json.JSONEncoder.default = _default # replacement
+
+
def test_class_HTML():
- a = "One"
+ a = "Oneüლ,ᔑ•ﺪ͟͠•ᔐ.ლ"
b = "two"
c = "Three"
d = unicode('u')
@@ -28,15 +42,30 @@ def test_class_HTML():
C = HTML(c)
D = HTML(d)
+ assert HTML(None) == HTML(u"%s" % None)
assert HTML() == HTML('')
+ assert str(A) == a, str(A)
+ assert "%s" % A == a, "%s" % A
+ assert json.loads(json.dumps(A)) == A
+ assert repr(A) == 'HTML(\"%s\")' % A
+ assert len(B) == len(b)
+ assert unicode(B) == unicode(b)
+
+
+
assert (A + B) == (a + b)
assert HTML().join([A, B]) == A + B
assert HTML().join([a, b]) == a + b
+ assert HTML("jo").join([A, B]) == A + "jo" + B
+ assert HTML("jo").join([a, b]) == a + "jo" + b
assert ''.join(map(str, [A, B])) == A + B
+
assert isinstance(A, HTML), type(A)
- assert isinstance(A, unicode), type(A)
+ # assert isinstance(A, unicode), type(A)
assert not isinstance(A, str), type(A)
+ assert isinstance(unicode(A), unicode), unicode(A)
+ assert isinstance(str(A), str), str(A)
assert isinstance(A + B, HTML), type(A + B)
assert isinstance(HTML('').join([A, B]), HTML)
assert isinstance(HTML().join([A, B]), HTML)
@@ -50,11 +79,17 @@ def test_class_HTML():
#
"<div></br><input/></div>"
A += B
- assert isinstance(A, HTML), A
-
a += b
+ assert isinstance(A, HTML), A
assert A == a, A
+ assert a in A, A
+ assert A.count(a) == 1
+ assert A.index(a) == 0
+
+ assert isinstance(A[1:3], HTML)
+ assert A[1:3] == a[1:3], A[1:3]
+
assert A == a
assert ("%s" % A) == a
@@ -71,7 +106,7 @@ def test_class_HTML():
assert A != B
assert isinstance(HTML(HTML(A)), HTML)
- assert isinstance("%s" % HTML(HTML(A)), unicode)
+ assert isinstance("%s" % HTML(HTML(A)), str)
assert isinstance(A, HTML)
A += (" JO PICASSO! ")
@@ -79,13 +114,21 @@ def test_class_HTML():
assert isinstance(A + "TEST" , HTML)
- assert isinstance("TEST%s" % A, unicode)
+ assert isinstance("TEST%s" % A, str)
assert "test" + C == "test" + c
assert D == d
assert "%s" % D == "%s" % d
- assert isinstance("%s" % D, unicode)
-
- assert repr(D) == "HTML(%s)" % repr(d)
+ assert isinstance(u"%s" % D, unicode)
+ assert isinstance("%s" % D, str)
+
+ E = A + B
+ e = "%s" % E
+ assert E.lstrip(E[0]) == e.lstrip(e[0])
+ assert E == e
+ assert E.rstrip(E[0]) == e.rstrip(e[0])
+ assert E == e
+ assert E.strip(E[0]) == e.strip(e[0])
+ assert E == e
diff --git a/tests/web/tools.py b/tests/web/tools.py
index bd65676..7440266 100644
--- a/tests/web/tools.py
+++ b/tests/web/tools.py
@@ -48,7 +48,7 @@ def timeit(method):
def prettify(html_text):
- txt = bs(html_text, 'html5lib').prettify()
+ txt = bs("%s" % html_text, 'html5lib').prettify()
return re.sub('\n{2,}', '\n', re.sub('>',
'>\n', txt))
@@ -126,6 +126,9 @@ def compare_soup(html1, html2):
def compare_html(html1, html2):
+ html1 = "%s" % html1
+ html2 = "%s" % html2
+
# compare tags
opening_1 = re.findall(r'<[^<]*>', html1)
opening_2 = re.findall(r'<[^<]*>', html2)
diff --git a/web/htdocs/htmllib.py b/web/htdocs/htmllib.py
index 97467d1..ff50d36 100644
--- a/web/htdocs/htmllib.py
+++ b/web/htdocs/htmllib.py
@@ -69,11 +69,17 @@ try:
except ImportError:
import json
+# Monkey patch in order to make the HTML class below json-serializable without changing
the default json calls.
+def _default(self, obj):
+ return getattr(obj.__class__, "to_json", _default.default)(obj)
+_default.default = json.JSONEncoder().default # Save unmodified default.
+json.JSONEncoder.default = _default # replacement
+
+
from cmk.exceptions import MKGeneralException, MKException
from lib import MKUserError
-
# Information about uri
class InvalidUserInput(Exception):
def __init__(self, varname, text):
@@ -145,34 +151,57 @@ class Escaper(object):
# | |_| |_| |_| |_| |_|_____| |
# | |
# +----------------------------------------------------------------------+
-# | This is a simple class which wraps a string provided by the caller |
-# | to make html.attrencode() know that this string should not be |
-# | encoded, html.attrencode() will then return the unmodified value. |
+# | This is a simple class which wraps a unicode string provided by |
+# | the caller to make html.attrencode() know that this string should |
+# | not be escaped. |
# | |
-# | This way we can implement encodings while still allowing HTML code |
-# | processing for some special cases. This is useful when one needs |
-# | to print out HTML tables in messages or help texts. |
+# | This way we can implement encodings while still allowing HTML code. |
+# | This is useful when one needs to print out HTML tables in messages |
+# | or help texts. |
# | |
-# | The class now implements all relevant string comparison methods. |
-# | The HTMLGenerator render_tag() function returns a HTML object. |
+# | The HTML class is implemented as an immutable type. |
+# | Every instance of the class is a unicode string. |
+# | Only utf-8 compatible encodings are supported. |
# '----------------------------------------------------------------------'
-class HTML(unicode, Escaper):
- def __new__(self, value = ''):
+class HTML(object):
+
+
+ def __init__(self, value = u''):
+ super(HTML, self).__init__()
+ self.value = self._ensure_unicode(value)
+
+
+ def __unicode__(self):
+ return self.value
+
+
+ def _ensure_unicode(self, thing, encoding_index=0):
try:
- return unicode.__new__(self, value)
- except UnicodeDecodeError as e:
- return unicode.__new__(self, value.decode('utf-8'))
+ return unicode(thing)
+ except UnicodeDecodeError:
+ return thing.decode("utf-8")
+
+
+ def __bytebatzen__(self):
+ return self.value.encode("utf-8")
+
+
+ def __str__(self):
+ return self.__bytebatzen__()
def __repr__(self):
- return "HTML(%s)" % repr("%s" % self)
+ return ("HTML(\"%s\")" %
self.value).encode("utf-8")
+
+
+ def to_json(self):
+ return self.value
def __add__(self, other):
- return HTML(unicode.__add__(self, other))
- #TODO: return HTML(unicode.__add__(self, self._escape_text(other)))
+ return HTML(self.value + self._ensure_unicode(other))
def __iadd__(self, other):
@@ -180,13 +209,52 @@ class HTML(unicode, Escaper):
def __radd__(self, other):
- return HTML("%s%s" % (other, self))
- #TODO: return HTML("%s%s" % (self._escape_text(other), self))
+ return HTML(self._ensure_unicode(other) + self.value)
def join(self, iterable):
- return HTML(''.join(iterable))
- #TODO: return HTML(''.join(map(lambda x: self._escape_text(x),
iterable)))
+ return HTML(self.value.join(map(self._ensure_unicode, iterable)))
+
+
+ def __eq__(self, other):
+ return self.value == self._ensure_unicode(other)
+
+
+ def __ne__(self, other):
+ return self.value != self._ensure_unicode(other)
+
+
+ def __len__(self):
+ return len(self.value)
+
+
+ def __getitem__(self, index):
+ return HTML(self.value[index])
+
+
+ def __contains__(self, item):
+ return self._ensure_unicode(item) in self.value
+
+
+ def count(self, item):
+ return self.value.count(self._ensure_unicode(item))
+
+
+ def index(self, item):
+ return self.value.index(self._ensure_unicode(item))
+
+
+ def lstrip(self, stripstr):
+ return HTML(self.value.lstrip(self._ensure_unicode(stripstr)))
+
+
+ def rstrip(self, stripstr):
+ return HTML(self.value.rstrip(self._ensure_unicode(stripstr)))
+
+
+ def strip(self, stripstr):
+ return HTML(self.value.strip(self._ensure_unicode(stripstr)))
+
__builtin__.HTML = HTML