# Path: pythoscope/astvisitor.py
# class ASTVisitor(object):
#     DEFAULT_PATTERNS = [
#         ('_visit_all', "file_input< nodes=any* >"),
#         ('_visit_all', "suite< nodes=any* >"),
#         ('_visit_class', "body=classdef< 'class' name=NAME ['(' bases=any ')'] ':' any >"),
#         ('_visit_function', "body=funcdef< 'def' name=NAME parameters< '(' [args=any] ')' > ':' any >"),
#         ('_visit_import', "body=import_name< 'import' names=any > | body=import_from< 'from' import_from=any 'import' names=any >"),
#         ('_visit_lambda_assign', "expr_stmt< name=NAME '=' lambdef< 'lambda' [args=any] ':' any > >"),
#         ('_visit_main_snippet', "body=if_stmt< 'if' comparison< '__name__' '==' (\"'__main__'\" | '\"__main__\"' ) > ':' any >"),
#     ]
# 
#     def __init__(self):
#         self.patterns = []
#         for method, pattern in self.DEFAULT_PATTERNS:
#             self.register_pattern(method, pattern)
# 
#     def register_pattern(self, method, pattern):
#         """Register method to handle given pattern.
#         """
#         self.patterns.append((method, compile_pattern(pattern)))
# 
#     def visit(self, tree):
#         """Main entry point of the ASTVisitor class.
#         """
#         if isinstance(tree, Leaf):
#             self.visit_leaf(tree)
#         elif isinstance(tree, Node):
#             self.visit_node(tree)
#         elif isinstance(tree, list):
#             for subtree in tree:
#                 self.visit(subtree)
#         else:
#             raise ASTError("Unknown tree type: %r." % tree)
# 
#     def visit_leaf(self, leaf):
#         pass
# 
#     def visit_node(self, node):
#         for method, pattern in self.patterns:
#             results = {}
#             if pattern.match(node, results):
#                 getattr(self, method)(results)
#                 break
#         else:
#             # For unknown nodes simply descend to their list of children.
#             self.visit(node.children)
# 
#     def visit_class(self, name, bases, body):
#         self.visit(body.children)
# 
#     def visit_function(self, name, args, body):
#         self.visit(body.children)
# 
#     def visit_import(self, names, import_from, body):
#         pass
# 
#     def visit_lambda_assign(self, name, args):
#         pass
# 
#     def visit_main_snippet(self, body):
#         pass
# 
#     def _visit_all(self, results):
#         self.visit(results['nodes'])
# 
#     def _visit_class(self, results):
#         self.visit_class(name=results['name'].value,
#                          bases=derive_class_names(results.get('bases')),
#                          body=results['body'])
# 
#     def _visit_function(self, results):
#         self.visit_function(name=results['name'].value,
#                             args=derive_arguments(results.get('args', [])),
#                             body=results['body'])
# 
#     def _visit_import(self, results):
#         self.visit_import(names=derive_import_names(results['names']),
#                           import_from=derive_import_name(results.get('import_from')),
#                           body=results['body'])
# 
#     def _visit_lambda_assign(self, results):
#         self.visit_lambda_assign(name=results['name'].value,
#                                  args=derive_arguments(results.get('args', [])))
# 
#     def _visit_main_snippet(self, results):
#         self.visit_main_snippet(body=results['body'])
# 
# Path: pythoscope/astbuilder.py
# def parse(code):
#     """String -> AST
# 
#     Parse the string and return its AST representation. May raise
#     a ParseError exception.
#     """
#     added_newline = False
#     if not code.endswith("\n"):
#         code += "\n"
#         added_newline = True
# 
#     try:
#         drv = driver.Driver(pygram.python_grammar, pytree.convert)
#         result = drv.parse_string(code, True)
#     except ParseError:
#         log.debug("Had problems parsing:\n%s\n" % quoted_block(code))
#         raise
# 
#     # Always return a Node, not a Leaf.
#     if isinstance(result, Leaf):
#         result = Node(syms.file_input, [result])
# 
#     result.added_newline = added_newline
# 
#     return result
# 
# def regenerate(tree):
#     """AST -> String
# 
#     Regenerate the source code from the AST tree.
#     """
#     if hasattr(tree, 'added_newline') and tree.added_newline:
#         return str(tree)[:-1]
#     else:
#         return str(tree)


from pythoscope.astvisitor import ASTVisitor
from pythoscope.astbuilder import parse, regenerate
from assertions import *
        class TestVisitor(ASTVisitor):
            def visit_import(self, names, import_from, body):
                method(names, import_from)
                method_called[0] = True

        TestVisitor().visit(parse(code))
        assert method_called[0], "visit_import wasn't called at all"

class TestASTVisitorMainSnippet:
    def test_detects_the_main_snippet(self):
        code = "import unittest\n\nif __name__ == '__main__':\n    unittest.main()\n"
        def assertions(body):
            assert_equal("\nif __name__ == '__main__':\n    unittest.main()\n", body)

        self._test_main_snippet(code, assertions)

    def test_detects_main_snippet_with_different_quotes(self):
        code = 'import unittest\n\nif __name__ == "__main__":\n    unittest.main()\n'
        def assertions(body):
            assert_equal('\nif __name__ == "__main__":\n    unittest.main()\n', body)

        self._test_main_snippet(code, assertions)

    def _test_main_snippet(self, code, method):
        method_called = [False]
        class TestVisitor(ASTVisitor):
            def visit_main_snippet(self, body):
                method(regenerate(body))
                method_called[0] = True


