You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

237 lines
8.9 KiB

10 years ago
10 years ago
10 years ago
  1. '''
  2. Created on Feb 2, 2014
  3. @author: Chris
  4. TODO:
  5. - test no argparse module
  6. - test argparse in main
  7. - test argparse in try/catch
  8. -
  9. '''
  10. import os
  11. import ast
  12. import unittest
  13. from gooey.python_bindings import source_parser
  14. basic_pyfile = '''
  15. import os
  16. def say_jello():
  17. print "Jello!"
  18. def main():
  19. print "hello!"
  20. parser = ArgumentParser(description='Example Argparse Program', formatter_class=RawDescriptionHelpFormatter)
  21. parser.add_argument("filename", help="filename")
  22. parser.add_argument("-r", "--recursive", dest="recurse", action="store_true",
  23. help="recurse into subfolders [default: %(default)s]")
  24. parser.add_argument("-v", "--verbose", dest="verbose", action="count",
  25. help="set verbosity level [default: %(default)s]")
  26. parser.add_argument("-i", "--include", action="append",
  27. help="only include paths matching this regex pattern. Note: exclude is given preference over include. [default: %(default)s]",
  28. metavar="RE")
  29. parser.add_argument("-m", "--mycoolargument", help="mycoolargument")
  30. parser.add_argument("-e", "--exclude", dest="exclude",
  31. help="exclude paths matching this regex pattern. [default: %(default)s]", metavar="RE")
  32. parser.add_argument('-V', '--version', action='version')
  33. parser.add_argument('-T', '--tester', choices=['yes', 'no'])
  34. parser.add_argument(dest="paths", help="paths to folder(s) with source file(s) [default: %(default)s]",
  35. metavar="path", nargs='+')
  36. if __name__ == '__main__':
  37. main()
  38. '''
  39. class TestSourceParser(unittest.TestCase):
  40. PATH = os.path.join(os.path.dirname(__file__), 'examples')
  41. def module_path(self, name):
  42. return os.path.join(self.PATH, name)
  43. def setUp(self):
  44. self._mockapp = self.module_path('examples.py')
  45. self._module_with_noargparse = self.module_path('module_with_no_argparse.py')
  46. self._module_with_arparse_in_try = self.module_path('TODO.py')
  47. self._module_with_argparse_in_main = self.module_path('example_argparse_souce_in_main.py')
  48. def test_should_throw_parser_exception_if_no_argparse_found_in_module(self):
  49. with self.assertRaises(source_parser.ParserError):
  50. source_parser.parse_source_file(self._module_with_noargparse)
  51. def test_find_main(self):
  52. example_source = '''
  53. def main(): pass
  54. '''
  55. nodes = ast.parse(example_source)
  56. main_node = source_parser.find_main(nodes)
  57. self.assertEqual('main', main_node.name)
  58. def test_find_main_throws_exception_if_not_found(self):
  59. example_source = '''
  60. def some_cool_function_that_is_not_main(): pass
  61. '''
  62. with self.assertRaises(source_parser.ParserError):
  63. nodes = ast.parse(example_source)
  64. main_node = source_parser.find_main(nodes)
  65. self.assertEqual('main', main_node.name)
  66. def test_find_try_blocks_finds_all_tryblock_styles(self):
  67. example_source = '''
  68. try: a = 1
  69. except: pass
  70. try: pass
  71. finally: pass
  72. try: pass
  73. except: pass
  74. else: pass
  75. '''
  76. nodes = ast.parse(example_source)
  77. try_blocks = source_parser.find_try_blocks(nodes)
  78. self.assertEqual(3, len(try_blocks))
  79. def test_find_try_blocks_returns_empty_if_no_blocks_present(self):
  80. example_source = 'def main(): pass'
  81. nodes = ast.parse(example_source)
  82. result = source_parser.find_try_blocks(nodes)
  83. self.assertEqual(list(), result)
  84. def test_find_argparse_located_object_when_imported_by_direct_name(self):
  85. example_source = '''
  86. def main():
  87. parser = ArgumentParser(description='Example Argparse Program', formatter_class=RawDescriptionHelpFormatter)
  88. '''
  89. nodes = ast.parse(example_source)
  90. main_node = source_parser.find_main(nodes)
  91. self.assertEqual('main', main_node.name)
  92. containing_block = source_parser.find_block_containing_argparse([main_node])
  93. self.assertTrue(containing_block is not None)
  94. def test_find_argparse_located_object_when_access_through_module_dot_notation(self):
  95. example_source = '''
  96. def main():
  97. parser = argparse.ArgumentParser(description='Example Argparse Program', formatter_class=RawDescriptionHelpFormatter)
  98. '''
  99. nodes = ast.parse(example_source)
  100. main_node = source_parser.find_main(nodes)
  101. self.assertEqual('main', main_node.name)
  102. containing_block = source_parser.find_block_containing_argparse([main_node])
  103. self.assertTrue(containing_block is not None)
  104. def test_find_argparse_locates_assignment_stmnt_in_main(self):
  105. nodes = ast.parse(source_parser._openfile(self._module_with_argparse_in_main))
  106. main_node = source_parser.find_main(nodes)
  107. self.assertEqual('main', main_node.name)
  108. containing_block = source_parser.find_block_containing_argparse([main_node])
  109. self.assertTrue(containing_block is not None)
  110. self.assertEqual('main', containing_block.name)
  111. def test_find_argparse_locates_assignment_stmnt_in_try_block(self):
  112. nodes = ast.parse(source_parser._openfile(self._module_with_arparse_in_try))
  113. main_node = source_parser.find_main(nodes)
  114. self.assertEqual('main', main_node.name)
  115. try_nodes = source_parser.find_try_blocks(main_node)
  116. self.assertTrue(len(try_nodes) > 0)
  117. containing_block = source_parser.find_block_containing_argparse([main_node] + try_nodes)
  118. self.assertEqual(ast.TryExcept, type(containing_block))
  119. def test_find_argparse_throws_exception_if_not_found(self):
  120. with self.assertRaises(source_parser.ParserError):
  121. nodes = ast.parse(source_parser._openfile(self._module_with_noargparse))
  122. main_node = source_parser.find_main(nodes)
  123. self.assertEqual('main', main_node.name)
  124. try_nodes = source_parser.find_try_blocks(main_node)
  125. containing_block = source_parser.find_block_containing_argparse([main_node] + try_nodes)
  126. def test_has_instantiator_returns_true_if_object_found(self):
  127. source = '''
  128. parser = ArgumentParser(description='Example Argparse Program', formatter_class=RawDescriptionHelpFormatter)
  129. parser.add_argument("filename", help="filename")
  130. '''
  131. nodes = ast.parse(source)
  132. self.assertTrue(source_parser.has_instantiator(nodes.body[0], 'ArgumentParser'))
  133. def test_has_instantiator_returns_false_if_object_not_found(self):
  134. source = '''
  135. parser = NopeParser(description='Example Argparse Program', formatter_class=RawDescriptionHelpFormatter)
  136. parser.add_argument("filename", help="filename")
  137. '''
  138. nodes = ast.parse(source)
  139. self.assertFalse(source_parser.has_instantiator(nodes.body[0], 'ArgumentParser'))
  140. def test_has_assignment_returns_true_if_object_found(self):
  141. source = '''
  142. parser = ArgumentParser(description='Example Argparse Program', formatter_class=RawDescriptionHelpFormatter)
  143. parser.add_argument("filename", help="filename")
  144. '''
  145. nodes = ast.parse(source)
  146. self.assertTrue(source_parser.has_assignment(nodes.body[1], 'add_argument'))
  147. def test_has_assignment_returns_false_if_object_not_found(self):
  148. source = '''
  149. parser = ArgumentParser(description='Example Argparse Program', formatter_class=RawDescriptionHelpFormatter)
  150. parser.add_argument("filename", help="filename")
  151. '''
  152. nodes = ast.parse(source)
  153. self.assertFalse(source_parser.has_instantiator(nodes.body[1], 'add_argument'))
  154. def test_parser_identifies_import_module(self):
  155. source = '''
  156. import os
  157. import itertools
  158. from os import path
  159. '''
  160. import _ast
  161. nodes = ast.parse(source)
  162. module_imports = source_parser.get_nodes_by_instance_type(nodes, _ast.Import)
  163. self.assertEqual(2, len(module_imports))
  164. def test_parser_identifies_import_from(self):
  165. source = '''
  166. import os
  167. import itertools
  168. from os import path
  169. from gooey.gooey_decorator import Gooey
  170. '''
  171. import _ast
  172. nodes = ast.parse(source)
  173. from_imports = source_parser.get_nodes_by_instance_type(nodes, _ast.ImportFrom)
  174. self.assertEqual(2, len(from_imports))
  175. def test_get_indent_return_indent_amount_for_tabs_and_spaces(self):
  176. spaced_lines = ["def main"," def main"," def main"," def main"]
  177. expected_indent = ["", " ", " ", " "]
  178. for line, expected in zip(spaced_lines, expected_indent):
  179. self.assertEqual(expected, source_parser.get_indent(line))
  180. # def test_parse_source_file__file_with_argparse_in_main__succesfully_finds_and_returns_ast_obejcts(self):
  181. # ast_objects = source_parser.parse_source_file(self._module_with_argparse_in_main)
  182. # for obj in ast_objects:
  183. # self.assertTrue(type(obj) in (ast.Assign, ast.Expr))
  184. #
  185. # def test_parse_source_file__file_with_argparse_in_try_block__succesfully_finds_and_returns_ast_obejcts(self):
  186. # ast_objects = source_parser.parse_source_file(self._module_with_arparse_in_try)
  187. # for obj in ast_objects:
  188. # self.assertTrue(type(obj) in (ast.Assign, ast.Expr))
  189. if __name__ == "__main__":
  190. #import sys;sys.argv = ['', 'Test.testName']
  191. unittest.main()