mirror of https://github.com/zulip/zulip.git
refactor: Rename `Huddle` Django model class to `DirectMessageGroup`.
This commit renames the "Huddle" Django model class to "DirectMessageGroup", while maintaining the same table -- "zerver_huddle". Fixes part of #28640.
This commit is contained in:
parent
79f858b4b8
commit
02d0566dc5
|
@ -63,7 +63,7 @@ from zerver.lib.user_counts import realm_user_count_by_role
|
|||
from zerver.lib.utils import assert_is_not_none
|
||||
from zerver.models import (
|
||||
Client,
|
||||
Huddle,
|
||||
DirectMessageGroup,
|
||||
Message,
|
||||
NamedUserGroup,
|
||||
PreregistrationUser,
|
||||
|
@ -174,12 +174,12 @@ class AnalyticsTestCase(ZulipTestCase):
|
|||
stream.save(update_fields=["recipient"])
|
||||
return stream, recipient
|
||||
|
||||
def create_huddle_with_recipient(self, **kwargs: Any) -> Tuple[Huddle, Recipient]:
|
||||
def create_huddle_with_recipient(self, **kwargs: Any) -> Tuple[DirectMessageGroup, Recipient]:
|
||||
self.name_counter += 1
|
||||
defaults = {"huddle_hash": f"hash{self.name_counter}"}
|
||||
for key, value in defaults.items():
|
||||
kwargs[key] = kwargs.get(key, value)
|
||||
huddle = Huddle.objects.create(**kwargs)
|
||||
huddle = DirectMessageGroup.objects.create(**kwargs)
|
||||
recipient = Recipient.objects.create(type_id=huddle.id, type=Recipient.DIRECT_MESSAGE_GROUP)
|
||||
huddle.recipient = recipient
|
||||
huddle.save(update_fields=["recipient"])
|
||||
|
|
|
@ -37,7 +37,7 @@ create_zulip_test
|
|||
|
||||
./manage.py dumpdata \
|
||||
zerver.UserProfile zerver.Stream zerver.Recipient \
|
||||
zerver.Subscription zerver.Message zerver.Huddle zerver.Realm \
|
||||
zerver.Subscription zerver.Message zerver.DirectMessageGroup zerver.Realm \
|
||||
zerver.UserMessage zerver.Client \
|
||||
zerver.DefaultStream >zerver/tests/fixtures/messages.json
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ from zerver.lib.partial import partial
|
|||
from zerver.lib.stream_color import STREAM_ASSIGNMENT_COLORS as STREAM_COLORS
|
||||
from zerver.models import (
|
||||
Attachment,
|
||||
Huddle,
|
||||
DirectMessageGroup,
|
||||
Message,
|
||||
Realm,
|
||||
RealmEmoji,
|
||||
|
@ -486,7 +486,7 @@ def build_stream(
|
|||
|
||||
|
||||
def build_direct_message_group(direct_message_group_id: int) -> ZerverFieldsT:
|
||||
direct_message_group = Huddle(
|
||||
direct_message_group = DirectMessageGroup(
|
||||
id=direct_message_group_id,
|
||||
)
|
||||
return model_to_dict(direct_message_group)
|
||||
|
|
|
@ -41,8 +41,8 @@ from zerver.models import (
|
|||
CustomProfileField,
|
||||
CustomProfileFieldValue,
|
||||
DefaultStream,
|
||||
DirectMessageGroup,
|
||||
GroupGroupMembership,
|
||||
Huddle,
|
||||
Message,
|
||||
MutedUser,
|
||||
NamedUserGroup,
|
||||
|
@ -1131,7 +1131,7 @@ def custom_fetch_direct_message_groups(response: TableData, context: Context) ->
|
|||
)
|
||||
realm_huddle_recipient_ids = {sub.recipient_id for sub in realm_huddle_subs}
|
||||
|
||||
# Mark all Huddles whose recipient ID contains a cross-realm user.
|
||||
# Mark all Direct Message groups whose recipient ID contains a cross-realm user.
|
||||
unsafe_huddle_recipient_ids = set()
|
||||
for sub in Subscription.objects.select_related("user_profile").filter(
|
||||
recipient__in=realm_huddle_recipient_ids
|
||||
|
@ -1157,7 +1157,7 @@ def custom_fetch_direct_message_groups(response: TableData, context: Context) ->
|
|||
|
||||
response["_huddle_recipient"] = huddle_recipients
|
||||
response["_huddle_subscription"] = huddle_subscription_dicts
|
||||
response["zerver_huddle"] = make_raw(Huddle.objects.filter(id__in=huddle_ids))
|
||||
response["zerver_huddle"] = make_raw(DirectMessageGroup.objects.filter(id__in=huddle_ids))
|
||||
|
||||
|
||||
def custom_fetch_scheduled_messages(response: TableData, context: Context) -> None:
|
||||
|
|
|
@ -50,8 +50,8 @@ from zerver.models import (
|
|||
CustomProfileField,
|
||||
CustomProfileFieldValue,
|
||||
DefaultStream,
|
||||
DirectMessageGroup,
|
||||
GroupGroupMembership,
|
||||
Huddle,
|
||||
Message,
|
||||
MutedUser,
|
||||
NamedUserGroup,
|
||||
|
@ -999,7 +999,7 @@ def disable_restricted_authentication_methods(data: TableData) -> None:
|
|||
# * Realm's announcements_streams and group_permissions
|
||||
# * UserProfile, in order by ID to avoid bot loop issues
|
||||
# * Now can do all realm_tables
|
||||
# * Huddle
|
||||
# * DirectMessageGroup
|
||||
# * Recipient
|
||||
# * Subscription
|
||||
# * Message
|
||||
|
@ -1232,10 +1232,10 @@ def do_import_realm(import_dir: Path, subdomain: str, processes: int = 1) -> Rea
|
|||
realm_emoji.save(update_fields=["author_id"])
|
||||
|
||||
if "zerver_huddle" in data:
|
||||
update_model_ids(Huddle, data, "huddle")
|
||||
# We don't import Huddle yet, since we don't have the data to
|
||||
# compute direct message group hashes until we've imported some
|
||||
# of the tables below.
|
||||
update_model_ids(DirectMessageGroup, data, "huddle")
|
||||
# We don't import DirectMessageGroup yet, since we don't have
|
||||
# the data to compute direct message group hashes until we've
|
||||
# imported some of the tables below.
|
||||
# We can't get direct message group hashes without processing
|
||||
# subscriptions first, during which
|
||||
# get_direct_message_groups_from_subscription is called.
|
||||
|
@ -1317,8 +1317,8 @@ def do_import_realm(import_dir: Path, subdomain: str, processes: int = 1) -> Rea
|
|||
|
||||
if "zerver_huddle" in data:
|
||||
process_direct_message_group_hash(data, "zerver_huddle")
|
||||
bulk_import_model(data, Huddle)
|
||||
for direct_message_group in Huddle.objects.filter(recipient=None):
|
||||
bulk_import_model(data, DirectMessageGroup)
|
||||
for direct_message_group in DirectMessageGroup.objects.filter(recipient=None):
|
||||
recipient = Recipient.objects.get(
|
||||
type=Recipient.DIRECT_MESSAGE_GROUP, type_id=direct_message_group.id
|
||||
)
|
||||
|
|
|
@ -72,7 +72,7 @@ from zerver.lib.validator import (
|
|||
check_string_or_int_list,
|
||||
)
|
||||
from zerver.models import (
|
||||
Huddle,
|
||||
DirectMessageGroup,
|
||||
Message,
|
||||
Realm,
|
||||
Recipient,
|
||||
|
@ -597,7 +597,7 @@ class NarrowBuilder:
|
|||
)
|
||||
except (JsonableError, ValidationError):
|
||||
raise BadNarrowOperatorError("unknown user in " + str(operand))
|
||||
except Huddle.DoesNotExist:
|
||||
except DirectMessageGroup.DoesNotExist:
|
||||
# Group DM where huddle doesn't exist
|
||||
return query.where(maybe_negate(false()))
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ from typing import Dict, Optional, Sequence
|
|||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from zerver.models import Huddle, Recipient, UserProfile
|
||||
from zerver.models import DirectMessageGroup, Recipient, UserProfile
|
||||
from zerver.models.recipients import (
|
||||
get_direct_message_group_hash,
|
||||
get_or_create_direct_message_group,
|
||||
|
@ -56,10 +56,10 @@ def get_recipient_from_user_profiles(
|
|||
if create:
|
||||
direct_message_group = get_or_create_direct_message_group(user_ids)
|
||||
else:
|
||||
# We intentionally let the Huddle.DoesNotExist escape, in the
|
||||
# case that there is no such direct message group, and the user
|
||||
# passed create=False
|
||||
direct_message_group = Huddle.objects.get(
|
||||
# We intentionally let the DirectMessageGroup.DoesNotExist escape,
|
||||
# in the case that there is no such direct message group, and the
|
||||
# user passed create=False
|
||||
direct_message_group = DirectMessageGroup.objects.get(
|
||||
huddle_hash=get_direct_message_group_hash(user_ids)
|
||||
)
|
||||
return Recipient(
|
||||
|
|
|
@ -601,7 +601,7 @@ def use_db_models(
|
|||
DefaultStream = apps.get_model("zerver", "DefaultStream")
|
||||
DefaultStreamGroup = apps.get_model("zerver", "DefaultStreamGroup")
|
||||
EmailChangeStatus = apps.get_model("zerver", "EmailChangeStatus")
|
||||
Huddle = apps.get_model("zerver", "Huddle")
|
||||
DirectMessageGroup = apps.get_model("zerver", "DirectMessageGroup")
|
||||
Message = apps.get_model("zerver", "Message")
|
||||
MultiuseInvite = apps.get_model("zerver", "MultiuseInvite")
|
||||
OnboardingStep = apps.get_model("zerver", "OnboardingStep")
|
||||
|
@ -645,7 +645,7 @@ def use_db_models(
|
|||
DefaultStream=DefaultStream,
|
||||
DefaultStreamGroup=DefaultStreamGroup,
|
||||
EmailChangeStatus=EmailChangeStatus,
|
||||
Huddle=Huddle,
|
||||
DirectMessageGroup=DirectMessageGroup,
|
||||
Message=Message,
|
||||
MultiuseInvite=MultiuseInvite,
|
||||
UserTopic=UserTopic,
|
||||
|
|
|
@ -59,9 +59,9 @@ realms used for testing; consider using deactivate_realm instead."""
|
|||
# storage; failing to do this leaves dangling files
|
||||
do_delete_all_realm_attachments(realm)
|
||||
|
||||
# TODO: This approach leaks Recipient and Huddle objects,
|
||||
# because those don't have a foreign key to the Realm or any
|
||||
# other model it cascades to (Realm/Stream/UserProfile/etc.).
|
||||
# TODO: This approach leaks Recipient and DirectMessageGroup
|
||||
# objects, because those don't have a foreign key to the Realm
|
||||
# or any other model it cascades to (Realm/Stream/UserProfile/etc.).
|
||||
realm.delete()
|
||||
|
||||
print("Realm has been successfully permanently deleted.")
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 5.0.6 on 2024-07-05 10:44
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("zerver", "0545_attachment_content_type"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.SeparateDatabaseAndState(
|
||||
database_operations=[],
|
||||
state_operations=[
|
||||
migrations.RenameModel(old_name="Huddle", new_name="DirectMessageGroup"),
|
||||
migrations.AlterModelTable(name="directmessagegroup", table="zerver_huddle"),
|
||||
],
|
||||
)
|
||||
]
|
|
@ -48,7 +48,7 @@ from zerver.models.realm_playgrounds import RealmPlayground as RealmPlayground
|
|||
from zerver.models.realms import Realm as Realm
|
||||
from zerver.models.realms import RealmAuthenticationMethod as RealmAuthenticationMethod
|
||||
from zerver.models.realms import RealmDomain as RealmDomain
|
||||
from zerver.models.recipients import Huddle as Huddle
|
||||
from zerver.models.recipients import DirectMessageGroup as DirectMessageGroup
|
||||
from zerver.models.recipients import Recipient as Recipient
|
||||
from zerver.models.scheduled_jobs import AbstractScheduledJob as AbstractScheduledJob
|
||||
from zerver.models.scheduled_jobs import MissedMessageEmailAddress as MissedMessageEmailAddress
|
||||
|
|
|
@ -21,18 +21,20 @@ class Recipient(models.Model):
|
|||
of audiences Zulip supports for a message.
|
||||
|
||||
Recipient has just two attributes: The enum type, and a type_id,
|
||||
which is the ID of the UserProfile/Stream/Huddle object containing
|
||||
all the metadata for the audience. There are 3 recipient types:
|
||||
which is the ID of the UserProfile/Stream/DirectMessageGroup object
|
||||
containing all the metadata for the audience. There are 3 recipient
|
||||
types:
|
||||
|
||||
1. 1:1 direct message: The type_id is the ID of the UserProfile
|
||||
who will receive any message to this Recipient. The sender
|
||||
of such a message is represented separately.
|
||||
2. Stream message: The type_id is the ID of the associated Stream.
|
||||
3. Group direct message: In Zulip, group direct messages are
|
||||
represented by Huddle objects, which encode the set of users
|
||||
in the conversation. The type_id is the ID of the associated Huddle
|
||||
object; the set of users is usually retrieved via the Subscription
|
||||
table. See the Huddle model for details.
|
||||
represented by DirectMessageGroup objects, which encode the set of
|
||||
users in the conversation. The type_id is the ID of the associated
|
||||
DirectMessageGroup object; the set of users is usually retrieved
|
||||
via the Subscription table. See the DirectMessageGroup model for
|
||||
details.
|
||||
|
||||
See also the Subscription model, which stores which UserProfile
|
||||
objects are subscribed to which Recipient objects.
|
||||
|
@ -112,26 +114,33 @@ def bulk_get_direct_message_group_user_ids(recipient_ids: List[int]) -> Dict[int
|
|||
return result_dict
|
||||
|
||||
|
||||
class Huddle(models.Model):
|
||||
class DirectMessageGroup(models.Model):
|
||||
"""
|
||||
Represents a group of individuals who may have a
|
||||
group direct message conversation together.
|
||||
|
||||
The membership of the Huddle is stored in the Subscription table just like with
|
||||
Streams - for each user in the Huddle, there is a Subscription object
|
||||
tied to the UserProfile and the Huddle's recipient object.
|
||||
The membership of the DirectMessageGroup is stored in the Subscription
|
||||
table just like with Streams - for each user in the DirectMessageGroup,
|
||||
there is a Subscription object tied to the UserProfile and the
|
||||
DirectMessageGroup's recipient object.
|
||||
|
||||
A hash of the list of user IDs is stored in the huddle_hash field
|
||||
below, to support efficiently mapping from a set of users to the
|
||||
corresponding Huddle object.
|
||||
corresponding DirectMessageGroup object.
|
||||
"""
|
||||
|
||||
# TODO: We should consider whether using
|
||||
# CommaSeparatedIntegerField would be better.
|
||||
huddle_hash = models.CharField(max_length=40, db_index=True, unique=True)
|
||||
# Foreign key to the Recipient object for this Huddle.
|
||||
# Foreign key to the Recipient object for this DirectMessageGroup.
|
||||
recipient = models.ForeignKey(Recipient, null=True, on_delete=models.SET_NULL)
|
||||
|
||||
# TODO: The model still uses the old "zerver_huddle" database table.
|
||||
# As a part of the migration of "Huddle" to "DirectMessageGroup"
|
||||
# it needs to be renamed to "zerver_directmessagegroup".
|
||||
class Meta:
|
||||
db_table = "zerver_huddle"
|
||||
|
||||
|
||||
def get_direct_message_group_hash(id_list: List[int]) -> str:
|
||||
id_list = sorted(set(id_list))
|
||||
|
@ -139,17 +148,18 @@ def get_direct_message_group_hash(id_list: List[int]) -> str:
|
|||
return hashlib.sha1(hash_key.encode()).hexdigest()
|
||||
|
||||
|
||||
def get_or_create_direct_message_group(id_list: List[int]) -> Huddle:
|
||||
def get_or_create_direct_message_group(id_list: List[int]) -> DirectMessageGroup:
|
||||
"""
|
||||
Takes a list of user IDs and returns the Huddle object for the
|
||||
group consisting of these users. If the Huddle object does not
|
||||
yet exist, it will be transparently created.
|
||||
Takes a list of user IDs and returns the DirectMessageGroup
|
||||
object for the group consisting of these users. If the
|
||||
DirectMessageGroup object does not yet exist, it will be
|
||||
transparently created.
|
||||
"""
|
||||
from zerver.models import Subscription, UserProfile
|
||||
|
||||
direct_message_group_hash = get_direct_message_group_hash(id_list)
|
||||
with transaction.atomic():
|
||||
(direct_message_group, created) = Huddle.objects.get_or_create(
|
||||
(direct_message_group, created) = DirectMessageGroup.objects.get_or_create(
|
||||
huddle_hash=direct_message_group_hash
|
||||
)
|
||||
if created:
|
||||
|
|
|
@ -62,8 +62,8 @@ from zerver.models import (
|
|||
BotStorageData,
|
||||
CustomProfileField,
|
||||
CustomProfileFieldValue,
|
||||
DirectMessageGroup,
|
||||
GroupGroupMembership,
|
||||
Huddle,
|
||||
Message,
|
||||
MutedUser,
|
||||
NamedUserGroup,
|
||||
|
@ -584,12 +584,12 @@ class RealmImportExportTest(ExportFile):
|
|||
self.send_group_direct_message(
|
||||
self.example_user("iago"), [self.example_user("cordelia"), self.example_user("AARON")]
|
||||
)
|
||||
direct_message_group_a = Huddle.objects.last()
|
||||
direct_message_group_a = DirectMessageGroup.objects.last()
|
||||
self.send_group_direct_message(
|
||||
self.example_user("ZOE"),
|
||||
[self.example_user("hamlet"), self.example_user("AARON"), self.example_user("othello")],
|
||||
)
|
||||
direct_message_group_b = Huddle.objects.last()
|
||||
direct_message_group_b = DirectMessageGroup.objects.last()
|
||||
|
||||
direct_message_group_c_message_id = self.send_group_direct_message(
|
||||
self.example_user("AARON"),
|
||||
|
@ -1043,8 +1043,9 @@ class RealmImportExportTest(ExportFile):
|
|||
Recipient.objects.get(type=Recipient.STREAM, type_id=stream.id).id,
|
||||
)
|
||||
|
||||
for dm_group in Huddle.objects.all():
|
||||
# Huddles don't have a realm column, so we just test all Huddles for simplicity.
|
||||
for dm_group in DirectMessageGroup.objects.all():
|
||||
# Direct Message groups don't have a realm column, so we just test all
|
||||
# Direct Message groups for simplicity.
|
||||
self.assertEqual(
|
||||
dm_group.recipient_id,
|
||||
Recipient.objects.get(type=Recipient.DIRECT_MESSAGE_GROUP, type_id=dm_group.id).id,
|
||||
|
@ -1272,7 +1273,9 @@ class RealmImportExportTest(ExportFile):
|
|||
@getter
|
||||
def get_group_direct_message(r: Realm) -> str:
|
||||
direct_message_group_hash = get_direct_message_group_hashes(r)
|
||||
direct_message_group_id = Huddle.objects.get(huddle_hash=direct_message_group_hash).id
|
||||
direct_message_group_id = DirectMessageGroup.objects.get(
|
||||
huddle_hash=direct_message_group_hash
|
||||
).id
|
||||
direct_message_group_recipient = Recipient.objects.get(
|
||||
type_id=direct_message_group_id, type=3
|
||||
)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import orjson
|
||||
|
||||
from zerver.lib.test_classes import ZulipTestCase
|
||||
from zerver.models import Huddle
|
||||
from zerver.models import DirectMessageGroup
|
||||
from zerver.models.recipients import get_direct_message_group_hash
|
||||
|
||||
|
||||
|
@ -203,7 +203,9 @@ class TypingHappyPathTestDirectMessages(ZulipTestCase):
|
|||
expected_recipient_ids = {user.id for user in expected_recipients}
|
||||
|
||||
direct_message_group_hash = get_direct_message_group_hash(list(expected_recipient_ids))
|
||||
self.assertFalse(Huddle.objects.filter(huddle_hash=direct_message_group_hash).exists())
|
||||
self.assertFalse(
|
||||
DirectMessageGroup.objects.filter(huddle_hash=direct_message_group_hash).exists()
|
||||
)
|
||||
|
||||
params = dict(
|
||||
to=orjson.dumps([user.id for user in recipient_users]).decode(),
|
||||
|
@ -219,7 +221,9 @@ class TypingHappyPathTestDirectMessages(ZulipTestCase):
|
|||
# We should not be adding new Direct Message groups
|
||||
# just because a user started typing in the compose
|
||||
# box. Let's wait till they send an actual message.
|
||||
self.assertFalse(Huddle.objects.filter(huddle_hash=direct_message_group_hash).exists())
|
||||
self.assertFalse(
|
||||
DirectMessageGroup.objects.filter(huddle_hash=direct_message_group_hash).exists()
|
||||
)
|
||||
|
||||
event = events[0]["event"]
|
||||
event_recipient_emails = {user["email"] for user in event["recipients"]}
|
||||
|
|
|
@ -51,8 +51,8 @@ from zerver.models import (
|
|||
Client,
|
||||
CustomProfileField,
|
||||
DefaultStream,
|
||||
DirectMessageGroup,
|
||||
Draft,
|
||||
Huddle,
|
||||
Message,
|
||||
Reaction,
|
||||
Realm,
|
||||
|
@ -127,7 +127,7 @@ def clear_database() -> None:
|
|||
Recipient,
|
||||
Realm,
|
||||
Subscription,
|
||||
Huddle,
|
||||
DirectMessageGroup,
|
||||
UserMessage,
|
||||
Client,
|
||||
DefaultStream,
|
||||
|
|
Loading…
Reference in New Issue