This blog post is a note on , Why Ruff (the linter) is trying to revert:
def ready(self):
import myapp.signals
into
def ready(self):
pass
This is not random. Ruff is doing this because of how it sees imports, side effects, and unused code.
Here is the precise explanation.
1. Ruff enforces the rule: “Do not use imports only for side-effects.”
Ruff has a ruleset (particularly F401 and I001 under unused-import) that says:
- If you import a module but do not use it explicitly,
- Ruff marks it as an unused import
- Even if you imported it intentionally for side-effects (signal registration)
So Ruff believes this code:
def ready(self):
import myapp.signals
is an unused import, because:
- No variable is used
- No functions from myapp.signals are referenced
- It thinks the import is unnecessary
To “fix” the unused import, Ruff offers an autofix:
→ Remove the import
→ Replace the function body with pass
Thus:
def ready(self):
pass
This is Ruff’s standard behavior.
2. Ruff does NOT understand Django signal registration
Django’s signal system depends on module import side-effects:
import myapp.signals
is the required mechanism to register:
- @receiver(post_save, sender=ModelName)
- @receiver(post_delete, sender=ModelName)
- etc.
Ruff does not know:
- That Django apps load signals inside ready()
- That importing a file has side effects (registering signals)
So Ruff thinks:
“This import is unused; I should remove it.”
But in Django, this import is essential.
3. Why was it reverted?
Because you probably ran:
ruff format
ruff check --fix
Or your IDE auto-applied Ruff fixes.
When Ruff sees:
def ready(self):
import myapp.signals
It removes the import and replaces it with:
def ready(self):
pass
This breaks Django signal loading.
4. Side effect of Ruff removing the import
Your Django signals STOPPED WORKING.
5. How to fix correctly
You must keep the import, and silence Ruff’s unused-import rule.
Option A — Tell Ruff to ignore this line:
def ready(self):
import myapp.signals # noqa: F401
Option B — Disable the rule for this file:
At the top of apps.py:
# ruff: noqa: F401
Option C — Disable the rule globally (not recommended)
6. This is a well-known Django + Ruff issue
Signal registration via side-effect imports is standard Django practice.
Ruff does not detect that the import is valid.
Therefore, the import must be kept manually and protected from Ruff.
7. Your real project issues were caused by this
Because ready() was replaced with pass, your signals were not imported at all.
Which explains:
This made the system appear broken at several points.
Take Away
Ruff’s autofix removed signal import because it flagged it as an unused import.
Ruff does not understand Django’s signal registration mechanism, so it incorrectly “corrected” the code.
You must restore the import and mark it as intentionally unused.
Top comments (0)