Discover moderated content models dynamically#8652
Conversation
Replace the hand-maintained moderated-model lists (the per-type branches in moderation_state_column_visible and the moderationobjecttype2model dict) with a registry built from __moderation_object_type__ declared on each model, and factor the duplicated mutual-block clause into a shared helper. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
tristanlabelle
left a comment
There was a problem hiding this comment.
Nice, much better. I think we can still go one step further with typing.Protocol.
| type ModeratedContentModel = type[ | ||
| HostRequest | GroupChat | FriendRelationship | EventOccurrence | Comment | Reply | Discussion | ||
| ] |
There was a problem hiding this comment.
Have you tried using typing.Protocol? My proof-of-concept works great and avoids the union and getattr(cls, cls.__moderation_author_column__),.
from enum import Enum, auto
from typing import ClassVar, Protocol
class ModerationObjectType(Enum):
event_occurrence = auto()
class ModeratedContent(Protocol):
__moderation_author_column__: ClassVar[str]
__moderation_object_type__: ClassVar[ModerationObjectType]
# id: Mapped[int]
class EventOccurrence:
__moderation_author_column__ = "creator_user_id"
__moderation_object_type__ = ModerationObjectType.event_occurrence
moderated_content_type: type[ModeratedContent] = EventOccurrence
print(moderated_content_type.__moderation_author_column__)
print(moderated_content_type.__moderation_object_type__)There was a problem hiding this comment.
awesome, implemented, thanks! typing was a bit inflexible, otherwise worked
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
📝 Release NotesThis PR does not need to be included in release notes. Reason: This PR is explicitly described as a pure refactor of moderation system plumbing with no behavior change. It improves internal maintainability and reduces hand-maintained duplication, but does not add a user-facing feature, noticeable UX improvement, or clearly significant end-user-impacting reliability change on its own. 🤖 Bot Debug InformationModel: |
Pure refactor of the Unified Moderation System plumbing, no behavior change.
Previously the set of UMS-governed models was encoded in several hand-maintained places: the seven per-object-type branches inside
moderation_state_column_visible, themoderationobjecttype2modeldict inservicers/moderation.py, and the_ModeratedContentunion insql.py. Adding a moderated type meant updating each.This replaces them with a single source of truth on the models themselves:
__moderation_object_type__alongside the existing__moderation_author_column__.get_moderated_models()discovers them by scanning the SQLAlchemy mapper registry and returns{ModerationObjectType: ModeratedModel}, whereModeratedModelresolves the model, object type, and author column.moderation_state_column_visibleandservicers/moderation.pynow iterate that registry instead of hardcoded lists.exists(...)clause is factored into a_users_block_each_otherhelper.Testing
make formatandmake mypypass (the two remaining mypy errors —test_calendar_events.pymissingicsstubs andfixtures/misc.pyreturn type — are pre-existing ondevelop).test_moderation,test_threads,test_notifications,test_discussions.cd app/backend && make format && make mypy && uv run pytest.Backend checklist
developif necessary for linear migration history (no DB changes)For maintainers
This PR was created with the Couchers PR skill.