Module: check_mk
Branch: master
Commit: cdb96fcadea6e39ed2e6995d2fb9b7307bdbd02f
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=cdb96fcadea6e3…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Tue Jan 10 14:36:25 2017 +0100
4229 New Web GUI logging configuration
The logging mechanism of the Web GUI has been changed to a single
global setting. Similar to the new core log level configuration.
Existing verbose log level configurations will be reset to the
default log level during update.
Change-Id: Ib0c8770343d72600a378ef3669fde393ef8e030a
---
.werks/4229 | 13 +++++++++++++
ChangeLog | 1 +
2 files changed, 14 insertions(+)
diff --git a/.werks/4229 b/.werks/4229
new file mode 100644
index 0000000..a674cfd
--- /dev/null
+++ b/.werks/4229
@@ -0,0 +1,13 @@
+Title: New Web GUI logging configuration
+Level: 1
+Component: multisite
+Compatible: compat
+Version: 1.4.0i4
+Date: 1484055330
+Class: feature
+
+The logging mechanism of the Web GUI has been changed to a single
+global setting. Similar to the new core log level configuration.
+
+Existing verbose log level configurations will be reset to the
+default log level during update.
diff --git a/ChangeLog b/ChangeLog
index d4adc45..ae412d1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -31,6 +31,7 @@
Multisite:
* 4169 View action: Default values of sticky, notification and persistent options can now be configured via global settings....
+ * 4229 New Web GUI logging configuration...
* 4143 FIX: Fixed possible log spam "MKAuthException: Invalid credentials" in web.log...
* 4004 FIX: Fixed exception when viewing availability of BI aggregations...
* 4144 FIX: Sidebar: Bottom of last snapin was not 100% visible
Module: check_mk
Branch: master
Commit: 45b222c68566e5c9e859d27ce2e08ebbfb21d105
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=45b222c68566e5…
Author: Roland Halbig <rh(a)mathias-kettner.de>
Date: Tue Jan 10 10:52:20 2017 +0100
Refactoring table.py: Moved functions around.
Change-Id: I3c98ae9e0a323bd62e79bc1c64ca41d004c5c189
---
web/htdocs/table.py | 144 ++++++++++++++++++++++++++--------------------------
1 file changed, 72 insertions(+), 72 deletions(-)
diff --git a/web/htdocs/table.py b/web/htdocs/table.py
index da107c8..5de76aa 100644
--- a/web/htdocs/table.py
+++ b/web/htdocs/table.py
@@ -129,77 +129,6 @@ def add_cell(title="", text="", css=None, help=None, colspan=None, sortable=True
table["rows"][-1][0].append((htmlcode, css, colspan))
-def _filter_rows(rows, search_term):
- filtered_rows = []
- for row, css, state, fixed in rows:
- if state == "header" or fixed:
- filtered_rows.append((row, css, state, fixed))
- continue # skip filtering of headers or fixed rows
-
- for cell_content, css_classes, colspan in row:
- if search_term in cell_content.lower():
- filtered_rows.append((row, css, state, fixed))
- break # skip other cells when matched
- return filtered_rows
-
-
-def _sort_rows(rows, sort_col, sort_reverse):
-
- # remove and remind fixed rows, add to separate list
- fixed_rows = []
- for index, row in enumerate(rows[:]):
- if row[3] == True:
- rows.remove(row)
- fixed_rows.append((index, row))
-
- # Then use natural sorting to sort the list. Note: due to a
- # change in the number of columns of a table in different software
- # versions the cmp-function might fail. This is because the sorting
- # column is persisted in a user file. So we ignore exceptions during
- # sorting. This gives the user the chance to change the sorting and
- # see the table in the first place.
- try:
- rows.sort(cmp=lambda a, b: cmp(num_split(a[0][sort_col][0]),
- num_split(b[0][sort_col][0])),
- reverse=sort_reverse==1)
- except IndexError:
- pass
-
- # Now re-add the removed "fixed" rows to the list again
- if fixed_rows:
- for index, row in fixed_rows:
- rows.insert(index, row)
-
- return rows
-
-
-def _write_csv(table, csv_separator):
-
- rows = table["rows"]
- headers = table["headers"]
- limit = table['limit']
- omit_headers = table["omit_headers"]
-
- num_rows_unlimited = len(rows)
- num_cols = len(headers)
-
- # Apply limit after search / sorting etc.
- if limit is not None:
- rows = rows[:limit]
-
- def render_headers():
- html.write(csv_separator.join([html.strip_tags(header) or "" for (header, css, help, sortable) in headers]) + "\n")
-
- # If we have no group headers then paint the headers now
- if not omit_headers and table["rows"] and table["rows"][0][2] != "header":
- render_headers()
-
- odd = "even"
- for nr, (row, css, state, fixed) in enumerate(rows):
- html.write(csv_separator.join([html.strip_tags(cell_content) for cell_content, css_classes, colspan in row ]))
- html.write("\n")
-
-
def end():
global table
finish_previous()
@@ -223,7 +152,6 @@ def end():
table = None
return
-
if do_csv:
_write_csv(table, csv_separator)
table = None
@@ -427,3 +355,75 @@ def end():
table = None
+def _write_csv(table, csv_separator):
+
+ rows = table["rows"]
+ headers = table["headers"]
+ limit = table['limit']
+ omit_headers = table["omit_headers"]
+
+ num_rows_unlimited = len(rows)
+ num_cols = len(headers)
+
+ # Apply limit after search / sorting etc.
+ if limit is not None:
+ rows = rows[:limit]
+
+ def render_headers():
+ html.write(csv_separator.join([html.strip_tags(header) or "" for (header, css, help, sortable) in headers]) + "\n")
+
+ # If we have no group headers then paint the headers now
+ if not omit_headers and table["rows"] and table["rows"][0][2] != "header":
+ render_headers()
+
+ odd = "even"
+ for nr, (row, css, state, fixed) in enumerate(rows):
+ html.write(csv_separator.join([html.strip_tags(cell_content) for cell_content, css_classes, colspan in row ]))
+ html.write("\n")
+
+
+
+def _filter_rows(rows, search_term):
+ filtered_rows = []
+ for row, css, state, fixed in rows:
+ if state == "header" or fixed:
+ filtered_rows.append((row, css, state, fixed))
+ continue # skip filtering of headers or fixed rows
+
+ for cell_content, css_classes, colspan in row:
+ if search_term in cell_content.lower():
+ filtered_rows.append((row, css, state, fixed))
+ break # skip other cells when matched
+ return filtered_rows
+
+
+def _sort_rows(rows, sort_col, sort_reverse):
+
+ # remove and remind fixed rows, add to separate list
+ fixed_rows = []
+ for index, row in enumerate(rows[:]):
+ if row[3] == True:
+ rows.remove(row)
+ fixed_rows.append((index, row))
+
+ # Then use natural sorting to sort the list. Note: due to a
+ # change in the number of columns of a table in different software
+ # versions the cmp-function might fail. This is because the sorting
+ # column is persisted in a user file. So we ignore exceptions during
+ # sorting. This gives the user the chance to change the sorting and
+ # see the table in the first place.
+ try:
+ rows.sort(cmp=lambda a, b: cmp(num_split(a[0][sort_col][0]),
+ num_split(b[0][sort_col][0])),
+ reverse=sort_reverse==1)
+ except IndexError:
+ pass
+
+ # Now re-add the removed "fixed" rows to the list again
+ if fixed_rows:
+ for index, row in fixed_rows:
+ rows.insert(index, row)
+
+ return rows
+
+
Module: check_mk
Branch: master
Commit: d3de9e474c8eb845eb3da0fc7ee60b50abf88148
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=d3de9e474c8eb8…
Author: Roland Halbig <rh(a)mathias-kettner.de>
Date: Thu Jan 5 15:47:48 2017 +0100
Refactoring table.py: Isolated sort and filter functions.
Change-Id: I16762356db788386c2f1abdd0f67d4ca1971162d
---
tests/web/test_table.py | 141 ++++++++++++++++++++++++++++++++++++++++++++++++
web/htdocs/table.py | 87 +++++++++++++++++-------------
2 files changed, 192 insertions(+), 36 deletions(-)
diff --git a/tests/web/test_table.py b/tests/web/test_table.py
new file mode 100644
index 0000000..7ce30e6
--- /dev/null
+++ b/tests/web/test_table.py
@@ -0,0 +1,141 @@
+#!/usr/bin/python
+# call using
+# > py.test -s -k test_html_generator.py
+
+# enable imports from web directory
+from testlib import cmk_path
+import sys, os
+sys.path.insert(0, "%s/web/htdocs" % cmk_path())
+
+# external imports
+import re
+from bs4 import BeautifulSoup as bs
+
+# internal imports
+from htmllib import html
+import __builtin__
+from htmllib import HTMLGenerator, HTMLCheck_MK
+from tools import compare_html , gentest, compare_and_empty
+from classes import DeprecatedRenderer
+
+
+try:
+ from config.user import load_file, save_file
+except:
+ load_file = lambda x, y: {}
+ save_file = lambda x, y: None
+
+import table
+
+import traceback
+
+class TableTest(html):
+
+ written_text = ''
+ tag_counter = 0
+
+ def lowlevel_write(self, text):
+
+ if re.match(r'.*\.close_\w+[(][)]', '\n'.join(traceback.format_stack()), re.DOTALL):
+ self.tag_counter -= 1 if self.tag_counter > 0 else 0
+ self.written_text += " " * 4 * self.tag_counter + text
+ elif re.match(r'.*\.open_\w+[(]', '\n'.join(traceback.format_stack()), re.DOTALL):
+ self.written_text += " " * 4 * self.tag_counter + text
+ self.tag_counter += 1
+ else:
+ self.written_text += " " * 4 * self.tag_counter + text + ''
+
+
+def read_out_table(text):
+ # Get the contents of the table as a list of lists
+ data = []
+ for row in bs(text, 'html5lib').findAll('tr'):
+ columns = row.findAll('th')
+ if not columns:
+ columns = row.findAll('td')
+ data.append([re.sub(r'\s', '', re.sub(r'<[^<]*>', '', cell.text)) for cell in columns])
+ return data
+
+
+def read_out_csv(text, separator):
+ # Get the contents of the table as a list of lists
+ data = []
+ for row in text.split('\n'):
+ columns = row.split(separator)
+ data.append([re.sub(r'\s', '', re.sub(r'<[^<]*>', '', cell)) for cell in columns])
+ data = [row for row in data if not all(cell == '' for cell in row)]
+ return data
+
+
+def table_test_cubical(sortable, searchable, limit, output_format):
+
+ html = TableTest()
+ __builtin__.html = html
+
+ table_id = 0
+ title = " TEST "
+ separator = ';'
+
+ html.add_var('_%s_sort' % table_id, "1,0")
+
+ rows = [ (i, i**3) for i in range(10) ]
+ header = ["Number", "Cubical"]
+
+ table.begin(table_id = table_id,
+ title = title,
+ sortable = sortable,
+ searchable = searchable,
+ limit = limit,
+ output_format = output_format)
+
+ for row in rows:
+ table.row()
+ for i in range(len(header)):
+ table.cell(_(header[i]), row[i])
+ table.end()
+
+ # write to file: This is part of the test! Look at the generated HTML!
+ filename = "./web/testtable_%s_%s_%s.html" % ("sortable" * sortable, "searchable" * searchable, limit)
+ text = html.written_text
+ with open(filename, "w") as html_file:
+ html_file.write(text)
+
+ # Data assertions
+ assert output_format in ['html', 'csv'], 'Fetch is not yet implemented'
+ if output_format == 'html':
+ data = read_out_table(text)
+ assert data.pop(0) == header
+ elif output_format == 'csv':
+ data = read_out_csv(text, separator)
+ assert data.pop(0) == header, header
+ else:
+ assert False, 'Not yet implemented!'
+
+ data = [ tuple(map(int, row)) for row in data ]
+ if limit is None:
+ limit = len(rows)
+
+ assert len(data) == limit
+ assert data == rows[:limit]
+
+
+def test_table():
+ table_test_cubical(False, False, None, 'html')
+
+
+def test_limit():
+ table_test_cubical(False, False, 2, 'html')
+
+
+def test_sortable():
+ table_test_cubical(True, False, None, 'html')
+
+
+def test_searchable():
+ table_test_cubical(False, True, None, 'html')
+
+
+def test_csv():
+ table_test_cubical(False, False, None, 'csv')
+
+
diff --git a/web/htdocs/table.py b/web/htdocs/table.py
index 4615b6b..b69e26b 100644
--- a/web/htdocs/table.py
+++ b/web/htdocs/table.py
@@ -128,6 +128,55 @@ def add_cell(title="", text="", css=None, help=None, colspan=None, sortable=True
table["headers"].append((title, css, help, sortable))
table["rows"][-1][0].append((htmlcode, css, colspan))
+
+def _filter_rows(rows, search_term):
+ filtered_rows = []
+ for row, css, state, fixed in rows:
+ if state == "header" or fixed:
+ filtered_rows.append((row, css, state, fixed))
+ continue # skip filtering of headers or fixed rows
+
+ for cell_content, css_classes, colspan in row:
+ if search_term in cell_content.lower():
+ filtered_rows.append((row, css, state, fixed))
+ break # skip other cells when matched
+ return filtered_rows
+
+
+def _sort_rows(rows, sort_col, sort_reverse):
+
+ # remove and remind fixed rows, add to separate list
+ fixed_rows = []
+ for index, row in enumerate(rows[:]):
+ if row[3] == True:
+ rows.remove(row)
+ fixed_rows.append((index, row))
+
+ # Then use natural sorting to sort the list. Note: due to a
+ # change in the number of columns of a table in different software
+ # versions the cmp-function might fail. This is because the sorting
+ # column is persisted in a user file. So we ignore exceptions during
+ # sorting. This gives the user the chance to change the sorting and
+ # see the table in the first place.
+ try:
+ rows.sort(cmp=lambda a, b: cmp(num_split(a[0][sort_col][0]),
+ num_split(b[0][sort_col][0])),
+ reverse=sort_reverse==1)
+ except IndexError:
+ pass
+
+ # Now re-add the removed "fixed" rows to the list again
+ if fixed_rows:
+ for index, row in fixed_rows:
+ rows.insert(index, row)
+
+ return rows
+
+
+
+
+
+
def end():
global table
finish_previous()
@@ -194,17 +243,7 @@ def end():
if search_term:
html.set_var('_%s_search' % table_id, search_term)
table_opts['search'] = search_term # persist
- filtered_rows = []
- for row, css, state, fixed in rows:
- if state == "header" or fixed:
- filtered_rows.append((row, css, state, fixed))
- continue # skip filtering of headers or fixed rows
-
- for cell_content, css_classes, colspan in row:
- if search_term in cell_content.lower():
- filtered_rows.append((row, css, state, fixed))
- break # skip other cells when matched
- rows = filtered_rows
+ rows = _filter_rows(rows, search_term)
if html.var('_%s_reset_sorting' % table_id):
html.del_var('_%s_sort' % table_id)
@@ -218,31 +257,7 @@ def end():
html.set_var('_%s_sort' % table_id, sort)
table_opts['sort'] = sort # persist
sort_col, sort_reverse = map(int, sort.split(',', 1))
-
- # remove and remind fixed rows, add to separate list
- fixed_rows = []
- for index, row in enumerate(rows[:]):
- if row[3] == True:
- rows.remove(row)
- fixed_rows.append((index, row))
-
- # Then use natural sorting to sort the list. Note: due to a
- # change in the number of columns of a table in different software
- # versions the cmp-function might fail. This is because the sorting
- # column is persisted in a user file. So we ignore exceptions during
- # sorting. This gives the user the chance to change the sorting and
- # see the table in the first place.
- try:
- rows.sort(cmp=lambda a, b: cmp(num_split(a[0][sort_col][0]),
- num_split(b[0][sort_col][0])),
- reverse=sort_reverse==1)
- except IndexError:
- pass
-
- # Now re-add the removed "fixed" rows to the list again
- if fixed_rows:
- for index, row in fixed_rows:
- rows.insert(index, row)
+ rows = _sort_rows(rows, sort_col, sort_reverse)
num_rows_unlimited = len(rows)
num_cols = len(table["headers"])