diff --git a/README.rst b/README.rst index 3af3782..3ff7c85 100644 --- a/README.rst +++ b/README.rst @@ -28,6 +28,13 @@ available in ``flake8``:: Changes ------- +3.1.0 - 2018-02-11 +`````````````````` +* Add a framework classifier for use in pypi.org +* Fix entry_point in setup.py leaving it off by default again +* Detect __import__ debugger statements +* Add support for `pudb` detection + 3.0.0 - 2017-05-11 ```````````````` * fix the refactor of the detector in 2.0.0 that was removed from pypi. diff --git a/flake8_debugger.py b/flake8_debugger.py index d3f0094..9e03d53 100644 --- a/flake8_debugger.py +++ b/flake8_debugger.py @@ -5,28 +5,16 @@ import pycodestyle -__version__ = '3.0.0' +__version__ = '3.1.0' -DEBUGGER_ERROR_CODE = 'T002' +DEBUGGER_ERROR_CODE = 'T100' debuggers = { - 'pdb': 'set_trace', - 'pudb': 'set_trace', - 'ipdb': 'set_trace', - 'IPython.terminal.embed': 'InteractiveShellEmbed', - 'IPython.frontend.terminal.embed': 'InteractiveShellEmbed', -} - - -VIOLATIONS = { - 'found': { - 'set_trace': 'T001 set_trace found.', - 'InteractiveShellEmbed': 'T003 InteractiveShellEmbed found.', - }, - 'declared': { - 'print': 'T101 Python 2.x reserved word print used.', - 'pprint': 'T103 pprint declared', - }, + 'pdb': ['set_trace'], + 'pudb': ['set_trace'], + 'ipdb': ['set_trace', 'sset_trace'], + 'IPython.terminal.embed': ['InteractiveShellEmbed'], + 'IPython.frontend.terminal.embed': ['InteractiveShellEmbed'], } @@ -42,8 +30,8 @@ def __init__(self, *args, **kwargs): self.debuggers_imported = {} def visit_Call(self, node): - debugger_method_names = chain(debuggers.values(), self.debuggers_traces_names.values()) - is_debugger_function = getattr(node.func, "id", None) in list(debugger_method_names) + debugger_method_names = list(chain(self.debuggers_traces_names.values(), *debuggers.values())) + is_debugger_function = getattr(node.func, "id", None) in debugger_method_names if is_debugger_function: if node.func.id in self.debuggers_traces_names.values(): debugger_method = next(item[0] for item in self.debuggers_traces_names.items() if item[1] == node.func.id) @@ -53,8 +41,7 @@ def visit_Call(self, node): else: entry.append('{0} trace found: {1} used as {2}'.format(DEBUGGER_ERROR_CODE, debugger_method, node.func.id)) - debugger_method_names = chain(debuggers.values(), self.debuggers_traces_names.values()) - is_debugger_attribute = getattr(node.func, "attr", None) in list(debugger_method_names) + is_debugger_attribute = getattr(node.func, "attr", None) in debugger_method_names if is_debugger_attribute: caller = getattr(node.func.value, "id", None) entry = self.debuggers_used.setdefault((node.lineno, node.col_offset), []) @@ -79,7 +66,7 @@ def visit_Import(self, node): def visit_ImportFrom(self, node): if node.module in list(debuggers.keys()): for name_node in node.names: - if name_node.name == debuggers[node.module]: + if name_node.name in debuggers[node.module]: if name_node.asname is not None: self.debuggers_traces_names[name_node.name] = name_node.asname entry = self.debuggers_traces_redefined.setdefault((node.lineno, node.col_offset), []) @@ -116,6 +103,7 @@ def run(self): parser = DebuggerFinder() parser.visit(self.tree) + for error, messages in parser.debuggers_used.items(): if not pycodestyle.noqa(self.lines[error[0] - 1]): for message in messages: diff --git a/setup.py b/setup.py index 65fc40a..a12f141 100644 --- a/setup.py +++ b/setup.py @@ -37,7 +37,7 @@ def get_long_description(): zip_safe=False, entry_points={ 'flake8.extension': [ - 'T = flake8_debugger:DebuggerChecker', + 'T100 = flake8_debugger:DebuggerChecker', ], }, install_requires=install_requires, diff --git a/test_linter.py b/test_linter.py index 2df37f3..7e1e8e4 100644 --- a/test_linter.py +++ b/test_linter.py @@ -62,8 +62,8 @@ def test_catches_simple_debugger(self): result = check_code_for_debugger_statements('from ipdb import set_trace as r\nr()') expected_result = [ - {'line': 2, 'message': 'T002 trace found: set_trace used as r', 'col': 0}, - {'line': 1, 'message': 'T002 import for set_trace found as r', 'col': 0}, + {'line': 2, 'message': 'T100 trace found: set_trace used as r', 'col': 0}, + {'line': 1, 'message': 'T100 import for set_trace found as r', 'col': 0}, ] assert result == expected_result @@ -72,8 +72,8 @@ def test_catches_simple_debugger_when_called_off_lib(self): result = check_code_for_debugger_statements('import ipdb\nipdb.set_trace()') expected_result = [ - {'line': 2, 'message': 'T002 trace found: ipdb.set_trace used', 'col': 0}, - {'line': 1, 'message': 'T002 import for ipdb found', 'col': 0}, + {'line': 2, 'message': 'T100 trace found: ipdb.set_trace used', 'col': 0}, + {'line': 1, 'message': 'T100 import for ipdb found', 'col': 0}, ] assert result == expected_result @@ -82,7 +82,7 @@ def test_catches_simple_debugger_when_called_off_global(self): result = check_code_for_debugger_statements("__import__('ipdb').set_trace()") expected_result = [ - {'line': 1, 'message': 'T002 trace found: set_trace used', 'col': 0}, + {'line': 1, 'message': 'T100 trace found: set_trace used', 'col': 0}, ] assert result == expected_result @@ -92,8 +92,8 @@ def test_catches_simple_debugger_when_called_off_var(self): result = check_code_for_debugger_statements('import ipdb\ntest = ipdb.set_trace\ntest()') expected_result = [ - {'line': 1, 'message': 'T002 import for ipdb found', 'col': 0}, - {'line': 3, 'message': 'T002 trace found: ipdb.set_trace used', 'col': 0} + {'line': 1, 'message': 'T100 import for ipdb found', 'col': 0}, + {'line': 3, 'message': 'T100 trace found: ipdb.set_trace used', 'col': 0} ] assert result == expected_result @@ -105,7 +105,7 @@ def test_skip_import(self): result = check_code_for_debugger_statements('from ipdb import set_trace as r # noqa\nr()') expected_result = [ - {'line': 2, 'message': 'T002 trace found: set_trace used as r', 'col': 0} + {'line': 2, 'message': 'T100 trace found: set_trace used as r', 'col': 0} ] assert result == expected_result @@ -115,7 +115,7 @@ def test_skip_usage(self): result = check_code_for_debugger_statements('from ipdb import set_trace as r\nr() # noqa') expected_result = [ - {'line': 1, 'message': 'T002 import for set_trace found as r', 'col': 0}, + {'line': 1, 'message': 'T100 import for set_trace found as r', 'col': 0}, ] assert result == expected_result @@ -132,22 +132,22 @@ def test_skip_import_and_usage(self): class TestImportCases(object): def test_import_multiple(self): result = check_code_for_debugger_statements('import math, ipdb, collections') - assert result == [{'col': 0, 'line': 1, 'message': 'T002 import for ipdb found'}] + assert result == [{'col': 0, 'line': 1, 'message': 'T100 import for ipdb found'}] def test_import(self): result = check_code_for_debugger_statements('import pdb') - assert result == [{'col': 0, 'line': 1, 'message': 'T002 import for pdb found'}] + assert result == [{'col': 0, 'line': 1, 'message': 'T100 import for pdb found'}] def test_import_interactive_shell_embed(self): result = check_code_for_debugger_statements('from IPython.terminal.embed import InteractiveShellEmbed') - assert result == [{'col': 0, 'line': 1, 'message': 'T002 import for InteractiveShellEmbed found'}] + assert result == [{'col': 0, 'line': 1, 'message': 'T100 import for InteractiveShellEmbed found'}] def test_import_both_same_line(self): result = check_code_for_debugger_statements('import pdb, ipdb') result = sorted(result, key=lambda debugger: debugger['message']) expected_result = [ - {'col': 0, 'line': 1, 'message': 'T002 import for ipdb found'}, - {'col': 0, 'line': 1, 'message': 'T002 import for pdb found'}, + {'col': 0, 'line': 1, 'message': 'T100 import for ipdb found'}, + {'col': 0, 'line': 1, 'message': 'T100 import for pdb found'}, ] assert result == expected_result @@ -165,8 +165,8 @@ def test_import_ipython_terminal_embed_use_InteractiveShellEmbed(self): result = check_code_for_debugger_statements('from IPython.terminal.embed import InteractiveShellEmbed; InteractiveShellEmbed()()') expected_result = [ - {'col': 58, 'line': 1, 'message': 'T002 trace found: InteractiveShellEmbed used'}, - {'col': 0, 'line': 1, 'message': 'T002 import for InteractiveShellEmbed found'} + {'col': 58, 'line': 1, 'message': 'T100 trace found: InteractiveShellEmbed used'}, + {'col': 0, 'line': 1, 'message': 'T100 import for InteractiveShellEmbed found'} ] try: @@ -181,8 +181,8 @@ def test_import_ipdb_use_set_trace(self): result = check_code_for_debugger_statements('import ipdb;ipdb.set_trace();') expected_result = [ - {'col': 12, 'line': 1, 'message': 'T002 trace found: ipdb.set_trace used'}, - {'col': 0, 'line': 1, 'message': 'T002 import for ipdb found'} + {'col': 12, 'line': 1, 'message': 'T100 trace found: ipdb.set_trace used'}, + {'col': 0, 'line': 1, 'message': 'T100 import for ipdb found'} ] try: @@ -197,8 +197,8 @@ def test_import_pdb_use_set_trace(self): result = check_code_for_debugger_statements('import pdb;pdb.set_trace();') expected_result = [ - {'col': 11, 'line': 1, 'message': 'T002 trace found: pdb.set_trace used'}, - {'col': 0, 'line': 1, 'message': 'T002 import for pdb found'}, + {'col': 11, 'line': 1, 'message': 'T100 trace found: pdb.set_trace used'}, + {'col': 0, 'line': 1, 'message': 'T100 import for pdb found'}, ] try: @@ -213,9 +213,9 @@ def test_import_pdb_use_set_trace_twice(self): result = check_code_for_debugger_statements('import pdb;pdb.set_trace() and pdb.set_trace();') expected_result = [ - {'col': 11, 'line': 1, 'message': 'T002 trace found: pdb.set_trace used'}, - {'col': 31, 'line': 1, 'message': 'T002 trace found: pdb.set_trace used'}, - {'col': 0, 'line': 1, 'message': 'T002 import for pdb found'}, + {'col': 11, 'line': 1, 'message': 'T100 trace found: pdb.set_trace used'}, + {'col': 31, 'line': 1, 'message': 'T100 trace found: pdb.set_trace used'}, + {'col': 0, 'line': 1, 'message': 'T100 import for pdb found'}, ] try: @@ -234,7 +234,7 @@ def test_import_other_module_as_set_trace_and_use_it(self): class TestImportAsCases(object): def test_import_ipdb_as(self): result = check_code_for_debugger_statements('import math, ipdb as sif, collections') - assert result == [{'col': 0, 'line': 1, 'message': 'T002 import for ipdb found as sif'}] + assert result == [{'col': 0, 'line': 1, 'message': 'T100 import for ipdb found as sif'}] class TestModuleASSetTraceCases(object): @@ -242,8 +242,8 @@ def test_import_ipdb_as_use_set_trace(self): result = check_code_for_debugger_statements('import ipdb as sif;sif.set_trace();') expected_result = [ - {'col': 19, 'line': 1, 'message': 'T002 trace found: sif.set_trace used'}, - {'col': 0, 'line': 1, 'message': 'T002 import for ipdb found as sif'}, + {'col': 19, 'line': 1, 'message': 'T100 trace found: sif.set_trace used'}, + {'col': 0, 'line': 1, 'message': 'T100 import for ipdb found as sif'}, ] try: @@ -260,8 +260,8 @@ def test_import_set_trace_ipdb(self): result = check_code_for_debugger_statements('from ipdb import run, set_trace;set_trace();') expected_result = [ - {'col': 32, 'line': 1, 'message': 'T002 trace found: set_trace used'}, - {'col': 0, 'line': 1, 'message': 'T002 import for set_trace found'}, + {'col': 32, 'line': 1, 'message': 'T100 trace found: set_trace used'}, + {'col': 0, 'line': 1, 'message': 'T100 import for set_trace found'}, ] try: @@ -276,8 +276,8 @@ def test_import_set_trace_pdb(self): result = check_code_for_debugger_statements('from pdb import set_trace; set_trace();') expected_result = [ - {'col': 27, 'line': 1, 'message': 'T002 trace found: set_trace used'}, - {'col': 0, 'line': 1, 'message': 'T002 import for set_trace found'}, + {'col': 27, 'line': 1, 'message': 'T100 trace found: set_trace used'}, + {'col': 0, 'line': 1, 'message': 'T100 import for set_trace found'}, ] try: @@ -292,8 +292,8 @@ def test_import_set_trace_ipdb_as_and_use(self): result = check_code_for_debugger_statements('from ipdb import run, set_trace as sif; sif();') expected_result = [ - {'col': 40, 'line': 1, 'message': 'T002 trace found: set_trace used as sif'}, - {'col': 0, 'line': 1, 'message': 'T002 import for set_trace found as sif'}, + {'col': 40, 'line': 1, 'message': 'T100 trace found: set_trace used as sif'}, + {'col': 0, 'line': 1, 'message': 'T100 import for set_trace found as sif'}, ] try: @@ -308,8 +308,8 @@ def test_import_set_trace_ipdb_as_and_use_with_conjunction_and(self): result = check_code_for_debugger_statements('from ipdb import run, set_trace as sif; True and sif();') expected_result = [ - {'col': 49, 'line': 1, 'message': 'T002 trace found: set_trace used as sif'}, - {'col': 0, 'line': 1, 'message': 'T002 import for set_trace found as sif'}, + {'col': 49, 'line': 1, 'message': 'T100 trace found: set_trace used as sif'}, + {'col': 0, 'line': 1, 'message': 'T100 import for set_trace found as sif'}, ] try: @@ -324,8 +324,8 @@ def test_import_set_trace_ipdb_as_and_use_with_conjunction_or(self): result = check_code_for_debugger_statements('from ipdb import run, set_trace as sif; True or sif();') expected_result = [ - {'col': 48, 'line': 1, 'message': 'T002 trace found: set_trace used as sif'}, - {'col': 0, 'line': 1, 'message': 'T002 import for set_trace found as sif'}, + {'col': 48, 'line': 1, 'message': 'T100 trace found: set_trace used as sif'}, + {'col': 0, 'line': 1, 'message': 'T100 import for set_trace found as sif'}, ] try: @@ -346,7 +346,7 @@ def test_import_set_trace_ipdb_as_and_use_with_conjunction_or_noqa(self): def test_import_set_trace_ipdb_as_and_use_with_conjunction_or_noqa_import_only(self): result = check_code_for_debugger_statements('from ipdb import run, set_trace as sif # noqa\nTrue or sif()') - expected_result = [{'col': 8, 'line': 2, 'message': 'T002 trace found: set_trace used as sif'}] + expected_result = [{'col': 8, 'line': 2, 'message': 'T100 trace found: set_trace used as sif'}] try: assert result == expected_result