tortoise / tortoise/tortoise-orm
Signals are not inherited
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 5.6k
- Forks
- 516
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 9
Description
All necessary models should be added to signals directly. Sometimes it is not comfortably because we must remember about this point and can't use the standard habitual OOP logic.
Example for reproducing:
from tortoise import fields, Model
from typing import Any
class Base(Model):
id = fields.IntField(pk=True)
class Meta:
abstract = True
@pre_save(Base)
async def signal_pre_save(*args: Any, **kwargs: Any) -> None:
print("Base pre_save. And it will be executed nowhere")
class Foo(Base):
pass
I've explored and detected a reason of this behavior. Who can sort out with this logic? I guess it was made specially.
I fixed this "issue" by the following workaround (maybe it will be useful for someone):
from tortoise import fields, Model
from tortoise.signals import Signals
from tortoise.signals import pre_save
class CustomListener(dict):
def get(self, cls: Type, default=None):
"""Tries to look for signals with MRO logic
"""
listeners = super().get(cls, default)
if not listeners:
for parent_cls in cls.__bases__:
listeners = self.get(parent_cls, default=default)
if listeners:
return listeners
return []
class Base(Model):
_listeners: Dict[Signals, CustomListener] = { # type: ignore
Signals.pre_save: CustomListener(),
Signals.post_save: CustomListener(),
Signals.pre_delete: CustomListener(),
Signals.post_delete: CustomListener(),
}
class Meta:
abstract = True
@pre_save(Base)
async def signal_pre_save(*args: Any, **kwargs: Any) -> None:
print("Base pre_save. And it will be executed for all children")
class Foo(Base):
pass
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the signal registration and model logic referenced in tortoise/models.py around line 838, then trace how listeners are selected for subclasses. Reproduce the Base/Foo example and compare the behavior with the proposed MRO-style workaround; done means the intended inheritance behavior is established and covered by a regression test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100