Skip to content

django-stubs: Fix Promise related typing errors. #22665

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

Merged
merged 2 commits into from
Aug 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions zerver/actions/message_edit.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import datetime
from typing import Any, Dict, Iterable, List, Optional, Set, TypedDict
from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Set, TypedDict

from django.conf import settings
from django.db import transaction
Expand Down Expand Up @@ -66,6 +66,9 @@
)
from zerver.tornado.django_api import send_event

if TYPE_CHECKING:
from django.utils.functional import _StrPromise as StrPromise


def subscriber_info(user_id: int) -> Dict[str, Any]:
return {"id": user_id, "flags": ["read"]}
Expand Down Expand Up @@ -198,10 +201,10 @@ def send_message_moved_breadcrumbs(
user_profile: UserProfile,
old_stream: Stream,
old_topic: str,
old_thread_notification_string: Optional[str],
old_thread_notification_string: Optional["StrPromise"],
new_stream: Stream,
new_topic: Optional[str],
new_thread_notification_string: Optional[str],
new_thread_notification_string: Optional["StrPromise"],
changed_messages_count: int,
) -> None:
# Since moving content between streams is highly disruptive,
Expand Down
10 changes: 5 additions & 5 deletions zerver/actions/streams.py
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,7 @@ def send_change_stream_permission_notification(
new_policy=new_policy_name,
)
internal_send_stream_message(
sender, stream, Realm.STREAM_EVENTS_NOTIFICATION_TOPIC, notification_string
sender, stream, str(Realm.STREAM_EVENTS_NOTIFICATION_TOPIC), notification_string
)


Expand Down Expand Up @@ -1030,7 +1030,7 @@ def send_change_stream_post_policy_notification(
new_policy=Stream.POST_POLICIES[new_post_policy],
)
internal_send_stream_message(
sender, stream, Realm.STREAM_EVENTS_NOTIFICATION_TOPIC, notification_string
sender, stream, str(Realm.STREAM_EVENTS_NOTIFICATION_TOPIC), notification_string
)


