`member_ids` needs to be defined as an `Iterable` as it will otherwise
inferred to have incompatible types in the else branch.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
Luckily `QuerySet` supports type variables. This allows us
to type table_filtered_to_id more accurately.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
TODO: For now, we import `_QuerySet` as `ValuesQuerySet`. But there
is a convenient reexport of `ValuesQuerySet` in `django_stubs_ext`
that does the same thing. Once we get django-stubs integrated,
we should import `ValuesQuerySet` from `django_stubs_ext` instead.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
Note that the `list` conversion before assignment to `all_records`
is not necessary for its usage in `realm_user_summary_table` from
a typing perspective.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
The pattern of using the same variable to apply filters
or alter the `QuerySet` in other ways might produce `QuerySet`s
with incompatible types. This behavior is not allowed by mypy.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
The returned dictionary is not at all used outside the function, so it's
sufficient to make it available only within the helper function itself.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
This ensure that the return type is compatible with the
actual type of `realm.realmdomain_set.values`.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
To explain the rationale of this change, for example, there is
`get_user_activity_summary` which accepts either a `Collection[UserActivity]`,
where `QuerySet[T]` is not strictly `Sequence[T]` because its slicing behavior
is different from the `Protocol`, making `Collection` necessary.
Similarily, we should have `Iterable[T]` instead of `List[T]` so that
`QuerySet[T]` will also be an acceptable subtype, or `Sequence[T]` when we
also expect it to be indexed.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
We were blindly adding / removing flag from UserMessages without
check if they even need to be updated.
This caused server to repeatedly update flags for messages which
already had been updated, creating a confusion for other clients
like mobile.
Fixes#22164
Added 2 new functions which check if a flag is present in a
user message or not using bit comparison.
Refactor `where_unread/starred/active_push_notification` to use
these functions.
Existing tests are enough to check if these functions work correctly.
dmypy is innately incompatible with `local_partial_types` being
`False` as it uses fined-grained incremental mode for caching.
We need to enable `local_partial_types` for mypy as well so that the two
will behave the same way.
This requires us to add additional type annotation in certain siuations
but that's fine.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
mypy daemon performs significantly better than running the regular
mypy cli tool when we type check the entire codebase multiple
times locally.
This adds running mypy daemon as an option for both
`tools/run-mypy` and `tools/lint`.
To ensure daemon messages like "Daemon started", "Daemon stopped"
won't get printed we filter any output that starts with "Daemon".
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
We’ve always been running CI on both push events and pull_request
events, which means it runs twice for commits that are pushed to a
pull request.
Filter the push events by branch name. Add the workflow_dispatch
event in case developers want to manually run CI on some other branch
that isn’t a pull request.
https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a-workflow
Signed-off-by: Anders Kaseorg <anders@zulip.com>
Resizing emoji can fail, especially for animated GIFs; in such cases,
it is useful to have the original data on hand, to be able to dissect
the failure.
This was removed in Django 4.0 except in historical migrations. We
might as well replace it everywhere.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
Our uWSGI configuration doesn’t correctly activate our virtualenv. We
should investigate that, but until we do, we need to invoke html2text
by an absolute path.
Signed-off-by: Anders Kaseorg <anders@zulip.com>