| from __future__ import print_function |
| from __future__ import unicode_literals |
| |
| import argparse |
| import ast |
| import collections |
| import traceback |
| |
| |
| DEBUG_STATEMENTS = set(['pdb', 'ipdb', 'pudb', 'q', 'rdb']) |
| |
| |
| DebugStatement = collections.namedtuple( |
| 'DebugStatement', ['name', 'line', 'col'], |
| ) |
| |
| |
| class ImportStatementParser(ast.NodeVisitor): |
| def __init__(self): |
| self.debug_import_statements = [] |
| |
| def visit_Import(self, node): |
| for node_name in node.names: |
| if node_name.name in DEBUG_STATEMENTS: |
| self.debug_import_statements.append( |
| DebugStatement(node_name.name, node.lineno, node.col_offset), |
| ) |
| |
| def visit_ImportFrom(self, node): |
| if node.module in DEBUG_STATEMENTS: |
| self.debug_import_statements.append( |
| DebugStatement(node.module, node.lineno, node.col_offset) |
| ) |
| |
| |
| def check_file_for_debug_statements(filename): |
| try: |
| ast_obj = ast.parse(open(filename).read(), filename=filename) |
| except SyntaxError: |
| print('{0} - Could not parse ast'.format(filename)) |
| print() |
| print('\t' + traceback.format_exc().replace('\n', '\n\t')) |
| print() |
| return 1 |
| visitor = ImportStatementParser() |
| visitor.visit(ast_obj) |
| if visitor.debug_import_statements: |
| for debug_statement in visitor.debug_import_statements: |
| print( |
| '{0}:{1}:{2} - {3} imported'.format( |
| filename, |
| debug_statement.line, |
| debug_statement.col, |
| debug_statement.name, |
| ) |
| ) |
| return 1 |
| else: |
| return 0 |
| |
| |
| def debug_statement_hook(argv=None): |
| parser = argparse.ArgumentParser() |
| parser.add_argument('filenames', nargs='*', help='Filenames to run') |
| args = parser.parse_args(argv) |
| |
| retv = 0 |
| for filename in args.filenames: |
| retv |= check_file_for_debug_statements(filename) |
| |
| return retv |
| |
| |
| if __name__ == '__main__': |
| exit(debug_statement_hook()) |