Include the python_gut tool
This commit is contained in:
parent
5b894d85b0
commit
3e9601033a
3 changed files with 257 additions and 9 deletions
72
gut.py
Executable file
72
gut.py
Executable file
|
|
@ -0,0 +1,72 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright (C) 2015-2016 Andrew Hamilton. All rights reserved.
|
||||||
|
# Licensed under the Artistic License 2.0.
|
||||||
|
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
USAGE = """Usage: gut.py <python file>
|
||||||
|
|
||||||
|
# gut.py test.py"""
|
||||||
|
|
||||||
|
|
||||||
|
INDENT_SIZE = 4
|
||||||
|
TAB_SIZE = 4
|
||||||
|
|
||||||
|
|
||||||
|
def indentation_of_line(line):
|
||||||
|
indentation = 0
|
||||||
|
for character in line:
|
||||||
|
if character == " ":
|
||||||
|
indentation += 1
|
||||||
|
elif character == "\t":
|
||||||
|
indentation += TAB_SIZE
|
||||||
|
elif character == "\n":
|
||||||
|
return None
|
||||||
|
else: # Is a non-whitespace character.
|
||||||
|
return indentation
|
||||||
|
|
||||||
|
|
||||||
|
def is_start_line_of_signature(line):
|
||||||
|
return re.match("^\s*def\s", line) is not None
|
||||||
|
|
||||||
|
|
||||||
|
def is_end_line_of_signature(line):
|
||||||
|
return (re.match(".*\):\s*\n$", line) is not None or
|
||||||
|
re.match(".*\):\s*#.*\n$", line) is not None)
|
||||||
|
|
||||||
|
|
||||||
|
def gut_module(module_contents):
|
||||||
|
SIGNATURE, BODY, TOP_LEVEL = 1, 2, 3
|
||||||
|
state = TOP_LEVEL
|
||||||
|
body_depth = 0
|
||||||
|
result = []
|
||||||
|
for line in module_contents.splitlines(keepends=True):
|
||||||
|
indent = indentation_of_line(line)
|
||||||
|
if state == BODY and indent is not None and \
|
||||||
|
indent < body_depth:
|
||||||
|
state = TOP_LEVEL
|
||||||
|
result.append("\n")
|
||||||
|
if state == TOP_LEVEL and is_start_line_of_signature(line):
|
||||||
|
state = SIGNATURE
|
||||||
|
body_depth = indent + INDENT_SIZE
|
||||||
|
if state == SIGNATURE and is_end_line_of_signature(line):
|
||||||
|
result.append(line)
|
||||||
|
state = BODY
|
||||||
|
elif state != BODY:
|
||||||
|
result.append(line)
|
||||||
|
return "".join(result)
|
||||||
|
|
||||||
|
|
||||||
|
def main(module_path):
|
||||||
|
with open(module_path) as module_file:
|
||||||
|
print(gut_module(module_file.read()))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) != 2:
|
||||||
|
print(USAGE)
|
||||||
|
sys.exit(-1)
|
||||||
|
main(sys.argv[1])
|
||||||
178
gut_test.py
Executable file
178
gut_test.py
Executable file
|
|
@ -0,0 +1,178 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright (C) 2015-2016 Andrew Hamilton. All rights reserved.
|
||||||
|
# Licensed under the Artistic License 2.0.
|
||||||
|
|
||||||
|
import textwrap
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import gut
|
||||||
|
|
||||||
|
|
||||||
|
class GutTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_import(self):
|
||||||
|
program = "import hello"
|
||||||
|
self.assertEqual(gut.gut_module(program), program)
|
||||||
|
|
||||||
|
def test_import_and_function(self):
|
||||||
|
program = textwrap.dedent("""
|
||||||
|
import hello
|
||||||
|
|
||||||
|
def first():
|
||||||
|
a = 1
|
||||||
|
""")
|
||||||
|
expected = textwrap.dedent("""
|
||||||
|
import hello
|
||||||
|
|
||||||
|
def first():
|
||||||
|
""")
|
||||||
|
self.assertEqual(gut.gut_module(program), expected)
|
||||||
|
|
||||||
|
def test_import_and_function_and_command(self):
|
||||||
|
program = textwrap.dedent("""
|
||||||
|
import hello
|
||||||
|
|
||||||
|
def first():
|
||||||
|
a = 1
|
||||||
|
|
||||||
|
b = 1
|
||||||
|
""")
|
||||||
|
expected = textwrap.dedent("""
|
||||||
|
import hello
|
||||||
|
|
||||||
|
def first():
|
||||||
|
|
||||||
|
b = 1
|
||||||
|
""")
|
||||||
|
self.assertEqual(gut.gut_module(program), expected)
|
||||||
|
|
||||||
|
def test_import_and_class(self):
|
||||||
|
program = textwrap.dedent("""
|
||||||
|
import hello
|
||||||
|
|
||||||
|
class Foo:
|
||||||
|
|
||||||
|
def bar():
|
||||||
|
a = 1
|
||||||
|
""")
|
||||||
|
expected = textwrap.dedent("""
|
||||||
|
import hello
|
||||||
|
|
||||||
|
class Foo:
|
||||||
|
|
||||||
|
def bar():
|
||||||
|
""")
|
||||||
|
self.assertEqual(gut.gut_module(program), expected)
|
||||||
|
|
||||||
|
def test_short_blank_line_in_def(self):
|
||||||
|
program = textwrap.dedent("""
|
||||||
|
def bar():
|
||||||
|
a = 1
|
||||||
|
|
||||||
|
b = 2
|
||||||
|
""")
|
||||||
|
expected = textwrap.dedent("""
|
||||||
|
def bar():
|
||||||
|
""")
|
||||||
|
self.assertEqual(gut.gut_module(program), expected)
|
||||||
|
|
||||||
|
def test_nested_functions(self):
|
||||||
|
program = textwrap.dedent("""
|
||||||
|
def bar():
|
||||||
|
a = 1
|
||||||
|
def foo():
|
||||||
|
pass
|
||||||
|
b = 2
|
||||||
|
""")
|
||||||
|
expected = textwrap.dedent("""
|
||||||
|
def bar():
|
||||||
|
""")
|
||||||
|
self.assertEqual(gut.gut_module(program), expected)
|
||||||
|
|
||||||
|
def test_multiline_signature(self):
|
||||||
|
program = textwrap.dedent("""
|
||||||
|
def bar(a, b
|
||||||
|
c, d):
|
||||||
|
a = 1
|
||||||
|
""")
|
||||||
|
expected = textwrap.dedent("""
|
||||||
|
def bar(a, b
|
||||||
|
c, d):
|
||||||
|
""")
|
||||||
|
self.assertEqual(gut.gut_module(program), expected)
|
||||||
|
|
||||||
|
def test_tab_in_indentation(self):
|
||||||
|
program = textwrap.dedent("""
|
||||||
|
def bar():
|
||||||
|
a = 1
|
||||||
|
\tb=2
|
||||||
|
""")
|
||||||
|
expected = textwrap.dedent("""
|
||||||
|
def bar():
|
||||||
|
""")
|
||||||
|
self.assertEqual(gut.gut_module(program), expected)
|
||||||
|
|
||||||
|
def test_comment_in_signature_line(self):
|
||||||
|
program = textwrap.dedent("""
|
||||||
|
def bar(): # comment
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
expected = textwrap.dedent("""
|
||||||
|
def bar(): # comment
|
||||||
|
""")
|
||||||
|
self.assertEqual(gut.gut_module(program), expected)
|
||||||
|
|
||||||
|
def test_indented_comment_in_body(self):
|
||||||
|
program = textwrap.dedent("""
|
||||||
|
def bar():
|
||||||
|
pass
|
||||||
|
# comment
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
expected = textwrap.dedent("""
|
||||||
|
def bar():
|
||||||
|
""")
|
||||||
|
self.assertEqual(gut.gut_module(program), expected)
|
||||||
|
|
||||||
|
def test_non_indented_comment_in_body(self):
|
||||||
|
program = textwrap.dedent("""
|
||||||
|
def bar():
|
||||||
|
pass
|
||||||
|
# comment
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
expected = textwrap.dedent("""
|
||||||
|
def bar():
|
||||||
|
|
||||||
|
# comment
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
self.assertEqual(gut.gut_module(program), expected)
|
||||||
|
|
||||||
|
def test_non_indented_comment_after_body(self):
|
||||||
|
program = textwrap.dedent("""
|
||||||
|
def bar():
|
||||||
|
pass
|
||||||
|
pass
|
||||||
|
# comment
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
expected = textwrap.dedent("""
|
||||||
|
def bar():
|
||||||
|
|
||||||
|
# comment
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
self.assertEqual(gut.gut_module(program), expected)
|
||||||
|
|
||||||
|
def test_commented_out_function(self):
|
||||||
|
program = textwrap.dedent("""
|
||||||
|
# def bar():
|
||||||
|
# pass
|
||||||
|
""")
|
||||||
|
self.assertEqual(gut.gut_module(program), program)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
16
tools.py
16
tools.py
|
|
@ -25,6 +25,7 @@ import pygments.styles
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
import fill3
|
import fill3
|
||||||
|
import gut
|
||||||
import termstr
|
import termstr
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -245,15 +246,11 @@ def unittests(path):
|
||||||
unittests.dependencies = {"python3"}
|
unittests.dependencies = {"python3"}
|
||||||
|
|
||||||
|
|
||||||
def gut(path):
|
def python_gut(path):
|
||||||
status, output = Status.info, ""
|
with open(path) as module_file:
|
||||||
try:
|
output = gut.gut_module(module_file.read())
|
||||||
output = subprocess.check_output(
|
|
||||||
["/home/ahamilton/code/python-gut/gut.py", path])
|
|
||||||
except subprocess.CalledProcessError:
|
|
||||||
status = Status.failure
|
|
||||||
source_widget = _syntax_highlight_code(fix_input(output), path)
|
source_widget = _syntax_highlight_code(fix_input(output), path)
|
||||||
return status, source_widget
|
return Status.info, source_widget
|
||||||
|
|
||||||
|
|
||||||
def pydoc3(path):
|
def pydoc3(path):
|
||||||
|
|
@ -502,7 +499,8 @@ def generic_tools():
|
||||||
def tools_for_extension():
|
def tools_for_extension():
|
||||||
return {
|
return {
|
||||||
"py": [python_syntax, unittests, pydoc3, python3_coverage, profile,
|
"py": [python_syntax, unittests, pydoc3, python3_coverage, profile,
|
||||||
pep8, pyflakes, pylint3, gut, modulefinder, python3_mccabe],
|
pep8, pyflakes, pylint3, python_gut, modulefinder,
|
||||||
|
python3_mccabe],
|
||||||
"pyc": [disassemble_pyc],
|
"pyc": [disassemble_pyc],
|
||||||
"pl": [perl_syntax, perldoc, perltidy],
|
"pl": [perl_syntax, perldoc, perltidy],
|
||||||
"pm": [perl_syntax, perldoc, perltidy],
|
"pm": [perl_syntax, perldoc, perltidy],
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue