Safe Bulk Cleanup
Bulk lint fixes (ruff --fix, pyflakes) can silently break multi-line from X import (a, b, c) blocks when a name is re-exported by the source module. This skill prevents that.
When to use
ruff check --fixon a whole package- Removing unused imports / unused variables across many files
- Any automated style cleanup that touches import statements
Hard rules
- Never run
ruff --fixon a whole package. It rewrites multi-line import blocks and deletes re-exported names. - Only fix single-line unused imports, one file at a time, with
patch. - Before deleting any import, grep for re-exports:
If ANY other module imports that name from the module you're editing, it's a re-export — keep it.grep -rn "from <module> import.*<name>" src/ --include="*.py" - Multi-line
from X import (a, b, c)blocks: never auto-fix. Only hand-edit if you've verified every name. - After each file, run import check:
PYTHONPATH=src python -c "import <module>" - After the batch, run the full test suite — collection errors (ImportError) mean you broke a re-export.
Workflow
- Get the list:
ruff check src/ --select F401 --statistics - For each file with F401:
grep -n "import" <file>to see the import block- For each unused name, check re-export:
grep -rn "from <file_module> import.*<name>" src/ - If no re-export,
patchto remove the single-line import - If re-export exists, leave it (add
# noqa: F401if it's intentional)
- Verify:
PYTHONPATH=src python -c "import <module>"per file - Full suite:
python -m pytest tests/ -q
Pitfalls
- ruff --fix on multi-line import blocks — deletes names that are re-exported, causing ImportError in downstream modules (collection errors in pytest)
- F401 in
__init__.py— often intentional re-exports; never auto-fix # noqadirectives — check they're valid before relying on them
Verification
PYTHONPATH=src python -m pytest tests/ -q # must be green
ruff check src/ --select F401 --statistics # count should drop, not break