Remove Debugging Statements¶
What is the step that you should do before opening a PR, but unfortunately no
pre-commit hook has done for you so far? Cleaning up all the various debugging
statements that you've added while desperately curiously wondering what
this code is doing.
Remove Breakpoints¶
Since Python 3.9, it's easy to add a new breakpoint. And it's still easy to forget about them. 😉
You can define a custom rule that removes all the calls to breakpoint()
and
add it to the rules
section of your .sourcery.yaml
config file:
rules:
- id: remove_breakpoint
description: Remove breakpoints from production code
pattern: breakpoint()
replacement: ''
Note the empty string for the replacement
. This means that the breakpoint()
statements will be removed.
Note: Sourcery won't apply this rule, if a code block contained only a
breakpoint()
, and applying this would lead to a syntax error. See also the
Reference Docs
about empty replacements.
Remove Old-Style Breakpoints¶
You can set up a similar check for the old-style breakpoints with
pdb.set_trace()
as well. In this case, we define 2 rules to ensure that all
occurrences are caught:
rules:
- id: remove_set_trace
description: Remove pdb.set_trace calls from production code
pattern: |
import pdb
pdb.set_trace()
replacement: ''
- id: remove_set_trace_no_import
description: Remove pdb.set_trace calls from production code
pattern: pdb.set_trace()
replacement: ''
Note that the 2 rules can have the same description
, but they both need to
have a unique id
.
Coming soon: In the next versions, we'll introduce syntax for optional elements, so that you can implement such checks with 1 rule.
Caveat: Same as for the 1st rule. If a code block contained only a
breakpoint()
, applying this rule and removing that only line will lead to a
syntax error.
Flag print
Statements¶
Of course, print
statements are a valid part of many codebases. But more often
than not they are remainders after a debugging session.
It might be tricky to distinguish between "real" and debugging print statements. But if your project:
- doesn't have a command line interface at all
- or uses a command line framework like
typer
orclick
,
you should probably flag all occurrences of print
.
For this, you can define a rule that finds all calls to print
with various
arguments:
rules:
- id: flag_print
description: print statement in production code
pattern: print(...)
Note that in contrast to the previous rules, this one doesn't have a
replacement
field. Sourcery will only flag these code snippets, but won't
replace or delete them.
Replace print
Statements With Logging¶
Another approach you might consider is to replace those print
statements
sprinkled all over the codebase with logging.
For this, you can define a rule with a replacement
:
rules:
- id: print_to_log
description: Replace print statement with logging
pattern: print(${args+})
replacement: logger.debug(${args})
This rule uses the capture ${args+}
, which captures 1 or more positional
arguments. This way, you can ensure not to replace a print()
call without any
arguments with logger.debug()
.
To learn more about capturing arguments, check out our Pattern Syntax Reference Docs
You can also define tests
to verify which code snippets your rule matches and
which it doesn't. Here's the same print_to_log
rule enhanced with some
tests
.
rules:
- id: print_to_log
description: Replace print statement with logging
pattern: print(${args+})
replacement: logger.debug(${args})
tests:
- match: print("placeholder")
- match: print(16, 20)
- match: print(16, 20, sep=";")
- no-match: print()
You can learn more about tests
in our
Custom Rule Reference
Caveat: Sourcery will replace print
with logger.debug
, but it won't check
whether the name logger
exists in that context. => After applying this rule,
you might need a manual adjustment to ensure that all the affected modules have
a logger
defined.