Module: check_mk
Branch: master
Commit: fc2551c94074020c382a8f758063e511c57942e7
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=fc2551c9407402…
Author: Roland Halbig <rh(a)mathias-kettner.de>
Date: Fri Oct 28 13:25:51 2016 +0200
Added refactoring tools auto_build_test and auto_refactor.
---
tests/web/auto_build_test.py | 107 ++++++++++++++++++++++++++++++++
tests/web/auto_refactor.py | 142 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 249 insertions(+)
diff --git a/tests/web/auto_build_test.py b/tests/web/auto_build_test.py
new file mode 100644
index 0000000..ad51128
--- /dev/null
+++ b/tests/web/auto_build_test.py
@@ -0,0 +1,107 @@
+#!/usr/bin/python
+
+#
+# This little script can be used to semi-automatically generate a test file for the
+# refactoring process.
+# It expects a 'git diff master refactored_file.py' printout and generates test
functions
+# for every individual replacement.
+# It is semi-automativ, because the generated 'test_auto_refactored_file.py needs to
be postprocessed
+# by adding variables and adjusting the indent level for if clauses for example.
+# then the file can be called using py.test -s -v test_auto_refactored_file.py
+#
+
+import sys, re
+import os.path
+
+header = '''
+#!/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
+sys.path.insert(0, "%s/web/htdocs" % cmk_path())
+
+# external imports
+import re
+from bs4 import BeautifulSoup as bs
+
+# internal imports
+from classes import HTMLOrigTester, HTMLCheck_MKTester
+from tools import compare_html , gentest, compare_and_empty
+'''
+
+function_start = lambda x: '''
+def test_%d():
+ old = HTMLOrigTester()
+ new = HTMLCheck_MKTester()
+ old.plug()
+ new.plug()
+\n
+''' % x
+
+function_end = '''
+ compare_and_empty(old, new)
+
+'''
+
+
+if __name__ == "__main__":
+
+ if len(sys.argv) <= 1:
+ print "ERROR GIVE A FILE PLS"
+ exit(0)
+
+ test_name = re.sub(r'\..*', '', sys.argv[1])
+ test_name = re.sub(r'diff_', '', test_name)
+ autotest_filename = 'test_auto_%s.py' % test_name
+
+ # Dialogue
+ if os.path.isfile(autotest_filename):
+ replace = raw_input("Do you want to replace the existing auto test file %s?
[Y/N]" % autotest_filename)
+ while replace not in ['y', 'Y', 'n', 'N']:
+ replace = raw_input("Please enter either 'Y' of
'N'!")
+ if replace in ['n', 'N']:
+ print 'Aborting..'
+ exit(0)
+
+ counter = 0
+
+ with open(autotest_filename, 'w') as auto:
+ auto.write(header)
+ with open(sys.argv[1], 'r') as diff:
+ for line in diff:
+
+ if re.match(r'@@.*', line):
+ if counter > 0:
+ auto.write(function_end)
+ auto.write(function_start(counter))
+ counter += 1
+ continue
+
+ elif counter == 0 or len(line) <= 1:
+ continue
+
+ if not re.match(r'[+|-].+', line):
+ continue
+
+ if not re.match(r'[+|-].+', line) and line[0] not in
['+', '-']:
+ auto.write(line[1:])
+
+ elif re.match(r'[+]{3}.*', line) or re.match(r'[-]{3}.*',
line):
+ continue
+
+ elif re.match(r'[-]\s*html\..*', line):
+ pattern = re.compile(r'[-]\s*html\.')
+ auto.write(re.sub(r'\s*html\.', ' old.', line[1:],
count=1))
+
+ elif re.match(r'[+]\s*html\..*', line):
+ pattern = re.compile(r'\s*html\.')
+ auto.write(pattern.sub(' new.', line[1:], count=1))
+
+ else:
+ auto.write(line[1:])
+
+ if(counter > 0):
+ auto.write(function_end)
diff --git a/tests/web/auto_refactor.py b/tests/web/auto_refactor.py
new file mode 100644
index 0000000..144ed74
--- /dev/null
+++ b/tests/web/auto_refactor.py
@@ -0,0 +1,142 @@
+import re
+import sys
+from bs4 import BeautifulSoup as bs
+from bs4 import NavigableString
+
+
+def eval_tag(tag_str, next_one, next_inbetween):
+
+ skip_next = False
+ children = list(bs(tag_str, 'html5lib').body.children)
+
+ if tag_str[1] == '/':
+ addendum = "html.close_%s()" % re.sub("<|[/]|>",
'' , tag_str)
+
+# elif '%' + 's' in tag_str:
+# addendum = ''
+
+ elif children and not isinstance(children[0], NavigableString):
+ tag_name = ''
+ attrs = ''
+ tag = children[0]
+
+ tag_name = tag.name
+ for key, val in tag.attrs.iteritems():
+ if key in ["class", "id", "type",
"for"]:
+ key += '_'
+ if attrs and key and val:
+ attrs += ", "
+ if isinstance(val, list):
+ val = "[\"" + "\", \"".join(val) +
"\"]"
+ attrs += "%s=%s" % (key, val)
+ else:
+ attrs += "%s=\"%s\"" % (key, val)
+
+ # See if we can close the tag right away
+ if next_one and next_one[1] == '/' and next_one ==
("</%s>" % tag_name):
+ addendum = "html.%s(%s%s)" % (tag_name, next_inbetween, ",
" + attrs if attrs else '')
+ skip_next = True
+ elif tag_name in ['br', 'hr', 'img']:
+ addendum = "html.%s(%s)" % (tag_name, attrs)
+ else:
+ addendum = "html.open_%s(%s)" % (tag_name, attrs)
+ else:
+ tag_name = tag_str.lstrip(' ').lstrip('<').split('
')[0].rstrip("/").rstrip(">")
+ attrs = tag_str.lstrip(' ').lstrip('<').rstrip('
').rstrip('>').lstrip(tag_name)
+ addendum = "html.open_%s(%s)" % (tag_name, attrs)
+
+ return addendum, skip_next
+
+
+def append_to_html(html, indent, addendum):
+ return "%s\n%s%s" %(html, ' ' * indent, "%s" % addendum)
+
+
+def split_html(text):
+ index = 1
+ while index < len(text) and text[index - 1] != "(":
+ index += 1
+ open_braces = 1
+ while index < len(text) and open_braces > 0:
+ if text[index] == "(":
+ open_braces += 1
+ elif text[index] == ")":
+ open_braces -= 1
+ index += 1
+ while index < len(text) and text[index] != "\n":
+ index += 1
+ return text[:index], text[index:]
+
+# this function does a big chunk of the refactoring for me
+def replace_tags(html, indent = 0):
+
+ # I want to refactor only lines with html.write
+ if not html.lstrip(' ').startswith('html.write('):
+ return html
+
+ # unbalanced paranthesis indicates sth that goes across line border
+ if html.count('(') != html.count(')'):
+ return html
+
+ html, rest = split_html(html)
+ orig_html = html
+
+ if len(html.split(" % ")) == 2:
+ html, string_input = html.split(" % ")
+ string_input =
string_input.lstrip("(").rstrip("$").rstrip("\n").rstrip('
').rstrip(")")
+ for input in string_input.split(","):
+ if ("%" + "s") in html:
+ html = re.sub("%" + "s", input, html, 1)
+
+ tags = re.findall(r'<[^<]*>', html)
+ if len(tags) == 0:
+ return orig_html + rest
+
+ inbetween = re.split(r'<[^<]*>',
re.sub(r'\s*html\.write\([\'|"]?', '', html, 1))
+ inbetween[-1] = ''.join(list(reversed(re.sub(r'\n\)["|\']',
'', ''.join(list(reversed(inbetween[-1]))), count=1))))
+
+ html = orig_html + "\n(new)"
+
+ if inbetween[0].strip(' ') not in ['', '\n']:
+ html = append_to_html(html, indent, "html.write(%s)" % inbetween[0])
+
+ # Iterate all tags
+ counter = 0
+ skip_next = False
+ while counter < len(tags):
+ tag_str = tags[counter]
+ next_one = tags[counter + 1] if counter + 1 < len(tags) else None
+ addendum, skip_next = eval_tag(tag_str, next_one, inbetween[counter + 1])
+ if not skip_next and addendum.strip(' '):
+ html = append_to_html(html, indent, addendum)
+
+ counter += 1
+
+ if not skip_next and inbetween[counter].strip(' ') not in ['',
'\n']:
+ html = append_to_html(html, indent, "html.write(%s)" %
inbetween[counter])
+
+ return html + rest + "\n(/new)"
+
+
+import re
+html = sys.argv[1]
+if html.endswith('.py'):
+ whole_text = ''
+ with open(html, 'r') as rfile:
+ whole_text = "".join(line for line in rfile)
+ parts = whole_text.split("html.write(")
+ with open("refactored_file.py", "w") as wfile:
+ part = parts.pop(0)
+ wfile.write(part)
+ indent = 0
+ while indent < len(part) and part[len(part) - 1 - indent] == ' ':
+ indent += 1
+ for part in parts:
+ part = "html.write(" + part
+ wfile.write(replace_tags(part, indent))
+ indent = 0
+ while indent < len(part) and part[len(part) - 1 - indent] == ' ':
+ indent += 1
+else:
+ print replace_tags(html)
+