Module: check_mk
Branch: master
Commit: a45b64de09dd0bbeb5477e192fb6388debe672e2
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=a45b64de09dd0b…
Author: Roland Halbig <rh(a)mathias-kettner.de>
Date: Tue Feb 7 13:39:12 2017 +0100
Feature in htmllib: Nested html plug context.
Change-Id: I241a99d657d93cb349f50d8ccae959fcebec2ba4
---
tests/web/test_OutputFunnel.py | 116 +++++++++++++++++++++++++++++++++++++++++
web/htdocs/htmllib.py | 50 ++++++++++--------
2 files changed, 143 insertions(+), 23 deletions(-)
diff --git a/tests/web/test_OutputFunnel.py b/tests/web/test_OutputFunnel.py
new file mode 100644
index 0000000..db6b6e9
--- /dev/null
+++ b/tests/web/test_OutputFunnel.py
@@ -0,0 +1,116 @@
+#!/usr/bin/python
+# call using
+# > py.test -s -k test_html_generator.py
+
+
+import pytest
+
+# Override the global site fixture. Not wanted for git tests!
+(a)pytest.fixture
+def site(request):
+ pass
+
+# Mark all tests in this file to be executed in the git context
+pytestmark = pytest.mark.html_gentest
+
+# external imports
+from contextlib import contextmanager
+
+
+# internal imports
+from htmllib import HTML, OutputFunnel, plug
+from classes import HTMLOrigTester, HTMLCheck_MKTester
+
+
+class OutputFunnelTester(OutputFunnel):
+
+ def __init__(self):
+ super(OutputFunnelTester, self).__init__()
+ self.written = ""
+
+
+ def lowlevel_write(self, text):
+ self.written += text
+
+
+# @ofdecorate
+# def write_test(self, text):
+# self.write("<div>THISISATESTTEXT: %s</div>\n" % text)
+#
+# decorator for automatical test generation
+# def ofdecorate(func):
+# def func_wrapper(html, *args, **kwargs):
+# with plug(html):
+# func(html, *args, **kwargs)
+# print "_" * 10 + " %s|%s|%s" % (args, kwargs,
html.plug_text)
+# return func_wrapper
+#
+#def test_decorator():
+# print ""
+# html = OutputFunnelTester()
+# html.write_test("HALLO WELT!")
+# print html.written
+
+
+def test_plug():
+ html = OutputFunnelTester()
+
+ html.write("A")
+ assert html.written == "A"
+ html.plug()
+ html.write("B")
+ assert html.plug_text == ["B"]
+ html.plug()
+ html.write("C")
+ assert html.plug_text == ["B", "C"]
+ html.unplug()
+ assert html.plug_text == ["BC"]
+ html.unplug()
+ assert html.written == "ABC"
+
+
+
+def test_context():
+ html = OutputFunnelTester()
+
+ html.write("A")
+ assert html.written == "A"
+ with plug(html):
+ html.write("B")
+ assert html.plug_text == ["B"]
+ with plug(html):
+ html.write("C")
+ assert html.plug_text == ["B", "C"]
+ assert html.plug_text == ["BC"]
+ assert html.written == "ABC"
+
+
+
+def test_drain():
+ html = OutputFunnelTester()
+
+ html.plug()
+ html.write("A")
+ text = html.drain()
+ assert text == "A"
+ html.write("B")
+ assert html.plug_text == ["B"]
+ html.unplug()
+ assert html.written == "B"
+
+
+def test_flush():
+ html = OutputFunnelTester()
+
+ html.plug()
+ html.write("A")
+ html.plug_text == ["A"]
+ html.flush()
+ assert html.written == "A"
+ assert html.plug_text == ['']
+ html.unplug()
+ assert html.written == "A"
+
+
+
+
diff --git a/web/htdocs/htmllib.py b/web/htdocs/htmllib.py
index 9ffdc8a..a994265 100644
--- a/web/htdocs/htmllib.py
+++ b/web/htdocs/htmllib.py
@@ -94,6 +94,15 @@ class RequestTimeout(MKException):
pass
+# TODO: is contextlib supported by older versions?
+from contextlib import contextmanager
+
+# Plug context
+@contextmanager
+def plug(html):
+ html.plug()
+ yield
+ html.unplug()
#
# Encoding and escaping
@@ -310,8 +319,8 @@ class OutputFunnel(object):
def __init__(self):
- self.plugged = False
- self.plugged_text = ""
+ self.plug_level = -1
+ self.plug_text = []
# Accepts str and unicode objects only!
@@ -326,8 +335,8 @@ class OutputFunnel(object):
if type(text) not in [str, unicode]: # also possible: type Exception!
raise MKGeneralException(_('Type Error: html.write accepts str and
unicode input objects only!'))
- if self.plugged:
- self.plugged_text += text
+ if self.is_plugged():
+ self.plug_text[self.plug_level] += text
else:
# encode when really writing out the data. Not when writing plugged,
# because the plugged code will be handled somehow by our code. We
@@ -335,7 +344,6 @@ class OutputFunnel(object):
if type(text) == unicode:
text = text.encode("utf-8")
self.lowlevel_write(text)
- #TODO: return self
def lowlevel_write(self, text):
@@ -344,34 +352,29 @@ class OutputFunnel(object):
# Put in a plug which stops the text stream and redirects it to a sink.
def plug(self):
- self.plugged = True
- self.plugged_text = ''
+ self.plug_text += ['']
+ self.plug_level += 1
def is_plugged(self):
- return self.plugged
+ return self.plug_level > -1
# Pull the plug for a moment to allow the sink content to pass through.
def flush(self):
- if self.plugged:
- text = self.plugged_text
-
- # encode when really writing out the data. Not when writing plugged,
- # because the plugged code will be handled somehow by our code. We
- # only encode when leaving the pythonic world.
- if type(text) == unicode:
- text = text.encode("utf-8")
-
- self.lowlevel_write(text)
- self.plugged_text = ''
+ if self.is_plugged():
+ text = self.plug_text[self.plug_level]
+ self.plug_text[self.plug_level] = ""
+ self.plug_level -= 1
+ self.write(text)
+ self.plug_level += 1
# Get the sink content in order to do something with it.
def drain(self):
- if self.plugged:
- text = self.plugged_text
- self.plugged_text = ''
+ if self.is_plugged():
+ text = self.plug_text[self.plug_level]
+ self.plug_text[self.plug_level] = ''
return text
else:
return ''
@@ -379,7 +382,8 @@ class OutputFunnel(object):
def unplug(self):
self.flush()
- self.plugged = False
+ self.plug_text.pop()
+ self.plug_level -= 1
#.