Issue Title
[Bug] init_actions skips event hooks with underscore-prefixed names since v2.1.0
Issue Body
Description
In Beanie 2.1.0, PR #1293 (chore: modernize Beanie codebase and types for py310+) introduced a change in init_actions() that skips all attributes starting with _. This silently breaks any @before_event / @after_event hooks whose method names begin with an underscore.
Location
beanie/odm/utils/init.py, method init_actions:
for attr in dir(cls):
if attr.startswith("_"): # Skip all private/magic attributes <-- THIS LINE
continue
Reproduction
from beanie import Document, before_event, Insert
class MyDocument(Document):
name: str
creator_id: str | None = None
@before_event(Insert)
async def _set_creator(self):
"""This hook is silently skipped in 2.1.0!"""
self.creator_id = "some_user"
# After init_beanie(...) and calling:
doc = MyDocument(name="test")
await doc.insert()
print(doc.creator_id) # None in 2.1.0, "some_user" in 2.0.0
Beanie 2.0.0: _set_creator is correctly registered and fires on insert. ✅
Beanie 2.1.0: _set_creator is skipped by init_actions because it starts with _, and creator_id remains None. ❌
Expected Behavior
Hooks decorated with @before_event / @after_event should be registered regardless of whether the method name starts with _. The has_action attribute check is already sufficient to filter relevant methods.
Actual Behavior
All methods starting with _ are silently skipped during action registration, even if they are valid user-defined hooks with @before_event / @after_event decorators. No error or warning is raised.
Impact
- Silent data loss: No error, no warning — hooks simply stop executing.
- Breaking change: Not documented in any changelog or migration guide.
- Users who followed a naming convention like
_before_create / _after_update for hooks are affected.
- In our case, this caused
creator_id and updater_id fields to silently become null in production after upgrading from 2.0.0 to 2.1.0.
Suggested Fix
Instead of skipping all _-prefixed attributes, only skip dunder attributes:
for attr in dir(cls):
if attr.startswith("__"): # Skip only dunder/magic attributes
continue
Or, even better, keep the optimization but still check has_action for _-prefixed methods:
for attr in dir(cls):
if attr.startswith("__"): # Skip magic/dunder attributes (performance optimization)
continue
f = getattr(cls, attr)
if inspect.isfunction(f) and hasattr(f, "has_action"):
ActionRegistry.add_action(
document_class=cls,
event_types=f.event_types,
action_direction=f.action_direction,
funct=f,
)
This preserves the performance optimization (skipping __init__, __repr__, etc.) while not breaking user-defined hooks with single-underscore prefixes.
Environment
Labels suggestion
bug, regression
Issue Title
[Bug] init_actions skips event hooks with underscore-prefixed names since v2.1.0Issue Body
Description
In Beanie 2.1.0, PR #1293 (
chore: modernize Beanie codebase and types for py310+) introduced a change ininit_actions()that skips all attributes starting with_. This silently breaks any@before_event/@after_eventhooks whose method names begin with an underscore.Location
beanie/odm/utils/init.py, methodinit_actions:Reproduction
Beanie 2.0.0:
_set_creatoris correctly registered and fires on insert. ✅Beanie 2.1.0:
_set_creatoris skipped byinit_actionsbecause it starts with_, andcreator_idremainsNone. ❌Expected Behavior
Hooks decorated with
@before_event/@after_eventshould be registered regardless of whether the method name starts with_. Thehas_actionattribute check is already sufficient to filter relevant methods.Actual Behavior
All methods starting with
_are silently skipped during action registration, even if they are valid user-defined hooks with@before_event/@after_eventdecorators. No error or warning is raised.Impact
_before_create/_after_updatefor hooks are affected.creator_idandupdater_idfields to silently becomenullin production after upgrading from 2.0.0 to 2.1.0.Suggested Fix
Instead of skipping all
_-prefixed attributes, only skip dunder attributes:Or, even better, keep the optimization but still check
has_actionfor_-prefixed methods:This preserves the performance optimization (skipping
__init__,__repr__, etc.) while not breaking user-defined hooks with single-underscore prefixes.Environment
24b2a7bfLabels suggestion
bug,regression