models: Remove type prefixes from __str__ values.

The Django convention is for __repr__ to include the type and __str__
to omit it.  In fact its default __repr__ implementation for models
automatically adds a type prefix to __str__, which has resulted in the
type being duplicated:

    >>> UserProfile.objects.first()
    <UserProfile: <UserProfile: emailgateway@zulip.com <Realm: zulipinternal 1>>>

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2023-03-08 13:18:59 -08:00 committed by Anders Kaseorg
parent f66136fcc2
commit 2d9b2a2a05
18 changed files with 80 additions and 82 deletions

View File

@ -62,7 +62,7 @@ class CountStat:
else:
self.interval = self.time_increment
def __str__(self) -> str:
def __repr__(self) -> str:
return f"<CountStat: {self.property}>"
def last_successful_fill(self) -> Optional[datetime]:

View File

@ -17,7 +17,7 @@ class FillState(models.Model):
state = models.PositiveSmallIntegerField()
def __str__(self) -> str:
return f"<FillState: {self.property} {self.end_time} {self.state}>"
return f"{self.property} {self.end_time} {self.state}"
# The earliest/starting end_time in FillState
@ -59,7 +59,7 @@ class InstallationCount(BaseCount):
]
def __str__(self) -> str:
return f"<InstallationCount: {self.property} {self.subgroup} {self.value}>"
return f"{self.property} {self.subgroup} {self.value}"
class RealmCount(BaseCount):
@ -82,7 +82,7 @@ class RealmCount(BaseCount):
index_together = ["property", "end_time"]
def __str__(self) -> str:
return f"<RealmCount: {self.realm} {self.property} {self.subgroup} {self.value}>"
return f"{self.realm!r} {self.property} {self.subgroup} {self.value}"
class UserCount(BaseCount):
@ -108,7 +108,7 @@ class UserCount(BaseCount):
index_together = ["property", "realm", "end_time"]
def __str__(self) -> str:
return f"<UserCount: {self.user} {self.property} {self.subgroup} {self.value}>"
return f"{self.user!r} {self.property} {self.subgroup} {self.value}"
class StreamCount(BaseCount):
@ -134,6 +134,4 @@ class StreamCount(BaseCount):
index_together = ["property", "realm", "end_time"]
def __str__(self) -> str:
return (
f"<StreamCount: {self.stream} {self.property} {self.subgroup} {self.value} {self.id}>"
)
return f"{self.stream!r} {self.property} {self.subgroup} {self.value} {self.id}"

View File

@ -180,7 +180,7 @@ class Confirmation(models.Model):
type = models.PositiveSmallIntegerField()
def __str__(self) -> str:
return f"<Confirmation: {self.content_object}>"
return f"{self.content_object!r}"
class Meta:
unique_together = ("type", "confirmation_key")

View File

@ -43,7 +43,7 @@ class Customer(models.Model):
return is_cloud
def __str__(self) -> str:
return f"<Customer {self.realm} {self.stripe_customer_id}>"
return f"{self.realm!r} {self.stripe_customer_id}"
def get_customer_by_realm(realm: Realm) -> Optional[Customer]:

View File

@ -10,7 +10,7 @@ exclude_lines =
# Don't require coverage for test suite AssertionError -- they're usually for clarity
raise AssertionError
# Don't require coverage for __str__ statements just used for printing
def __str__[(]self[)] -> .*:
def __(repr|str)__[(]self[)] -> .*:
# Don't require coverage for errors about unsupported webhook event types
raise UnsupportedWebhookEventTypeError
# Don't require coverage for blocks only run when type-checking

View File

