PySweep is a fast, lightweight, and extensible static analysis tool that scans Python projects to find dead code, unused variables, design smelling issues, and debug left-overs.
PySweep scans your code utilizing Python's native AST (Abstract Syntax Tree) and Tokenizers rather than fragile regex heuristics. It detects 22 types of code issues categorized into 3 domains:
- Unused Imports: Finds import statements containing modules that are never referenced.
- Unused Variables: Identifies local variables defined in function blocks that are never read.
- Unused Functions: Flags module-level functions that are defined but never called or referenced.
- Files Never Imported: Finds orphan Python files that are completely disconnected from the dependency tree.
- Duplicate Functions: Identifies functions with identical logical AST structures (ignoring variable naming, comments, and docstrings).
- Duplicate Classes: Flags duplicate class definitions across the codebase.
- Duplicate String Literals: Detects string constants repeated multiple times, suggesting constant refactoring.
- Wildcard Imports: Warns against using
from module import *. - Excessive Parameters: Flags functions accepting more than 7 parameters.
- Large Nested Blocks: Detects control structures nested deeper than 3 levels (indentation smells).
- Debug Prints: Checks for left-over
print()statements. - Breakpoints: Flags
breakpoint()statements. - PDB Imports: Detects debug imports like
pdb,ipdb, andpudb. - Long Functions: Detects functions exceeding 75 lines of code.
- Large Files: Warns when file size exceeds 500 lines.
- Empty Files: Identifies empty
.pyfiles. - Empty Folders: Flags folders that contain no code files.
- Missing Module/Function Docstrings: Encourages API documentation compliance.
- Circular Imports: Analyzes the project import graph and flags import cycles (e.g. A β B β A).
- TODO & FIXME: Surface inline developer comments.
git clone https://github.com/allanabtech/PySweep.git
cd pysweep
pip install -e .pip install -e .[dev]Run a scan against any Python directory or file:
pysweep scan ./my_project--json: Outputs the entire report structure to stdout as JSON.--verbose: Runs in debug mode to see scanning logs.--output <file_path>/-o: Saves the structured scan results to a JSON file.--score: Prints only the health score integer (0 to 100). Excellent for CI/CD checks!--summary: Prints only the high-level dashboard metrics (skips detailed issue line-by-line dumps).
======================================================
PySweep Analysis
======================================================
Summary:
Files scanned: 12
Issues found: 7
Health Score: 89/100
Issue Breakdown:
Issue Type Count Severity
ββββββββββββββββββββββββββββββββββββββββββ
Unused Imports 3 WARNING
Debug Prints 2 WARNING
Circular Imports 1 ERROR
TODOs 1 INFO
Detailed Issues:
π my_project/helpers.py
β Line 8: Unused import: 'sys' (unused-import)
Suggestion: Remove unused import to clean up dependency graph.
β Line 15: print() statement found (print-statement)
Suggestion: Use logging module instead of print() for production.
π my_project/core.py
β Line 1: Circular import path detected: core.py -> utils.py -> core.py (circular-import)
Suggestion: Redesign imports or use dependency injection.
Recommendations:
β’ Remove unused imports
β’ Remove debug prints, breakpoints, and pdb imports
β’ Redesign imports or use dependency injection to resolve circular imports
PySweep's engine consists of a pipeline that walks files, compiles ASTs/Tokens, resolves import graphs, runs built-in or custom detectors, calculates health scores, and formats output.
graph TD
A[CLI Entrypoint: pysweep scan] --> B[Load Config: pyproject.toml]
B --> C[Scanner: File discovery & gitignore filters]
C --> D[AST & Tokenizer Parser]
D --> E[Analyzer: Import Resolver & Plugin Loader]
E --> F[Run File Detectors]
E --> G[Run Project Detectors]
F --> H[Issue Collector]
G --> H
H --> I[Reporter: Score Calc & Formatters]
I --> J[Rich Terminal Output]
I --> K[JSON File Report]
PySweep is built with a plugin-first mindset. To add a custom check without modifying PySweep:
- Create a
.pysweep/plugins/folder in your project. - Create a file called
custom_rule.py:
from pysweep.detectors import register_file_detector
from pysweep.models import Issue, FileContext
from pysweep.config import Config
@register_file_detector
def detect_unsafe_eval(context: FileContext, config: Config):
"""Detect calls to eval()"""
issues = []
if not context.tree:
return issues
import ast
for node in ast.walk(context.tree):
if isinstance(node, ast.Call) and isinstance(node.func, ast.Name) and node.func.id == "eval":
issues.append(Issue(
file=context.relative_path,
line=node.lineno,
severity="error",
rule="no-eval",
message="Use of unsafe eval() detected.",
suggestion="Replace eval() with safe alternatives like ast.literal_eval."
))
return issuesPySweep will load this file dynamically and execute your check on every run!
- CI/CD Integration: Add GitHub Actions integration to fail builds under a threshold score.
- Auto-Fixer: Implement
--fixto automatically remove unused imports and variables. - Interactive Mode: Add interactive terminal prompts to clean up dead code.
- Configuration UI: Web-based configuration builder for custom rules.
Contributions are welcome! Please check our CONTRIBUTING.md guide for guidelines on how to run tests, write code, and build plugins.
This project is licensed under the MIT License.