Python cleanup suite

Proprietary

Run every Python cleanup recipe in one pass, including the code quality fixes: literal simplification, boolean and comparison tidying, dead code removal, naming fixes, and more. Each recipe leaves code alone where its rewrite could change what the code does.

org.openrewrite.python.cleanup.PythonBestPractices
mod run . --recipe=org.openrewrite.python.cleanup.PythonBestPractices

Install it once, then run it on every repository under the current directory. New to the Moderne CLI? Set it up.

Recipe list

It runs these recipes, in this order.

  1. Use {} literal instead of dict() constructor
  2. Use [] literal instead of list() constructor
  3. Use () literal instead of tuple() constructor
  4. Unwrap tuple(), list() or set() around a collection literal
  5. Drop unnecessary step 1 argument from range()
  6. Drop unnecessary 0 start argument from range()
  7. Compare to None with identity operators (is / is not)
  8. Fold same-literal ==/!= comparisons to boolean constants
  9. Collapse self-cancelling ^ / - with duplicate operands to 0
  10. Rewrite self-multiplication as ** 2
  11. Convert else: if to elif
  12. Flip an empty if body by negating the condition
  13. Drop a pass-only elif by negating its condition
  14. Simplify a negated elif to else
  15. Drop else after an early-exit if branch
  16. Use a conditional expression for a simple if/else assignment
  17. Collapse boolean ternary to bare condition
  18. Eliminate boolean literal from and/or
  19. Replace len() emptiness check with truthiness
  20. Substitute constant collection condition with boolean
  21. Collapse if/else returning boolean literals
  22. Flatten negated logic via De Morgan's identities
  23. Replace self-referencing ternary with or
  24. Swap conditional expression branches to drop a negated condition
  25. Use augmented assignment
  26. Drop default slice boundaries
  27. Use negative index instead of len() offset
  28. Code quality
  29. Use chained comparison syntax
  30. Replace .find() check with in / not in
  31. Consolidate repeated == with or into in
  32. Merge isinstance() calls
  33. Prefer set literals in in membership tests
  34. Remove redundant pass statements
  35. Strip trailing continue from loop body
  36. Drop exists() check paired with is_dir()/is_file()
  37. Delete no-op assert True statements
  38. Strip dead code after terminal statements
  39. Delete if blocks whose body is only pass
  40. Unwrap str() from print() arguments
  41. Remove redundant None default from dict.get()
  42. Drop f prefix from strings without placeholders
  43. Strip str() from f-string placeholders
  44. Prefer startswith/endswith over slice comparison
  45. Use bracket access for re.Match groups
  46. Fold constants into f-string text
  47. Drop redundant .keys() on dict iteration
  48. Convert one-item dict.update() to bracket assignment
  49. Unwrap unnecessary dict() from union operands
  50. Deduplicate repeated keys in dict literals
  51. Deduplicate repeated elements in set literals
  52. Flatten for/else when the loop has no break
  53. Use comprehension syntax instead of list()/set() around generators
  54. Pass iterable directly to any()/all() instead of identity generator
  55. Use generator expression instead of list comprehension in iterable-accepting calls
  56. Simplify identity comprehension to list()/set() call
  57. Swap not all()/not any() by negating the comparison
  58. Apply De Morgan's law to any(not ...)/all(not ...)
  59. Rewrite any(v == literal ...) as literal in collection
  60. Simplify sum(1 for x in items if cond) to sum(bool(cond) for x in items)
  61. Unwrap one-element exception tuple in except
  62. Chain exceptions with raise ... from in except blocks
  63. Standardize @classmethod first parameter to cls
  64. Standardize instance method first parameter to self
  65. Convert apply('name') to a direct method invocation
  66. Replace the and/or idiom with a conditional expression
  67. Swap variables with tuple unpacking
  68. Use datetime.now() instead of datetime.today()
  69. Replace getattr(x, 'attr') with x.attr
  70. Replace setattr() with constant attribute assignment
  71. Replace not x in y with x not in y
  72. Use is not instead of not ... is
  73. Replace logger.warn() with logger.warning()
  74. Remove unnecessary assignment before return
  75. Replace Yoda conditions with normal comparisons
  76. Remove useless object inheritance
  77. Merge multiple startswith()/endswith() calls into one
  78. Replace zip(d.keys(), d.values()) with d.items()
  79. Remove trailing return None from functions
  80. Replace del x[:] with x.clear()
  81. Merge nested with statements into one