@ -801,7 +801,7 @@ class Realm(models.Model): # type: ignore[django-manager-missing] # django-stub
return ret
def __str__(self) -> str:
return f"<Realm: {self.string_id} {self.id}>"
return f"{self.string_id} {self.id}"
# `realm` instead of `self` here to make sure the parameters of the cache key
# function matches the original method.
@ -1113,7 +1113,7 @@ class RealmEmoji(models.Model):
STILL_PATH_ID_TEMPLATE = "{realm_id}/emoji/images/still/{emoji_filename_without_extension}.png"
def __str__(self) -> str:
return f"<RealmEmoji({self.realm.string_id}): {self.id} {self.name} {self.deactivated} {self.file_name}>"
return f"{self.realm.string_id}: {self.id} {self.name} {self.deactivated} {self.file_name}"
class Meta:
constraints = [
@ -1316,7 +1316,7 @@ class RealmFilter(models.Model):
)
def __str__(self) -> str:
return f"<RealmFilter({self.realm.string_id}): {self.pattern} {self.url_format_string}>"
return f"{self.realm.string_id}: {self.pattern} {self.url_format_string}"
def get_linkifiers_cache_key(realm_id: int) -> str:
@ -1413,7 +1413,7 @@ class RealmPlayground(models.Model):
unique_together = (("realm", "pygments_language", "name"),)
def __str__(self) -> str:
return f"<RealmPlayground({self.realm.string_id}): {self.pygments_language} {self.name}>"
return f"{self.realm.string_id}: {self.pygments_language} {self.name}"
def get_realm_playgrounds(realm: Realm) -> List[RealmPlaygroundDict]:
@ -1479,7 +1479,7 @@ class Recipient(models.Model):
def __str__(self) -> str:
display_recipient = get_display_recipient(self)
return f"<Recipient: {display_recipient} ({self.type_id}, {self.type})>"
return f"{display_recipient} ({self.type_id}, {self.type})"
class UserBaseSettings(models.Model):
@ -1977,7 +1977,7 @@ class UserProfile(AbstractBaseUser, PermissionsMixin, UserBaseSettings): # type
return False
def __str__(self) -> str:
return f"<UserProfile: {self.email} {self.realm}>"
return f"{self.email} {self.realm!r}"
@property
def is_provisional_member(self) -> bool:
@ -2562,7 +2562,7 @@ class Stream(models.Model):
}
def __str__(self) -> str:
return f"<Stream: {self.name}>"
return self.name
def is_public(self) -> bool:
# All streams are private in Zephyr mirroring realms.
@ -2695,7 +2695,7 @@ class UserTopic(models.Model):
]
def __str__(self) -> str:
return f"<UserTopic: ({self.user_profile.email}, {self.stream.name}, {self.topic_name}, {self.last_updated})>"
return f"({self.user_profile.email}, {self.stream.name}, {self.topic_name}, {self.last_updated})"
class MutedUser(models.Model):
@ -2707,7 +2707,7 @@ class MutedUser(models.Model):
unique_together = ("user_profile", "muted_user")
def __str__(self) -> str:
return f"<MutedUser: {self.user_profile.email} -> {self.muted_user.email}>"
return f"{self.user_profile.email} -> {self.muted_user.email}"
post_save.connect(flush_muting_users_cache, sender=MutedUser)
@ -2719,7 +2719,7 @@ class Client(models.Model):
name = models.CharField(max_length=MAX_NAME_LENGTH, db_index=True, unique=True)
def __str__(self) -> str:
return f"<Client: {self.name}>"
return self.name
get_client_cache: Dict[str, Client] = {}
@ -2905,7 +2905,7 @@ class AbstractMessage(models.Model):
def __str__(self) -> str:
display_recipient = get_display_recipient(self.recipient)
return f"<{type(self).__name__}: {display_recipient} / {self.subject} / {self.sender}>"
return f"{display_recipient} / {self.subject} / {self.sender!r}"
class ArchiveTransaction(models.Model):
@ -2923,7 +2923,7 @@ class ArchiveTransaction(models.Model):
realm = models.ForeignKey(Realm, null=True, on_delete=CASCADE)
def __str__(self) -> str:
return "ArchiveTransaction id: {id}, type: {type}, realm: {realm}, timestamp: {timestamp}".format(
return "id: {id}, type: {type}, realm: {realm}, timestamp: {timestamp}".format(
id=self.id,
type="MANUAL" if self.type == self.MANUAL else "RETENTION_POLICY_BASED",
realm=self.realm.string_id if self.realm else None,
@ -3094,7 +3094,7 @@ class Draft(models.Model):
last_edit_time = models.DateTimeField(db_index=True)
def __str__(self) -> str:
return f"<{type(self).__name__}: {self.user_profile.email} / {self.id} / {self.last_edit_time}>"
return f"{self.user_profile.email} / {self.id} / {self.last_edit_time}"
def to_dict(self) -> Dict[str, Any]:
if self.recipient is None:
@ -3391,7 +3391,7 @@ class UserMessage(AbstractUserMessage):
def __str__(self) -> str:
display_recipient = get_display_recipient(self.message.recipient)
return f"<{type(self).__name__}: {display_recipient} / {self.user_profile.email} ({self.flags_list()})>"
return f"{display_recipient} / {self.user_profile.email} ({self.flags_list()})"
@staticmethod
def select_for_update_query() -> QuerySet["UserMessage"]:
@ -3429,7 +3429,7 @@ class ArchivedUserMessage(AbstractUserMessage):
def __str__(self) -> str:
display_recipient = get_display_recipient(self.message.recipient)
return f"<{type(self).__name__}: {display_recipient} / {self.user_profile.email} ({self.flags_list()})>"
return f"{display_recipient} / {self.user_profile.email} ({self.flags_list()})"
class AbstractAttachment(models.Model):
@ -3471,7 +3471,7 @@ class AbstractAttachment(models.Model):
abstract = True
def __str__(self) -> str:
return f"<{type(self).__name__}: {self.file_name}>"
return self.file_name
class ArchivedAttachment(AbstractAttachment):
@ -3713,7 +3713,7 @@ class Subscription(models.Model):
]
def __str__(self) -> str:
return f"<Subscription: {self.user_profile} -> {self.recipient}>"
return f"{self.user_profile!r} -> {self.recipient!r}"
# Subscription fields included whenever a Subscription object is provided to
# Zulip clients via the API. A few details worth noting:
@ -4208,7 +4208,7 @@ class ScheduledEmail(AbstractScheduledJob):
type = models.PositiveSmallIntegerField()
def __str__(self) -> str:
return f"<ScheduledEmail: {self.type} {self.address or list(self.users.all())} {self.scheduled_timestamp}>"
return f"{self.type} {self.address or list(self.users.all())} {self.scheduled_timestamp}"
class MissedMessageEmailAddress(models.Model):
@ -4295,7 +4295,7 @@ class ScheduledMessage(models.Model):
def __str__(self) -> str:
display_recipient = get_display_recipient(self.recipient)
return f"<ScheduledMessage: {display_recipient} {self.subject} {self.sender} {self.scheduled_timestamp}>"
return f"{display_recipient} {self.subject} {self.sender!r} {self.scheduled_timestamp}"
EMAIL_TYPES = {
@ -4471,10 +4471,10 @@ class RealmAuditLog(AbstractRealmAuditLog):
def __str__(self) -> str:
if self.modified_user is not None:
return f"<RealmAuditLog: {self.modified_user} {self.event_type} {self.event_time} {self.id}>"
return f"{self.modified_user!r} {self.event_type} {self.event_time} {self.id}"
if self.modified_stream is not None:
return f"<RealmAuditLog: {self.modified_stream} {self.event_type} {self.event_time} {self.id}>"
return f"<RealmAuditLog: {self.realm} {self.event_type} {self.event_time} {self.id}>"
return f"{self.modified_stream!r} {self.event_type} {self.event_time} {self.id}"
return f"{self.realm!r} {self.event_type} {self.event_time} {self.id}"
class UserHotspot(models.Model):
@ -4623,7 +4623,7 @@ class CustomProfileField(models.Model):
return False
def __str__(self) -> str:
return f"<CustomProfileField: {self.realm} {self.name} {self.field_type} {self.order}>"
return f"{self.realm!r} {self.name} {self.field_type} {self.order}"
def custom_profile_fields_for_realm(realm_id: int) -> QuerySet[CustomProfileField]:
@ -4640,7 +4640,7 @@ class CustomProfileFieldValue(models.Model):
unique_together = ("user_profile", "field")
def __str__(self) -> str:
return f"<CustomProfileFieldValue: {self.user_profile} {self.field} {self.value}>"
return f"{self.user_profile!r} {self.field!r} {self.value}"
# Interfaces for services

View File

@ -211,8 +211,8 @@ class TestRealmAuditLog(ZulipTestCase):
event_type=RealmAuditLog.USER_EMAIL_CHANGED, event_time__gte=now
)
self.assertTrue(
str(audit_entry).startswith(
f"<RealmAuditLog: <UserProfile: {user.email} {user.realm}> {RealmAuditLog.USER_EMAIL_CHANGED} "
repr(audit_entry).startswith(
f"<RealmAuditLog: <UserProfile: {user.email} {user.realm!r}> {RealmAuditLog.USER_EMAIL_CHANGED} "
)
)

View File

@ -435,7 +435,7 @@ class RateLimitTests(ZulipTestCase):
self.assertEqual(
m.output,
[
f"WARNING:zilencer.auth:Remote server <RemoteZulipServer demo.example.com {server_uuid[:12]}> exceeded rate limits on domain api_by_remote_server"
f"WARNING:zilencer.auth:Remote server <RemoteZulipServer: demo.example.com {server_uuid[:12]}> exceeded rate limits on domain api_by_remote_server"
],
)
finally:

View File

@ -1334,13 +1334,13 @@ class MarkdownTest(ZulipTestCase):
)
def check_add_linkifiers(
self, linkifiers: List[RealmFilter], expected_linkifier_strs: List[str]
self, linkifiers: List[RealmFilter], expected_linkifier_reprs: List[str]
) -> None:
self.assert_length(linkifiers, len(expected_linkifier_strs))
for linkifier, expected_linkifier_str in zip(linkifiers, expected_linkifier_strs):
self.assert_length(linkifiers, len(expected_linkifier_reprs))
for linkifier, expected_linkifier_repr in zip(linkifiers, expected_linkifier_reprs):
linkifier.clean()
linkifier.save()
self.assertEqual(str(linkifier), expected_linkifier_str)
self.assertEqual(repr(linkifier), expected_linkifier_repr)
def test_realm_patterns(self) -> None:
realm = get_realm("zulip")
@ -1352,7 +1352,7 @@ class MarkdownTest(ZulipTestCase):
url_format_string=r"https://trac.example.com/ticket/%(id)s",
)
],
["<RealmFilter(zulip): #(?P<id>[0-9]{2,8}) https://trac.example.com/ticket/%(id)s>"],
["<RealmFilter: zulip: #(?P<id>[0-9]{2,8}) https://trac.example.com/ticket/%(id)s>"],
)
msg = Message(sender=self.example_user("othello"))
@ -1519,9 +1519,9 @@ class MarkdownTest(ZulipTestCase):
),
],
[
"<RealmFilter(zulip): (?P<id>ABC-[0-9]+) https://trac.example.com/ticket/%(id)s>",
"<RealmFilter(zulip): (?P<id>[A-Z][A-Z0-9]*-[0-9]+) https://other-trac.example.com/ticket/%(id)s>",
"<RealmFilter(zulip): (?P<id>[A-Z][A-Z0-9]+) https://yet-another-trac.example.com/ticket/%(id)s>",
"<RealmFilter: zulip: (?P<id>ABC-[0-9]+) https://trac.example.com/ticket/%(id)s>",
"<RealmFilter: zulip: (?P<id>[A-Z][A-Z0-9]*-[0-9]+) https://other-trac.example.com/ticket/%(id)s>",
"<RealmFilter: zulip: (?P<id>[A-Z][A-Z0-9]+) https://yet-another-trac.example.com/ticket/%(id)s>",
],
)
@ -1581,8 +1581,8 @@ class MarkdownTest(ZulipTestCase):
),
],
[
"<RealmFilter(zulip): ABC-42 https://google.com>",
r"<RealmFilter(zulip): com.+(?P<id>ABC\-[0-9]+) https://trac.example.com/ticket/%(id)s>",
"<RealmFilter: zulip: ABC-42 https://google.com>",
r"<RealmFilter: zulip: com.+(?P<id>ABC\-[0-9]+) https://trac.example.com/ticket/%(id)s>",
],
)
@ -1640,10 +1640,10 @@ class MarkdownTest(ZulipTestCase):
),
],
[
"<RealmFilter(zulip): http http://example.com/>",
"<RealmFilter(zulip): b#(?P<id>[a-z]+) http://example.com/b/%(id)s>",
"<RealmFilter(zulip): a#(?P<aid>[a-z]+) b#(?P<bid>[a-z]+) http://example.com/a/%(aid)s/b/%(bid)s>",
"<RealmFilter(zulip): a#(?P<id>[a-z]+) http://example.com/a/%(id)s>",
"<RealmFilter: zulip: http http://example.com/>",
"<RealmFilter: zulip: b#(?P<id>[a-z]+) http://example.com/b/%(id)s>",
"<RealmFilter: zulip: a#(?P<aid>[a-z]+) b#(?P<bid>[a-z]+) http://example.com/a/%(aid)s/b/%(bid)s>",
"<RealmFilter: zulip: a#(?P<id>[a-z]+) http://example.com/a/%(id)s>",
],
)
# There should be 5 link matches in the topic, if ordered from the most priortized to the least:
@ -2431,8 +2431,8 @@ class MarkdownTest(ZulipTestCase):
)
linkifier.save()
self.assertEqual(
str(linkifier),
"<RealmFilter(zulip): #(?P<id>[0-9]{2,8}) https://trac.example.com/ticket/%(id)s>",
repr(linkifier),
"<RealmFilter: zulip: #(?P<id>[0-9]{2,8}) https://trac.example.com/ticket/%(id)s>",
)
# Create a user that potentially interferes with the pattern.
test_user = create_user(
@ -2519,8 +2519,8 @@ class MarkdownTest(ZulipTestCase):
)
linkifier.save()
self.assertEqual(
str(linkifier),
"<RealmFilter(zulip): #(?P<id>[0-9]{2,8}) https://trac.example.com/ticket/%(id)s>",
repr(linkifier),
"<RealmFilter: zulip: #(?P<id>[0-9]{2,8}) https://trac.example.com/ticket/%(id)s>",
)
# Create a user-group that potentially interferes with the pattern.
user_id = user_profile.id
@ -2777,8 +2777,8 @@ class MarkdownTest(ZulipTestCase):
)
linkifier.save()
self.assertEqual(
str(linkifier),
"<RealmFilter(zulip): #(?P<id>[0-9]{2,8}) https://trac.example.com/ticket/%(id)s>",
repr(linkifier),
"<RealmFilter: zulip: #(?P<id>[0-9]{2,8}) https://trac.example.com/ticket/%(id)s>",
)
# Create a topic link that potentially interferes with the pattern.
denmark = get_stream("Denmark", realm)
@ -2846,8 +2846,8 @@ class MarkdownTest(ZulipTestCase):
)
linkifier.save()
self.assertEqual(
str(linkifier),
"<RealmFilter(zulip): #(?P<id>[0-9]{2,8}) https://trac.example.com/ticket/%(id)s>",
repr(linkifier),
"<RealmFilter: zulip: #(?P<id>[0-9]{2,8}) https://trac.example.com/ticket/%(id)s>",
)
# Create a stream that potentially interferes with the pattern.
stream = self.make_stream(stream_name="Stream #1234", realm=realm)

