diff --git a/ChangeLog b/ChangeLog index b8dce9a625..9b1ab00a96 100644 --- a/ChangeLog +++ b/ChangeLog @@ -48,6 +48,10 @@ Release date: TBA * Extended ``consider-using-tuple`` check to cover ``in`` comparisons. +* Added ``forgotten-debug-statement``: Emitted when ``breakpoint``, ``pdb.set_trace`` or ``sys.breakpointhook`` calls are found + + Closes #3692 + What's New in Pylint 2.9.6? =========================== diff --git a/doc/whatsnew/2.10.rst b/doc/whatsnew/2.10.rst index 6bfea5b5f6..cadfc3fa64 100644 --- a/doc/whatsnew/2.10.rst +++ b/doc/whatsnew/2.10.rst @@ -24,6 +24,10 @@ New checkers Closes #4365 +* Added ``forgotten-debug-statement``: Emitted when ``breakpoint``, ``pdb.set_trace`` or ``sys.breakpointhook`` calls are found + + Closes #3692 + Extensions ========== diff --git a/pylint/checkers/stdlib.py b/pylint/checkers/stdlib.py index afc5faa80f..7eabe9bb40 100644 --- a/pylint/checkers/stdlib.py +++ b/pylint/checkers/stdlib.py @@ -55,6 +55,7 @@ SUBPROCESS_POPEN = "subprocess.Popen" SUBPROCESS_RUN = "subprocess.run" OPEN_MODULE = "_io" +DEBUG_BREAKPOINTS = ("builtins.breakpoint", "sys.breakpointhook", "pdb.set_trace") DEPRECATED_MODULES = { @@ -434,6 +435,12 @@ class StdlibChecker(DeprecatedMixin, BaseChecker): "Using the system default implicitly can create problems on other operating systems. " "See https://www.python.org/dev/peps/pep-0597/", ), + "W1515": ( + "Leaving functions creating breakpoints in production code is not recommended", + "forgotten-debug-statement", + "Calls to breakpoint(), sys.breakpointhook() and pdb.set_trace() should be removed " + "from code that is not actively being debugged.", + ), } def __init__(self, linter=None): @@ -495,6 +502,7 @@ def _check_shallow_copy_environ(self, node): "subprocess-run-check", "deprecated-class", "unspecified-encoding", + "forgotten-debug-statement", ) def visit_call(self, node): """Visit a Call node.""" @@ -531,6 +539,8 @@ def visit_call(self, node): self._check_env_function(node, inferred) elif name == SUBPROCESS_RUN: self._check_for_check_kw_in_run(node) + elif name in DEBUG_BREAKPOINTS: + self.add_message("forgotten-debug-statement", node=node) self.check_deprecated_method(node, inferred) except astroid.InferenceError: return diff --git a/tests/functional/f/forgotten_debug_statement_py37.py b/tests/functional/f/forgotten_debug_statement_py37.py new file mode 100644 index 0000000000..ebe0a7a44d --- /dev/null +++ b/tests/functional/f/forgotten_debug_statement_py37.py @@ -0,0 +1,10 @@ +# pylint: disable=missing-docstring + +import pdb +import sys + +breakpoint() # [forgotten-debug-statement] +sys.breakpointhook() # [forgotten-debug-statement] +pdb.set_trace() # [forgotten-debug-statement] +b = breakpoint +b() # [forgotten-debug-statement] diff --git a/tests/functional/f/forgotten_debug_statement_py37.rc b/tests/functional/f/forgotten_debug_statement_py37.rc new file mode 100644 index 0000000000..a17bb22daf --- /dev/null +++ b/tests/functional/f/forgotten_debug_statement_py37.rc @@ -0,0 +1,2 @@ +[testoptions] +min_pyver=3.7 diff --git a/tests/functional/f/forgotten_debug_statement_py37.txt b/tests/functional/f/forgotten_debug_statement_py37.txt new file mode 100644 index 0000000000..40e8914a67 --- /dev/null +++ b/tests/functional/f/forgotten_debug_statement_py37.txt @@ -0,0 +1,4 @@ +forgotten-debug-statement:6:0::"Leaving functions creating breakpoints in production code is not recommended" +forgotten-debug-statement:7:0::"Leaving functions creating breakpoints in production code is not recommended" +forgotten-debug-statement:8:0::"Leaving functions creating breakpoints in production code is not recommended" +forgotten-debug-statement:10:0::"Leaving functions creating breakpoints in production code is not recommended"