# Path: pythoscope/astvisitor.py
# class ASTVisitor(object):
#     DEFAULT_PATTERNS = [
#         ('_visit_all', "file_input< nodes=any* >"),
#         ('_visit_all', "suite< nodes=any* >"),
#         ('_visit_class', "body=classdef< 'class' name=NAME ['(' bases=any ')'] ':' any >"),
#         ('_visit_function', "body=funcdef< 'def' name=NAME parameters< '(' [args=any] ')' > ':' any >"),
#         ('_visit_import', "body=import_name< 'import' names=any > | body=import_from< 'from' import_from=any 'import' names=any >"),
#         ('_visit_lambda_assign', "expr_stmt< name=NAME '=' lambdef< 'lambda' [args=any] ':' any > >"),
#         ('_visit_main_snippet', "body=if_stmt< 'if' comparison< '__name__' '==' (\"'__main__'\" | '\"__main__\"' ) > ':' any >"),
#     ]
# 
#     def __init__(self):
#         self.patterns = []
#         for method, pattern in self.DEFAULT_PATTERNS:
#             self.register_pattern(method, pattern)
# 
#     def register_pattern(self, method, pattern):
#         """Register method to handle given pattern.
#         """
#         self.patterns.append((method, compile_pattern(pattern)))
# 
#     def visit(self, tree):
#         """Main entry point of the ASTVisitor class.
#         """
#         if isinstance(tree, Leaf):
#             self.visit_leaf(tree)
#         elif isinstance(tree, Node):
#             self.visit_node(tree)
#         elif isinstance(tree, list):
#             for subtree in tree:
#                 self.visit(subtree)
#         else:
#             raise ASTError("Unknown tree type: %r." % tree)
# 
#     def visit_leaf(self, leaf):
#         pass
# 
#     def visit_node(self, node):
#         for method, pattern in self.patterns:
#             results = {}
#             if pattern.match(node, results):
#                 getattr(self, method)(results)
#                 break
#         else:
#             # For unknown nodes simply descend to their list of children.
#             self.visit(node.children)
# 
#     def visit_class(self, name, bases, body):
#         self.visit(body.children)
# 
#     def visit_function(self, name, args, body):
#         self.visit(body.children)
# 
#     def visit_import(self, names, import_from, body):
#         pass
# 
#     def visit_lambda_assign(self, name, args):
#         pass
# 
#     def visit_main_snippet(self, body):
#         pass
# 
#     def _visit_all(self, results):
#         self.visit(results['nodes'])
# 
#     def _visit_class(self, results):
#         self.visit_class(name=results['name'].value,
#                          bases=derive_class_names(results.get('bases')),
#                          body=results['body'])
# 
#     def _visit_function(self, results):
#         self.visit_function(name=results['name'].value,
#                             args=derive_arguments(results.get('args', [])),
#                             body=results['body'])
# 
#     def _visit_import(self, results):
#         self.visit_import(names=derive_import_names(results['names']),
#                           import_from=derive_import_name(results.get('import_from')),
#                           body=results['body'])
# 
#     def _visit_lambda_assign(self, results):
#         self.visit_lambda_assign(name=results['name'].value,
#                                  args=derive_arguments(results.get('args', [])))
# 
#     def _visit_main_snippet(self, results):
#         self.visit_main_snippet(body=results['body'])
# 
# Path: pythoscope/astbuilder.py
# def parse(code):
#     """String -> AST
# 
#     Parse the string and return its AST representation. May raise
#     a ParseError exception.
#     """
#     added_newline = False
#     if not code.endswith("\n"):
#         code += "\n"
#         added_newline = True
# 
#     try:
#         drv = driver.Driver(pygram.python_grammar, pytree.convert)
#         result = drv.parse_string(code, True)
#     except ParseError:
#         log.debug("Had problems parsing:\n%s\n" % quoted_block(code))
#         raise
# 
#     # Always return a Node, not a Leaf.
#     if isinstance(result, Leaf):
#         result = Node(syms.file_input, [result])
# 
#     result.added_newline = added_newline
# 
#     return result
# 
# def regenerate(tree):
#     """AST -> String
# 
#     Regenerate the source code from the AST tree.
#     """
#     if hasattr(tree, 'added_newline') and tree.added_newline:
#         return str(tree)[:-1]
#     else:
#         return str(tree)


# Path: test/test_astvisitor.py
from pythoscope.astvisitor import ASTVisitor
from pythoscope.astbuilder import parse, regenerate
from assertions import *

        class TestVisitor(ASTVisitor):
            def visit_import(self, names, import_from, body):
                method(names, import_from)
                method_called[0] = True

        TestVisitor().visit(parse(code))
        assert method_called[0], "visit_import wasn't called at all"

class TestASTVisitorMainSnippet:
    def test_detects_the_main_snippet(self):
        code = "import unittest\n\nif __name__ == '__main__':\n    unittest.main()\n"
        def assertions(body):
            assert_equal("\nif __name__ == '__main__':\n    unittest.main()\n", body)

        self._test_main_snippet(code, assertions)

    def test_detects_main_snippet_with_different_quotes(self):
        code = 'import unittest\n\nif __name__ == "__main__":\n    unittest.main()\n'
        def assertions(body):
            assert_equal('\nif __name__ == "__main__":\n    unittest.main()\n', body)

        self._test_main_snippet(code, assertions)

    def _test_main_snippet(self, code, method):
        method_called = [False]
        class TestVisitor(ASTVisitor):
            def visit_main_snippet(self, body):
                method(regenerate(body))
                method_called[0] = True


        TestVisitor().visit(parse(code))