mirror of
https://github.com/zulip/zulip.git
synced 2025-10-23 04:52:12 +00:00
ruff: Fix UP007 Use X | Y
for type annotations.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
committed by
Tim Abbott
parent
e08a24e47f
commit
531b34cb4c
@@ -2,7 +2,7 @@ import logging
|
||||
import time
|
||||
from collections import OrderedDict, defaultdict
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Callable, Optional, Sequence, Union
|
||||
from typing import Callable, Sequence, Union
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import connection, models
|
||||
@@ -55,7 +55,7 @@ class CountStat:
|
||||
property: str,
|
||||
data_collector: "DataCollector",
|
||||
frequency: str,
|
||||
interval: Optional[timedelta] = None,
|
||||
interval: timedelta | None = None,
|
||||
) -> None:
|
||||
self.property = property
|
||||
self.data_collector = data_collector
|
||||
@@ -72,7 +72,7 @@ class CountStat:
|
||||
def __repr__(self) -> str:
|
||||
return f"<CountStat: {self.property}>"
|
||||
|
||||
def last_successful_fill(self) -> Optional[datetime]:
|
||||
def last_successful_fill(self) -> datetime | None:
|
||||
fillstate = FillState.objects.filter(property=self.property).first()
|
||||
if fillstate is None:
|
||||
return None
|
||||
@@ -92,7 +92,7 @@ class DependentCountStat(CountStat):
|
||||
property: str,
|
||||
data_collector: "DataCollector",
|
||||
frequency: str,
|
||||
interval: Optional[timedelta] = None,
|
||||
interval: timedelta | None = None,
|
||||
dependencies: Sequence[str] = [],
|
||||
) -> None:
|
||||
CountStat.__init__(self, property, data_collector, frequency, interval=interval)
|
||||
@@ -103,7 +103,7 @@ class DataCollector:
|
||||
def __init__(
|
||||
self,
|
||||
output_table: type[BaseCount],
|
||||
pull_function: Optional[Callable[[str, datetime, datetime, Optional[Realm]], int]],
|
||||
pull_function: Callable[[str, datetime, datetime, Realm | None], int] | None,
|
||||
) -> None:
|
||||
self.output_table = output_table
|
||||
self.pull_function = pull_function
|
||||
@@ -115,9 +115,7 @@ class DataCollector:
|
||||
## CountStat-level operations ##
|
||||
|
||||
|
||||
def process_count_stat(
|
||||
stat: CountStat, fill_to_time: datetime, realm: Optional[Realm] = None
|
||||
) -> None:
|
||||
def process_count_stat(stat: CountStat, fill_to_time: datetime, realm: Realm | None = None) -> None:
|
||||
# TODO: The realm argument is not yet supported, in that we don't
|
||||
# have a solution for how to update FillState if it is passed. It
|
||||
# exists solely as partial plumbing for when we do fully implement
|
||||
@@ -180,7 +178,7 @@ def do_update_fill_state(fill_state: FillState, end_time: datetime, state: int)
|
||||
# We assume end_time is valid (e.g. is on a day or hour boundary as appropriate)
|
||||
# and is time-zone-aware. It is the caller's responsibility to enforce this!
|
||||
def do_fill_count_stat_at_hour(
|
||||
stat: CountStat, end_time: datetime, realm: Optional[Realm] = None
|
||||
stat: CountStat, end_time: datetime, realm: Realm | None = None
|
||||
) -> None:
|
||||
start_time = end_time - stat.interval
|
||||
if not isinstance(stat, LoggingCountStat):
|
||||
@@ -209,7 +207,7 @@ def do_delete_counts_at_hour(stat: CountStat, end_time: datetime) -> None:
|
||||
|
||||
|
||||
def do_aggregate_to_summary_table(
|
||||
stat: CountStat, end_time: datetime, realm: Optional[Realm] = None
|
||||
stat: CountStat, end_time: datetime, realm: Realm | None = None
|
||||
) -> None:
|
||||
cursor = connection.cursor()
|
||||
|
||||
@@ -303,7 +301,7 @@ def do_aggregate_to_summary_table(
|
||||
def do_increment_logging_stat(
|
||||
model_object_for_bucket: Union[Realm, UserProfile, Stream, "RemoteRealm", "RemoteZulipServer"],
|
||||
stat: CountStat,
|
||||
subgroup: Optional[Union[str, int, bool]],
|
||||
subgroup: str | int | bool | None,
|
||||
event_time: datetime,
|
||||
increment: int = 1,
|
||||
) -> None:
|
||||
@@ -311,7 +309,7 @@ def do_increment_logging_stat(
|
||||
return
|
||||
|
||||
table = stat.data_collector.output_table
|
||||
id_args: dict[str, Union[int, None]] = {}
|
||||
id_args: dict[str, int | None] = {}
|
||||
conflict_args: list[str] = []
|
||||
if table == RealmCount:
|
||||
assert isinstance(model_object_for_bucket, Realm)
|
||||
@@ -433,7 +431,7 @@ def do_pull_by_sql_query(
|
||||
start_time: datetime,
|
||||
end_time: datetime,
|
||||
query: QueryFn,
|
||||
group_by: Optional[tuple[type[models.Model], str]],
|
||||
group_by: tuple[type[models.Model], str] | None,
|
||||
) -> int:
|
||||
if group_by is None:
|
||||
subgroup: Composable = SQL("NULL")
|
||||
@@ -469,10 +467,10 @@ def do_pull_by_sql_query(
|
||||
def sql_data_collector(
|
||||
output_table: type[BaseCount],
|
||||
query: QueryFn,
|
||||
group_by: Optional[tuple[type[models.Model], str]],
|
||||
group_by: tuple[type[models.Model], str] | None,
|
||||
) -> DataCollector:
|
||||
def pull_function(
|
||||
property: str, start_time: datetime, end_time: datetime, realm: Optional[Realm] = None
|
||||
property: str, start_time: datetime, end_time: datetime, realm: Realm | None = None
|
||||
) -> int:
|
||||
# The pull function type needs to accept a Realm argument
|
||||
# because the 'minutes_active::day' CountStat uses
|
||||
@@ -485,7 +483,7 @@ def sql_data_collector(
|
||||
return DataCollector(output_table, pull_function)
|
||||
|
||||
|
||||
def count_upload_space_used_by_realm_query(realm: Optional[Realm]) -> QueryFn:
|
||||
def count_upload_space_used_by_realm_query(realm: Realm | None) -> QueryFn:
|
||||
if realm is None:
|
||||
realm_clause: Composable = SQL("")
|
||||
else:
|
||||
@@ -520,7 +518,7 @@ def count_upload_space_used_by_realm_query(realm: Optional[Realm]) -> QueryFn:
|
||||
|
||||
|
||||
def do_pull_minutes_active(
|
||||
property: str, start_time: datetime, end_time: datetime, realm: Optional[Realm] = None
|
||||
property: str, start_time: datetime, end_time: datetime, realm: Realm | None = None
|
||||
) -> int:
|
||||
user_activity_intervals = (
|
||||
UserActivityInterval.objects.filter(
|
||||
@@ -555,7 +553,7 @@ def do_pull_minutes_active(
|
||||
return len(rows)
|
||||
|
||||
|
||||
def count_message_by_user_query(realm: Optional[Realm]) -> QueryFn:
|
||||
def count_message_by_user_query(realm: Realm | None) -> QueryFn:
|
||||
if realm is None:
|
||||
realm_clause: Composable = SQL("")
|
||||
else:
|
||||
@@ -588,7 +586,7 @@ def count_message_by_user_query(realm: Optional[Realm]) -> QueryFn:
|
||||
|
||||
|
||||
# Note: ignores the group_by / group_by_clause.
|
||||
def count_message_type_by_user_query(realm: Optional[Realm]) -> QueryFn:
|
||||
def count_message_type_by_user_query(realm: Realm | None) -> QueryFn:
|
||||
if realm is None:
|
||||
realm_clause: Composable = SQL("")
|
||||
else:
|
||||
@@ -643,7 +641,7 @@ def count_message_type_by_user_query(realm: Optional[Realm]) -> QueryFn:
|
||||
# use this also subgroup on UserProfile.is_bot. If in the future there is a
|
||||
# stat that counts messages by stream and doesn't need the UserProfile
|
||||
# table, consider writing a new query for efficiency.
|
||||
def count_message_by_stream_query(realm: Optional[Realm]) -> QueryFn:
|
||||
def count_message_by_stream_query(realm: Realm | None) -> QueryFn:
|
||||
if realm is None:
|
||||
realm_clause: Composable = SQL("")
|
||||
else:
|
||||
@@ -683,7 +681,7 @@ def count_message_by_stream_query(realm: Optional[Realm]) -> QueryFn:
|
||||
# same event_time and event_type in [RealmAuditLog.USER_CREATED,
|
||||
# USER_DEACTIVATED, etc]. In particular, it's important to ensure
|
||||
# that migrations don't cause that to happen.
|
||||
def check_realmauditlog_by_user_query(realm: Optional[Realm]) -> QueryFn:
|
||||
def check_realmauditlog_by_user_query(realm: Realm | None) -> QueryFn:
|
||||
if realm is None:
|
||||
realm_clause: Composable = SQL("")
|
||||
else:
|
||||
@@ -722,7 +720,7 @@ def check_realmauditlog_by_user_query(realm: Optional[Realm]) -> QueryFn:
|
||||
)
|
||||
|
||||
|
||||
def check_useractivityinterval_by_user_query(realm: Optional[Realm]) -> QueryFn:
|
||||
def check_useractivityinterval_by_user_query(realm: Realm | None) -> QueryFn:
|
||||
if realm is None:
|
||||
realm_clause: Composable = SQL("")
|
||||
else:
|
||||
@@ -746,7 +744,7 @@ def check_useractivityinterval_by_user_query(realm: Optional[Realm]) -> QueryFn:
|
||||
).format(**kwargs, realm_clause=realm_clause)
|
||||
|
||||
|
||||
def count_realm_active_humans_query(realm: Optional[Realm]) -> QueryFn:
|
||||
def count_realm_active_humans_query(realm: Realm | None) -> QueryFn:
|
||||
if realm is None:
|
||||
realm_clause: Composable = SQL("")
|
||||
else:
|
||||
@@ -817,7 +815,7 @@ count_stream_by_realm_query = lambda kwargs: SQL(
|
||||
).format(**kwargs)
|
||||
|
||||
|
||||
def get_count_stats(realm: Optional[Realm] = None) -> dict[str, CountStat]:
|
||||
def get_count_stats(realm: Realm | None = None) -> dict[str, CountStat]:
|
||||
## CountStat declarations ##
|
||||
|
||||
count_stats_ = [
|
||||
|
@@ -1,5 +1,4 @@
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Optional
|
||||
|
||||
from analytics.lib.counts import CountStat
|
||||
from zerver.lib.timestamp import floor_to_day, floor_to_hour, verify_UTC
|
||||
@@ -10,7 +9,7 @@ from zerver.lib.timestamp import floor_to_day, floor_to_hour, verify_UTC
|
||||
# So informally, time_range(Sep 20, Sep 22, day, None) returns [Sep 20, Sep 21, Sep 22],
|
||||
# and time_range(Sep 20, Sep 22, day, 5) returns [Sep 18, Sep 19, Sep 20, Sep 21, Sep 22]
|
||||
def time_range(
|
||||
start: datetime, end: datetime, frequency: str, min_length: Optional[int]
|
||||
start: datetime, end: datetime, frequency: str, min_length: int | None
|
||||
) -> list[datetime]:
|
||||
verify_UTC(start)
|
||||
verify_UTC(end)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
from datetime import timedelta
|
||||
from typing import Any, Mapping, Union
|
||||
from typing import Any, Mapping
|
||||
|
||||
from django.core.files.uploadedfile import UploadedFile
|
||||
from django.utils.timezone import now as timezone_now
|
||||
@@ -147,7 +147,7 @@ class Command(ZulipBaseCommand):
|
||||
with open(IMAGE_FILE_PATH, "rb") as fp:
|
||||
upload_message_attachment_from_request(UploadedFile(fp), shylock)
|
||||
|
||||
FixtureData: TypeAlias = Mapping[Union[str, int, None], list[int]]
|
||||
FixtureData: TypeAlias = Mapping[str | int | None, list[int]]
|
||||
|
||||
def insert_fixture_data(
|
||||
stat: CountStat,
|
||||
@@ -330,7 +330,7 @@ class Command(ZulipBaseCommand):
|
||||
"true": self.generate_fixture_data(stat, 20, 2, 3, 0.2, 3),
|
||||
}
|
||||
insert_fixture_data(stat, realm_data, RealmCount)
|
||||
stream_data: Mapping[Union[int, str, None], list[int]] = {
|
||||
stream_data: Mapping[int | str | None, list[int]] = {
|
||||
"false": self.generate_fixture_data(stat, 10, 7, 5, 0.6, 4),
|
||||
"true": self.generate_fixture_data(stat, 5, 3, 2, 0.4, 2),
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
from contextlib import AbstractContextManager, ExitStack, contextmanager
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Any, Iterator, Optional
|
||||
from typing import Any, Iterator
|
||||
from unittest import mock
|
||||
|
||||
import time_machine
|
||||
@@ -111,7 +111,7 @@ class AnalyticsTestCase(ZulipTestCase):
|
||||
# used to generate unique names in self.create_*
|
||||
self.name_counter = 100
|
||||
# used as defaults in self.assert_table_count
|
||||
self.current_property: Optional[str] = None
|
||||
self.current_property: str | None = None
|
||||
|
||||
# Delete RemoteRealm registrations to have a clean slate - the relevant
|
||||
# tests want to construct this from scratch.
|
||||
@@ -226,10 +226,10 @@ class AnalyticsTestCase(ZulipTestCase):
|
||||
self,
|
||||
table: type[BaseCount],
|
||||
value: int,
|
||||
property: Optional[str] = None,
|
||||
subgroup: Optional[str] = None,
|
||||
property: str | None = None,
|
||||
subgroup: str | None = None,
|
||||
end_time: datetime = TIME_ZERO,
|
||||
realm: Optional[Realm] = None,
|
||||
realm: Realm | None = None,
|
||||
**kwargs: models.Model,
|
||||
) -> None:
|
||||
if property is None:
|
||||
@@ -1812,7 +1812,7 @@ class TestActiveUsersAudit(AnalyticsTestCase):
|
||||
self.current_property = self.stat.property
|
||||
|
||||
def add_event(
|
||||
self, event_type: int, days_offset: float, user: Optional[UserProfile] = None
|
||||
self, event_type: int, days_offset: float, user: UserProfile | None = None
|
||||
) -> None:
|
||||
hours_offset = int(24 * days_offset)
|
||||
if user is None:
|
||||
@@ -1984,7 +1984,7 @@ class TestRealmActiveHumans(AnalyticsTestCase):
|
||||
self.stat = COUNT_STATS["realm_active_humans::day"]
|
||||
self.current_property = self.stat.property
|
||||
|
||||
def mark_15day_active(self, user: UserProfile, end_time: Optional[datetime] = None) -> None:
|
||||
def mark_15day_active(self, user: UserProfile, end_time: datetime | None = None) -> None:
|
||||
if end_time is None:
|
||||
end_time = self.TIME_ZERO
|
||||
UserCount.objects.create(
|
||||
|
@@ -1,5 +1,4 @@
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Optional
|
||||
|
||||
from django.utils.timezone import now as timezone_now
|
||||
from typing_extensions import override
|
||||
@@ -88,7 +87,7 @@ class TestGetChartData(ZulipTestCase):
|
||||
return [0, 0, i, 0]
|
||||
|
||||
def insert_data(
|
||||
self, stat: CountStat, realm_subgroups: list[Optional[str]], user_subgroups: list[str]
|
||||
self, stat: CountStat, realm_subgroups: list[str | None], user_subgroups: list[str]
|
||||
) -> None:
|
||||
if stat.frequency == CountStat.HOUR:
|
||||
insert_time = self.end_times_hour[2]
|
||||
|
@@ -1,5 +1,3 @@
|
||||
from typing import Union
|
||||
|
||||
from django.conf import settings
|
||||
from django.conf.urls import include
|
||||
from django.urls import path
|
||||
@@ -16,7 +14,7 @@ from analytics.views.stats import (
|
||||
)
|
||||
from zerver.lib.rest import rest_path
|
||||
|
||||
i18n_urlpatterns: list[Union[URLPattern, URLResolver]] = [
|
||||
i18n_urlpatterns: list[URLPattern | URLResolver] = [
|
||||
# Server admin (user_profile.is_staff) visible stats pages
|
||||
path("stats/realm/<realm_str>/", stats_for_realm),
|
||||
path("stats/installation", stats_for_installation),
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import logging
|
||||
from collections import defaultdict
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Any, Optional, TypeVar, Union, cast
|
||||
from typing import Any, Optional, TypeVar, cast
|
||||
|
||||
from django.conf import settings
|
||||
from django.db.models import QuerySet
|
||||
@@ -52,9 +52,9 @@ def is_analytics_ready(realm: Realm) -> bool:
|
||||
def render_stats(
|
||||
request: HttpRequest,
|
||||
data_url_suffix: str,
|
||||
realm: Optional[Realm],
|
||||
realm: Realm | None,
|
||||
*,
|
||||
title: Optional[str] = None,
|
||||
title: str | None = None,
|
||||
analytics_ready: bool = True,
|
||||
) -> HttpResponse:
|
||||
assert request.user.is_authenticated
|
||||
@@ -246,25 +246,25 @@ def get_chart_data(
|
||||
request: HttpRequest,
|
||||
user_profile: UserProfile,
|
||||
chart_name: str = REQ(),
|
||||
min_length: Optional[int] = REQ(converter=to_non_negative_int, default=None),
|
||||
start: Optional[datetime] = REQ(converter=to_utc_datetime, default=None),
|
||||
end: Optional[datetime] = REQ(converter=to_utc_datetime, default=None),
|
||||
min_length: int | None = REQ(converter=to_non_negative_int, default=None),
|
||||
start: datetime | None = REQ(converter=to_utc_datetime, default=None),
|
||||
end: datetime | None = REQ(converter=to_utc_datetime, default=None),
|
||||
# These last several parameters are only used by functions
|
||||
# wrapping get_chart_data; the callers are responsible for
|
||||
# parsing/validation/authorization for them.
|
||||
realm: Optional[Realm] = None,
|
||||
realm: Realm | None = None,
|
||||
for_installation: bool = False,
|
||||
remote: bool = False,
|
||||
remote_realm_id: Optional[int] = None,
|
||||
remote_realm_id: int | None = None,
|
||||
server: Optional["RemoteZulipServer"] = None,
|
||||
stream: Optional[Stream] = None,
|
||||
stream: Stream | None = None,
|
||||
) -> HttpResponse:
|
||||
TableType: TypeAlias = Union[
|
||||
type["RemoteInstallationCount"],
|
||||
type[InstallationCount],
|
||||
type["RemoteRealmCount"],
|
||||
type[RealmCount],
|
||||
]
|
||||
TableType: TypeAlias = (
|
||||
type["RemoteInstallationCount"]
|
||||
| type[InstallationCount]
|
||||
| type["RemoteRealmCount"]
|
||||
| type[RealmCount]
|
||||
)
|
||||
if for_installation:
|
||||
if remote:
|
||||
assert settings.ZILENCER_ENABLED
|
||||
@@ -281,9 +281,9 @@ def get_chart_data(
|
||||
else:
|
||||
aggregate_table = RealmCount
|
||||
|
||||
tables: Union[
|
||||
tuple[TableType], tuple[TableType, type[UserCount]], tuple[TableType, type[StreamCount]]
|
||||
]
|
||||
tables: (
|
||||
tuple[TableType] | tuple[TableType, type[UserCount]] | tuple[TableType, type[StreamCount]]
|
||||
)
|
||||
|
||||
if chart_name == "number_of_humans":
|
||||
stats = [
|
||||
@@ -292,7 +292,7 @@ def get_chart_data(
|
||||
COUNT_STATS["active_users_audit:is_bot:day"],
|
||||
]
|
||||
tables = (aggregate_table,)
|
||||
subgroup_to_label: dict[CountStat, dict[Optional[str], str]] = {
|
||||
subgroup_to_label: dict[CountStat, dict[str | None, str]] = {
|
||||
stats[0]: {None: "_1day"},
|
||||
stats[1]: {None: "_15day"},
|
||||
stats[2]: {"false": "all_time"},
|
||||
@@ -372,7 +372,7 @@ def get_chart_data(
|
||||
assert server is not None
|
||||
assert aggregate_table is RemoteInstallationCount or aggregate_table is RemoteRealmCount
|
||||
aggregate_table_remote = cast(
|
||||
Union[type[RemoteInstallationCount], type[RemoteRealmCount]], aggregate_table
|
||||
type[RemoteInstallationCount] | type[RemoteRealmCount], aggregate_table
|
||||
) # https://stackoverflow.com/questions/68540528/mypy-assertions-on-the-types-of-types
|
||||
if not aggregate_table_remote.objects.filter(server=server).exists():
|
||||
raise JsonableError(
|
||||
@@ -552,7 +552,7 @@ def get_time_series_by_subgroup(
|
||||
table: type[BaseCount],
|
||||
key_id: int,
|
||||
end_times: list[datetime],
|
||||
subgroup_to_label: dict[Optional[str], str],
|
||||
subgroup_to_label: dict[str | None, str],
|
||||
include_empty_subgroups: bool,
|
||||
) -> dict[str, list[int]]:
|
||||
queryset = (
|
||||
@@ -560,7 +560,7 @@ def get_time_series_by_subgroup(
|
||||
.filter(property=stat.property)
|
||||
.values_list("subgroup", "end_time", "value")
|
||||
)
|
||||
value_dicts: dict[Optional[str], dict[datetime, int]] = defaultdict(lambda: defaultdict(int))
|
||||
value_dicts: dict[str | None, dict[datetime, int]] = defaultdict(lambda: defaultdict(int))
|
||||
for subgroup, end_time, value in queryset:
|
||||
value_dicts[subgroup][end_time] = value
|
||||
value_arrays = {}
|
||||
|
Reference in New Issue
Block a user