New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for all streams minimal #1430
base: main
Are you sure you want to change the base?
Add support for all streams minimal #1430
Conversation
Hello @theViz343, it seems like you have referenced #816 in your pull request description, but you have not referenced them in your commit message description(s). Referencing an issue in a commit message automatically closes the corresponding issue when the commit is merged, which makes the issue tracker easier to manage. Please run An example of a correctly-formatted commit:
To learn how to write a great commit message, please refer to our guide. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@theViz343 It's good to see another go at this one, though there are some comments from before to keep up with, including:
I'm happy with the core of this, but other than the points above was initially interested to see if the early new data in the Model you added could be confirmed in test_init using new fixtures. To see that you added fixtures which had similar data to test later code confirmed that would be useful, to test the data flow through the Model from the initial_data into the accessors.
zulipterminal/model.py
Outdated
@@ -1281,6 +1281,22 @@ def _register_non_subscribed_streams( | |||
stream["stream_id"]: stream for stream in never_subscribed_streams | |||
} | |||
|
|||
def _get_stream_from_id(self, stream_id: int) -> Union[Subscription, Stream]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only way to use this function with a subscription is with additional information and then casting?
Given that, perhaps set the return type to Stream
? We can have a separate function, something like _get_subscription_from_id
, specifically for subscription data. That will not need to search through the never-subscribed, and can provide a different error.
Note that you only need what you have here for supporting the name and other core stream data, whereas eg. color will need Subscription.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we do that, should I cast the subscribed
and unsubscribed
streams returned by this method to Stream
? That might make the usage of this method clearer too, ie. to only access stream properties (and not subscription properties) from the returned stream.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A cast shouldn't be necessary once you have the two different functions - you don't have that in the latest version of the code you just pushed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've casted the stream_dict and the unsubscribed_streams to a Stream
in the _get_stream_from_id
in the latest commit, so that methods which use the _get_stream_from_id
always access only the stream properties and not the subscription properties (which would then warrant the use of _get_subscription_from_id
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah right, but I don't remember seeing an explicit cast()
to work around mypy - I assume this works in the type system since a Stream is a subset of a Subscription.
tests/core/test_core.py
Outdated
controller.model.stream_dict = { | ||
stream_id: { | ||
stream_id: general_stream, | ||
} | ||
controller.model.stream_dict[stream_id].update( | ||
{ | ||
"color": "#ffffff", | ||
"name": stream_name, | ||
} | ||
} | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's good that this commit focuses on the stream/subscription migration, but
- it doesn't seem that the color is important to the test(s)?
- that could make this transition smaller/simpler
- can we replace the stream_dict code by setting the return_value in the model, in the later commits? (if we don't already)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the third point, which function's return_value are you referring to?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant that where you're moving to use the functions that access the name and color, instead of using stream_dict, can we now mock those functions and set the return value directly?
Essentially, we want to ensure we move away from the stream_dict fixture (or equivalent manual dicts), in addition to directly accessing the model attribute.
62f7883
to
84f31e9
Compare
0345e9f
to
01bda75
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@theViz343 Thanks for the update again 👍
Overall this is good, and the commits are generally clean and well tested.
I think most of my non-minor feedback has come about since this refactoring is complex - tidying types, correcting fixtures, fixing inconsistencies, adding data, using new accessors, removing old fixtures, integrating with existing code, updating old accessors - and so there are a lot of potential rough edges, some of which only surface later.
The stream_dict removals in the tests could be left for another time, certainly the complex cases.
I think clarifying the stream/subscription validity functions are likely the standout issue to address here, and which we need to be a little careful about since they're already in use, and we don't interact with all streams in every case.
zulipterminal/api_types.py
Outdated
# NOTE: Server data may not contain this field, in which case ZT adds it | ||
# and sets it to None. | ||
date_created: NotRequired[Optional[int]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Good comment, but you've lost the 'new in ...' details.
zulipterminal/api_types.py
Outdated
color: str | ||
|
||
# Deprecated fields | ||
# in_home_view: bool # Replaced by is_muted in Zulip 2.1; still present in updates | ||
# role: int # Removed in Zulip 6.0 / ZFL 133; not actively used by ZT or Zulip web |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Also present 4.0/ZFL31 until then.
"history_public_to_subscribers": True, | ||
} | ||
], | ||
"unsubscribed": unsubscribed_streams_fixture, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: I'd mention these changes to the fixtures in the commit text, even though we don't use them until now.
# https://zulip.com/api/register-queue | ||
# Also directly from: | ||
# https://zulip.com/api/get-events#subscription-add | ||
# https://zulip.com/api/get-subscriptions (unused) | ||
|
||
|
||
class Subscription(TypedDict): | ||
class Stream(TypedDict): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With all of the extra test material, and the next commits tidying up only the existing types/stream_dict, this refactor seems somewhat separate from the feature you're adding.
I'd consider splitting and shifting the new data addition until just before you start using them in the helper methods.
"first_message_id": None, | ||
}, | ||
), | ||
], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: Would be helpful to include some case ids here, to indicate that there is one test for a subscribed and one for unsubscribed stream?
Similarly for the other method.
These basically act as comments while reading the code.
write_box.model.is_valid_stream.return_value = is_valid_stream | ||
write_box.model.stream_dict = stream_dict | ||
write_box.model.get_all_stream_ids.return_value = all_stream_ids |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note how we're already using is_valid_stream
here, vs using all_stream_ids
, in reference to my other comment.
@@ -1005,11 +1005,7 @@ def test_msg_generates_search_and_header_bar( | |||
assert_header_bar, | |||
assert_search_bar, | |||
): | |||
self.model.stream_dict = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we remove other stream_dict in this file? (in that same trimming refactor, perhaps)
tests/model/test_model.py
Outdated
case( | ||
999, | ||
"#ddd", | ||
id="Unsubscribed stream", | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This stream is not an unsubscribed stream. A different test is fine to ensure the color is different, but an actual unsubscribed (not never) would be good to include.
write_box.model.subscription_color_from_id.side_effect = lambda x: stream_dict[ | ||
x | ||
]["color"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, this would be nice to avoid, but we might have to rethink the test.
tests/core/test_core.py
Outdated
} | ||
controller.model.stream_dict[stream_id]["name"] = stream_name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's necessary to keep this line for the test, can the stream_dict be removed instead later, when we switch to the new function?
01bda75
to
f03632e
Compare
This commit refactors the Subscription typeddict to separate Stream and Subscription TypedDicts. The Subscription TypedDict now inherits the Stream TypedDict. This is a preparatory refactor to later introduce the unsubscribed_streams and never_subscribed_streams to the model.
This commit updates the `date_created` and `stream_post_policy` fields present in the Stream typeddict, and the `role` field in the Subscription typeddict. For `date_created`, since servers with ZFL<30 do not include the field, but ZT does add it with a value of None to ensure consistency, the type is changed to `NotRequired[Optional[int]]`. For `stream_post_policy`, the field is only included after Zulip 3.0 / ZFL 1, so it has been changed to a NotRequired field. For `role`, the field has been removed in Zulip 6.0 (ZFL 133), so it has been removed from the Subscriptions typeddict and also from the unsubscribed_streams_fixture.
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.
With the revamp of the Subscription TypedDict in an earlier commit, we use it to improve the typing of stream_dict in this commit. The `is_old_stream` is removed from stream fixtures since ZFL 14 removes them from the Streams object. This field was always equivalent to stream_weekly_traffic != null on the same object. Tests and fixtures updated to support the new typing.
This commit adds three helper methods - _get_stream_from_id, _get_subscription_from_id, and get_all_stream_ids. These three helper methods help in preparation for adding stream and subscription property accessor methods in the next commits. Tests and fixture added.
This commit introduces the stream_name_from_id method in order to limit the direct accessing of stream_dict outside the model. The commit also replaces the access of the name attribute from stream_dict with the new method. Tests added and updated.
This commit introduces the subscription_color_from_id method in order to limit the direct accessing of stream_dict outside the model. The commit also replaces the access of the color attribute from stream_dict with the new method. Tests added and updated.
This commit removes the direct use of stream dicts in most of the tests and if necessary, patches the stream accessor methods created in a previous commit.
f03632e
to
d0c1a8d
Compare
Heads up @theViz343, we just merged some commits that conflict with the changes you made in this pull request! You can review this repository's recent commits to see where the conflicts occur. Please rebase your feature branch against the |
What does this PR do, and why?
This PR is very similar to #1408 and #1419 and combines elements of both. This PR keeps the initial commits from #1419 but replaces the general accessor methods with only an attribute-specific necessary method i.e "name".
Outstanding aspect(s)
External discussion & connections
Adding streams throws key error
How did you test this?
Self-review checklist for each commit
Visual changes