Skip to content

Commit 895a7a4

Browse files
committed
model/api_types: Add data structures to support non-subscribed streams.
This commit creates data structures, similar to stream_dict, to support unsubscribed and never-subscribed streams. These streams are available in the fetched initial data which is used to populate the new data structures using the _register_non_subscribed_streams function. Test updated and fixtures added.
1 parent a37d0c4 commit 895a7a4

File tree

4 files changed

+125
-46
lines changed

4 files changed

+125
-46
lines changed

tests/conftest.py

Lines changed: 86 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
CustomProfileField,
1212
Message,
1313
MessageType,
14+
Stream,
15+
Subscription,
1416
)
1517
from zulipterminal.config.keys import (
1618
ZT_TO_URWID_CMD_MAPPING,
@@ -339,6 +341,66 @@ def streams_fixture(
339341
return deepcopy(streams)
340342

341343

344+
@pytest.fixture
345+
def unsubscribed_streams_fixture() -> List[Subscription]:
346+
unsubscribed_streams: List[Subscription] = []
347+
for i in range(3, 5):
348+
unsubscribed_streams.append(
349+
{
350+
"name": f"Stream {i}",
351+
"date_created": 1472047124 + i,
352+
"invite_only": False,
353+
"color": "#b0a5fd",
354+
"pin_to_top": False,
355+
"stream_id": i,
356+
"is_muted": False,
357+
"audible_notifications": False,
358+
"description": f"A description of stream {i}",
359+
"rendered_description": f"A description of stream {i}",
360+
"desktop_notifications": False,
361+
"stream_weekly_traffic": 0,
362+
"push_notifications": False,
363+
"message_retention_days": i + 30,
364+
"email_address": f"stream{i}@example.com",
365+
"email_notifications": False,
366+
"wildcard_mentions_notify": False,
367+
"subscribers": [1001, 11, 12],
368+
"history_public_to_subscribers": True,
369+
"is_announcement_only": True,
370+
"stream_post_policy": 0,
371+
"is_web_public": True,
372+
"first_message_id": None,
373+
"role": 1,
374+
}
375+
)
376+
return deepcopy(unsubscribed_streams)
377+
378+
379+
@pytest.fixture
380+
def never_subscribed_streams_fixture() -> List[Stream]:
381+
never_subscribed_streams: List[Stream] = []
382+
for i in range(5, 7):
383+
never_subscribed_streams.append(
384+
{
385+
"name": f"Stream {i}",
386+
"date_created": 1472047124 + i,
387+
"invite_only": False,
388+
"stream_id": i,
389+
"description": f"A description of stream {i}",
390+
"rendered_description": f"A description of stream {i}",
391+
"stream_weekly_traffic": 0,
392+
"message_retention_days": i + 30,
393+
"subscribers": [1001, 11, 12],
394+
"history_public_to_subscribers": True,
395+
"is_announcement_only": True,
396+
"stream_post_policy": 0,
397+
"is_web_public": True,
398+
"first_message_id": None,
399+
}
400+
)
401+
return deepcopy(never_subscribed_streams)
402+
403+
342404
@pytest.fixture
343405
def realm_emojis() -> Dict[str, Dict[str, Any]]:
344406
# Omitting source_url, author_id (server version 3.0),
@@ -873,6 +935,8 @@ def initial_data(
873935
logged_on_user: Dict[str, Any],
874936
users_fixture: List[Dict[str, Any]],
875937
streams_fixture: List[Dict[str, Any]],
938+
unsubscribed_streams_fixture: List[Subscription],
939+
never_subscribed_streams_fixture: List[Stream],
876940
realm_emojis: Dict[str, Dict[str, Any]],
877941
custom_profile_fields_fixture: List[Dict[str, Union[str, int]]],
878942
) -> Dict[str, Any]:
@@ -884,24 +948,7 @@ def initial_data(
884948
"email": logged_on_user["email"],
885949
"user_id": logged_on_user["user_id"],
886950
"realm_name": "Test Organization Name",
887-
"unsubscribed": [
888-
{
889-
"audible_notifications": False,
890-
"description": "announce",
891-
"stream_id": 7,
892-
"is_old_stream": True,
893-
"desktop_notifications": False,
894-
"pin_to_top": False,
895-
"stream_weekly_traffic": 0,
896-
"invite_only": False,
897-
"name": "announce",
898-
"push_notifications": False,
899-
"email_address": "",
900-
"color": "#bfd56f",
901-
"is_muted": False,
902-
"history_public_to_subscribers": True,
903-
}
904-
],
951+
"unsubscribed": unsubscribed_streams_fixture,
905952
"result": "success",
906953
"queue_id": "1522420755:786",
907954
"realm_users": users_fixture,
@@ -950,24 +997,7 @@ def initial_data(
950997
"subscriptions": streams_fixture,
951998
"msg": "",
952999
"max_message_id": 552761,
953-
"never_subscribed": [
954-
{
955-
"invite_only": False,
956-
"description": "Announcements from the Zulip GCI Mentors",
957-
"stream_id": 87,
958-
"name": "GCI announce",
959-
"is_old_stream": True,
960-
"stream_weekly_traffic": 0,
961-
},
962-
{
963-
"invite_only": False,
964-
"description": "General discussion",
965-
"stream_id": 74,
966-
"name": "GCI general",
967-
"is_old_stream": True,
968-
"stream_weekly_traffic": 0,
969-
},
970-
],
1000+
"never_subscribed": never_subscribed_streams_fixture,
9711001
"unread_msgs": {
9721002
"pms": [
9731003
{"sender_id": 1, "unread_message_ids": [1, 2]},
@@ -1437,6 +1467,26 @@ def stream_dict(streams_fixture: List[Dict[str, Any]]) -> Dict[int, Any]:
14371467
return {stream["stream_id"]: stream for stream in streams_fixture}
14381468

14391469

1470+
@pytest.fixture
1471+
def unsubscribed_streams(
1472+
unsubscribed_streams_fixture: List[Subscription],
1473+
) -> Dict[int, Subscription]:
1474+
return {
1475+
unsubscribed_stream["stream_id"]: unsubscribed_stream
1476+
for unsubscribed_stream in unsubscribed_streams_fixture
1477+
}
1478+
1479+
1480+
@pytest.fixture
1481+
def never_subscribed_streams(
1482+
never_subscribed_streams_fixture: List[Stream],
1483+
) -> Dict[int, Stream]:
1484+
return {
1485+
never_subscribed_stream["stream_id"]: never_subscribed_stream
1486+
for never_subscribed_stream in never_subscribed_streams_fixture
1487+
}
1488+
1489+
14401490
@pytest.fixture(
14411491
params=[
14421492
{

tests/model/test_model.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,17 @@ def test_init(
6363
realm_emojis_data,
6464
zulip_emoji,
6565
stream_dict,
66+
unsubscribed_streams,
67+
never_subscribed_streams,
6668
):
6769
assert hasattr(model, "controller")
6870
assert hasattr(model, "client")
6971
assert model.narrow == []
7072
assert model._have_last_message == {}
7173
assert model.stream_id is None
7274
assert model.stream_dict == stream_dict
75+
assert model._unsubscribed_streams == unsubscribed_streams
76+
assert model._never_subscribed_streams == never_subscribed_streams
7377
assert model.recipients == frozenset()
7478
assert model.index == initial_index
7579
assert model.last_unread_pm is None

zulipterminal/api_types.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -204,21 +204,33 @@ class Message(TypedDict, total=False):
204204

205205

206206
###############################################################################
207-
# In "subscriptions" response from:
207+
# In "subscriptions", "unsubscribed", and "never_subscribed" responses from:
208208
# https://zulip.com/api/register-queue
209209
# Also directly from:
210210
# https://zulip.com/api/get-events#subscription-add
211211
# https://zulip.com/api/get-subscriptions (unused)
212212

213213

214-
class Subscription(TypedDict):
214+
class Stream(TypedDict):
215215
stream_id: int
216216
name: str
217217
description: str
218218
rendered_description: str
219219
date_created: int # NOTE: new in Zulip 4.0 / ZFL 30
220220
invite_only: bool
221221
subscribers: List[int]
222+
223+
is_announcement_only: bool # Deprecated in Zulip 3.0 -> stream_post_policy
224+
stream_post_policy: int # NOTE: new in Zulip 3.0 / ZFL 1
225+
226+
is_web_public: bool
227+
message_retention_days: Optional[int] # NOTE: new in Zulip 3.0 / ZFL 17
228+
history_public_to_subscribers: bool
229+
first_message_id: Optional[int]
230+
stream_weekly_traffic: Optional[int]
231+
232+
233+
class Subscription(Stream):
222234
desktop_notifications: Optional[bool]
223235
email_notifications: Optional[bool]
224236
wildcard_mentions_notify: Optional[bool]
@@ -229,16 +241,8 @@ class Subscription(TypedDict):
229241

230242
is_muted: bool
231243

232-
is_announcement_only: bool # Deprecated in Zulip 3.0 -> stream_post_policy
233-
stream_post_policy: int # NOTE: new in Zulip 3.0 / ZFL 1
234-
235-
is_web_public: bool
236244
role: int # NOTE: new in Zulip 4.0 / ZFL 31
237245
color: str
238-
message_retention_days: Optional[int] # NOTE: new in Zulip 3.0 / ZFL 17
239-
history_public_to_subscribers: bool
240-
first_message_id: Optional[int]
241-
stream_weekly_traffic: Optional[int]
242246

243247
# Deprecated fields
244248
# in_home_view: bool # Replaced by is_muted in Zulip 2.1; still present in updates

zulipterminal/model.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
PrivateMessageUpdateRequest,
4747
RealmEmojiData,
4848
RealmUser,
49+
Stream,
4950
StreamComposition,
5051
StreamMessageUpdateRequest,
5152
Subscription,
@@ -177,11 +178,18 @@ def __init__(self, controller: Any) -> None:
177178
self._update_users_data_from_initial_data()
178179

179180
self.stream_dict: Dict[int, Any] = {}
181+
self._unsubscribed_streams: Dict[int, Subscription] = {}
182+
self._never_subscribed_streams: Dict[int, Stream] = {}
180183
self.muted_streams: Set[int] = set()
181184
self.pinned_streams: List[StreamData] = []
182185
self.unpinned_streams: List[StreamData] = []
183186
self.visual_notified_streams: Set[int] = set()
184187

188+
self._register_non_subscribed_streams(
189+
unsubscribed_streams=self.initial_data["unsubscribed"],
190+
never_subscribed_streams=self.initial_data["never_subscribed"],
191+
)
192+
185193
self._subscribe_to_streams(self.initial_data["subscriptions"])
186194

187195
# NOTE: The date_created field of stream has been added in feature
@@ -1260,6 +1268,19 @@ def user_name_from_id(self, user_id: int) -> str:
12601268

12611269
return self.user_dict[user_email]["full_name"]
12621270

1271+
def _register_non_subscribed_streams(
1272+
self,
1273+
unsubscribed_streams: List[Subscription],
1274+
never_subscribed_streams: List[Stream],
1275+
) -> None:
1276+
self._unsubscribed_streams = {
1277+
subscription["stream_id"]: subscription
1278+
for subscription in unsubscribed_streams
1279+
}
1280+
self._never_subscribed_streams = {
1281+
stream["stream_id"]: stream for stream in never_subscribed_streams
1282+
}
1283+
12631284
def _subscribe_to_streams(self, subscriptions: List[Subscription]) -> None:
12641285
def make_reduced_stream_data(stream: Subscription) -> StreamData:
12651286
# stream_id has been changed to id.

0 commit comments

Comments
 (0)