View File

@ -257,8 +257,8 @@ class MessageDictTest(ZulipTestCase):
realm=zulip_realm, pattern=r"#(?P<id>[0-9]{2,8})", url_format_string=url_format_string
)
self.assertEqual(
str(linkifier),
"<RealmFilter(zulip): #(?P<id>[0-9]{2,8}) https://trac.example.com/ticket/%(id)s>",
repr(linkifier),
"<RealmFilter: zulip: #(?P<id>[0-9]{2,8}) https://trac.example.com/ticket/%(id)s>",
)
def get_message(sender: UserProfile, realm: Realm) -> Message:

View File

@ -1645,9 +1645,9 @@ class StreamMessagesTest(ZulipTestCase):
self.send_stream_message(sender, "Denmark", content="whatever", topic_name="my topic")
message = most_recent_message(receiving_user_profile)
self.assertEqual(
str(message),
repr(message),
"<Message: Denmark / my topic / "
"<UserProfile: {} {}>>".format(sender.email, sender.realm),
"<UserProfile: {} {!r}>>".format(sender.email, sender.realm),
)
def test_message_mentions(self) -> None:

View File

@ -25,7 +25,7 @@ class TestClientModel(ZulipTestCase):
This test is designed to cover __str__ method for Client.
"""
client = make_client("some_client")
self.assertEqual(str(client), "<Client: some_client>")
self.assertEqual(repr(client), "<Client: some_client>")
class UserPresenceModelTests(ZulipTestCase):

View File

@ -109,8 +109,8 @@ class RealmEmojiTest(ZulipTestCase):
realm_emoji = RealmEmoji.objects.get(name="green_tick")
file_name = str(realm_emoji.id) + ".png"
self.assertEqual(
str(realm_emoji),
f"<RealmEmoji(zulip): {realm_emoji.id} green_tick False {file_name}>",
repr(realm_emoji),
f"<RealmEmoji: zulip: {realm_emoji.id} green_tick False {file_name}>",
)
def test_upload_exception(self) -> None:

View File

@ -356,14 +356,14 @@ class AddNewUserHistoryTest(ZulipTestCase):
with patch("zerver.models.get_display_recipient", return_value="recip"):
self.assertEqual(
str(message),
repr(message),
"<Message: recip / / "
"<UserProfile: {} {}>>".format(user_profile.email, user_profile.realm),
"<UserProfile: {} {!r}>>".format(user_profile.email, user_profile.realm),
)
user_message = most_recent_usermessage(user_profile)
self.assertEqual(
str(user_message),
repr(user_message),
f"<UserMessage: recip / {user_profile.email} ([])>",
)

View File

@ -552,7 +552,7 @@ class RecipientTest(ZulipTestCase):
type_id=stream.id,
type=Recipient.STREAM,
)
self.assertEqual(str(recipient), f"<Recipient: Verona ({stream.id}, {Recipient.STREAM})>")
self.assertEqual(repr(recipient), f"<Recipient: Verona ({stream.id}, {Recipient.STREAM})>")
class StreamAdminTest(ZulipTestCase):
@ -5111,11 +5111,11 @@ class SubscriptionAPITest(ZulipTestCase):
)
subscription = self.get_subscription(user_profile, invite_streams[0])
with mock.patch("zerver.models.Recipient.__str__", return_value="recip"):
with mock.patch("zerver.models.Recipient.__repr__", return_value="recip"):
self.assertEqual(
str(subscription),
repr(subscription),
"<Subscription: "
f"<UserProfile: {user_profile.email} {user_profile.realm}> -> recip>",
f"<UserProfile: {user_profile.email} {user_profile.realm!r}> -> recip>",
)
self.assertIsNone(subscription.desktop_notifications)

View File

@ -390,7 +390,7 @@ class FileUploadTest(UploadSerializeMixin, ZulipTestCase):
d1_attachment = Attachment.objects.get(path_id=d1_path_id)
d1_attachment.create_time = two_week_ago
d1_attachment.save()
self.assertEqual(str(d1_attachment), "<Attachment: dummy_1.txt>")
self.assertEqual(repr(d1_attachment), "<Attachment: dummy_1.txt>")
# This Attachment won't have any messages.
d2_attachment = Attachment.objects.get(path_id=d2_path_id)
d2_attachment.create_time = two_week_ago

View File

@ -61,7 +61,7 @@ def rate_limit_remote_server(
try:
RateLimitedRemoteZulipServer(remote_server, domain=domain).rate_limit_request(request)
except RateLimitedError as e:
logger.warning("Remote server %s exceeded rate limits on domain %s", remote_server, domain)
logger.warning("Remote server %r exceeded rate limits on domain %s", remote_server, domain)
raise e

View File

@ -50,7 +50,7 @@ class RemoteZulipServer(models.Model):
plan_type = models.PositiveSmallIntegerField(default=PLAN_TYPE_SELF_HOSTED)
def __str__(self) -> str:
return f"<RemoteZulipServer {self.hostname} {str(self.uuid)[0:12]}>"
return f"{self.hostname} {str(self.uuid)[0:12]}"
def format_requestor_for_logs(self) -> str:
return "zulip-server:" + str(self.uuid)
@ -75,7 +75,7 @@ class RemotePushDeviceToken(AbstractPushDeviceToken):
]
def __str__(self) -> str:
return f"<RemotePushDeviceToken {self.server} {self.user_id}>"
return f"{self.server!r} {self.user_id}"
class RemoteZulipServerAuditLog(AbstractRealmAuditLog):
@ -91,7 +91,7 @@ class RemoteZulipServerAuditLog(AbstractRealmAuditLog):
server = models.ForeignKey(RemoteZulipServer, on_delete=models.CASCADE)
def __str__(self) -> str:
return f"<RemoteZulipServerAuditLog: {self.server} {self.event_type} {self.event_time} {self.id}>"
return f"{self.server!r} {self.event_type} {self.event_time} {self.id}"
class RemoteRealmAuditLog(AbstractRealmAuditLog):
@ -105,7 +105,7 @@ class RemoteRealmAuditLog(AbstractRealmAuditLog):
remote_id = models.IntegerField(db_index=True)
def __str__(self) -> str:
return f"<RemoteRealmAuditLog: {self.server} {self.event_type} {self.event_time} {self.id}>"
return f"{self.server!r} {self.event_type} {self.event_time} {self.id}"
class RemoteInstallationCount(BaseCount):
@ -120,7 +120,7 @@ class RemoteInstallationCount(BaseCount):
]
def __str__(self) -> str:
return f"<InstallationCount: {self.property} {self.subgroup} {self.value}>"
return f"{self.property} {self.subgroup} {self.value}"
# We can't subclass RealmCount because we only have a realm_id here, not a foreign key.
@ -138,7 +138,7 @@ class RemoteRealmCount(BaseCount):
]
def __str__(self) -> str:
return f"{self.server} {self.realm_id} {self.property} {self.subgroup} {self.value}"
return f"{self.server!r} {self.realm_id} {self.property} {self.subgroup} {self.value}"
class RateLimitedRemoteZulipServer(RateLimitedObject):