Expand Down Expand Up @@ -1153,7 +1153,7 @@ def do_rename_stream(stream: Stream, new_name: str, user_profile: UserProfile) -
internal_send_stream_message(
sender,
stream,
Realm.STREAM_EVENTS_NOTIFICATION_TOPIC,
str(Realm.STREAM_EVENTS_NOTIFICATION_TOPIC),
_("{user_name} renamed stream {old_stream_name} to {new_stream_name}.").format(
user_name=silent_mention_syntax_for_user(user_profile),
old_stream_name=f"**{old_name}**",
Expand Down Expand Up @@ -1190,7 +1190,7 @@ def send_change_stream_description_notification(
)

internal_send_stream_message(
sender, stream, Realm.STREAM_EVENTS_NOTIFICATION_TOPIC, notification_string
sender, stream, str(Realm.STREAM_EVENTS_NOTIFICATION_TOPIC), notification_string
)


Expand Down Expand Up @@ -1276,7 +1276,7 @@ def send_change_stream_message_retention_days_notification(
summary_line=summary_line,
)
internal_send_stream_message(
sender, stream, Realm.STREAM_EVENTS_NOTIFICATION_TOPIC, notification_string
sender, stream, str(Realm.STREAM_EVENTS_NOTIFICATION_TOPIC), notification_string
)


Expand Down
4 changes: 2 additions & 2 deletions zerver/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def clean_password(self) -> str:
if self.fields["password"].required and not check_password_strength(password):
# The frontend code tries to stop the user from submitting the form with a weak password,
# but if the user bypasses that protection, this error code path will run.
raise ValidationError(PASSWORD_TOO_WEAK_ERROR)
raise ValidationError(str(PASSWORD_TOO_WEAK_ERROR))

return password

Expand Down Expand Up @@ -275,7 +275,7 @@ def clean_new_password1(self) -> str:
if not check_password_strength(new_password):
# The frontend code tries to stop the user from submitting the form with a weak password,
# but if the user bypasses that protection, this error code path will run.
raise ValidationError(PASSWORD_TOO_WEAK_ERROR)
raise ValidationError(str(PASSWORD_TOO_WEAK_ERROR))

return new_password

Expand Down
10 changes: 6 additions & 4 deletions zerver/lib/hotspots.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
# See https://zulip.readthedocs.io/en/latest/subsystems/hotspots.html
# for documentation on this subsystem.
from typing import Dict, List
from typing import TYPE_CHECKING, Dict, List

from django.conf import settings
from django.utils.functional import Promise
from django.utils.translation import gettext_lazy

from zerver.models import UserHotspot, UserProfile

INTRO_HOTSPOTS: Dict[str, Dict[str, Promise]] = {
if TYPE_CHECKING:
from django.utils.functional import _StrPromise as StrPromise

INTRO_HOTSPOTS: Dict[str, Dict[str, "StrPromise"]] = {
"intro_streams": {
"title": gettext_lazy("Catch up on a stream"),
"description": gettext_lazy(
Expand Down Expand Up @@ -42,7 +44,7 @@
# We would most likely implement new hotspots in the future that aren't
# a part of the initial tutorial. To that end, classifying them into
# categories which are aggregated in ALL_HOTSPOTS, seems like a good start.
ALL_HOTSPOTS: Dict[str, Dict[str, Promise]] = {
ALL_HOTSPOTS: Dict[str, Dict[str, "StrPromise"]] = {
**INTRO_HOTSPOTS,
}

Expand Down
8 changes: 5 additions & 3 deletions zerver/lib/integrations.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import os
from dataclasses import dataclass, field
from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Sequence, Tuple

from django.contrib.staticfiles.storage import staticfiles_storage
from django.urls import URLResolver, path
from django.utils.functional import Promise
from django.utils.module_loading import import_string
from django.utils.translation import gettext_lazy

from zerver.lib.storage import static_path

if TYPE_CHECKING:
from django.utils.functional import _StrPromise as StrPromise

"""This module declares all of the (documented) integrations available
in the Zulip server. The Integration class is used as part of
generating the documentation on the /integrations page, while the
Expand All @@ -31,7 +33,7 @@

OptionValidator = Callable[[str, str], Optional[str]]

CATEGORIES: Dict[str, Promise] = {
CATEGORIES: Dict[str, "StrPromise"] = {
"meta-integration": gettext_lazy("Integration frameworks"),
"continuous-integration": gettext_lazy("Continuous integration"),
"customer-support": gettext_lazy("Customer support"),
Expand Down
25 changes: 20 additions & 5 deletions zerver/lib/types.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
import datetime
from dataclasses import dataclass
from typing import Any, Callable, Dict, List, Optional, Tuple, TypedDict, TypeVar, Union
from typing import (
TYPE_CHECKING,
Any,
Callable,
Dict,
List,
Optional,
Tuple,
TypedDict,
TypeVar,
Union,
)

from django.utils.functional import Promise
from typing_extensions import NotRequired

if TYPE_CHECKING:
from django.utils.functional import _StrPromise as StrPromise

# See zerver/lib/validator.py for more details of Validators,
# including many examples
ResultT = TypeVar("ResultT")
Expand Down Expand Up @@ -37,9 +50,11 @@ class ProfileDataElementUpdateDict(TypedDict):

ProfileData = List[ProfileDataElement]

FieldElement = Tuple[int, Promise, Validator[ProfileDataElementValue], Callable[[Any], Any], str]
ExtendedFieldElement = Tuple[int, Promise, ExtendedValidator, Callable[[Any], Any], str]
UserFieldElement = Tuple[int, Promise, RealmUserValidator, Callable[[Any], Any], str]
FieldElement = Tuple[
int, "StrPromise", Validator[ProfileDataElementValue], Callable[[Any], Any], str
]
ExtendedFieldElement = Tuple[int, "StrPromise", ExtendedValidator, Callable[[Any], Any], str]
UserFieldElement = Tuple[int, "StrPromise", RealmUserValidator, Callable[[Any], Any], str]

ProfileFieldData = Dict[str, Union[Dict[str, str], str]]

Expand Down
12 changes: 7 additions & 5 deletions zerver/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
from django.db.models.query import QuerySet
from django.db.models.signals import post_delete, post_save, pre_delete
from django.db.models.sql.compiler import SQLCompiler
from django.utils.functional import Promise
from django.utils.timezone import now as timezone_now
from django.utils.translation import gettext as _
from django.utils.translation import gettext_lazy
Expand Down Expand Up @@ -120,6 +119,7 @@
# We use ModelBackend only for typing. Importing it otherwise causes circular dependency.
from django.contrib.auth.backends import ModelBackend
from django.db.models.query import _QuerySet as ValuesQuerySet
from django.utils.functional import _StrPromise as StrPromise


class EmojiInfo(TypedDict):
Expand Down Expand Up @@ -907,7 +907,7 @@ def currently_used_upload_space_bytes(realm) -> int:

def ensure_not_on_limited_plan(self) -> None:
if self.plan_type == Realm.PLAN_TYPE_LIMITED:
raise JsonableError(self.UPGRADE_TEXT_STANDARD)
raise JsonableError(str(self.UPGRADE_TEXT_STANDARD))

@property
def subdomain(self) -> str:
Expand Down Expand Up @@ -1872,7 +1872,7 @@ class UserProfile(AbstractBaseUser, PermissionsMixin, UserBaseSettings):
}

def get_role_name(self) -> str:
return self.ROLE_ID_TO_NAME_MAP[self.role]
return str(self.ROLE_ID_TO_NAME_MAP[self.role])

def profile_data(self) -> ProfileData:
values = CustomProfileFieldValue.objects.filter(user_profile=self)
Expand Down Expand Up @@ -2452,7 +2452,7 @@ class Stream(models.Model):

# Who in the organization has permission to send messages to this stream.
stream_post_policy: int = models.PositiveSmallIntegerField(default=STREAM_POST_POLICY_EVERYONE)
POST_POLICIES: Dict[int, str] = {
POST_POLICIES: Dict[int, "StrPromise"] = {
# These strings should match the strings in the
# stream_post_policy_values object in stream_data.js.
STREAM_POST_POLICY_EVERYONE: gettext_lazy("All stream members can post"),
Expand Down Expand Up @@ -4505,7 +4505,9 @@ class CustomProfileField(models.Model):
FIELD_CONVERTERS: Dict[int, Callable[[Any], Any]] = {
item[0]: item[3] for item in ALL_FIELD_TYPES
}
FIELD_TYPE_CHOICES: List[Tuple[int, Promise]] = [(item[0], item[1]) for item in ALL_FIELD_TYPES]
FIELD_TYPE_CHOICES: List[Tuple[int, "StrPromise"]] = [
(item[0], item[1]) for item in ALL_FIELD_TYPES
]

field_type: int = models.PositiveSmallIntegerField(
choices=FIELD_TYPE_CHOICES,
Expand Down
2 changes: 1 addition & 1 deletion zerver/views/streams.py
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,7 @@ def send_messages_for_new_subscribers(
internal_prep_stream_message(
sender=sender,
stream=stream,
topic=Realm.STREAM_EVENTS_NOTIFICATION_TOPIC,
topic=str(Realm.STREAM_EVENTS_NOTIFICATION_TOPIC),
content=_(
"**{policy}** stream created by {user_name}. **Description:**"
).format(
Expand Down
2 changes: 1 addition & 1 deletion zerver/views/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,7 @@ def create_user_backend(
pass

if not check_password_strength(password):
raise JsonableError(PASSWORD_TOO_WEAK_ERROR)
raise JsonableError(str(PASSWORD_TOO_WEAK_ERROR))

target_user = do_create_user(
email,
Expand Down