Skip to content

Commit 1a68ffa

Browse files
ref: fix some types for sentry.api (#72641)
fixes errors when BaseManager becomes typed <!-- Describe your PR here. -->
1 parent 4195f82 commit 1a68ffa

17 files changed

+75
-33
lines changed

src/sentry/api/authentication.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -243,10 +243,13 @@ def authenticate_credentials(self, userid, password, request=None):
243243
if password:
244244
return None
245245

246+
key: ApiKeyReplica | ApiKey
246247
if SiloMode.get_current_mode() == SiloMode.REGION:
247-
key = ApiKeyReplica.objects.filter(key=userid).last()
248-
if key is None:
248+
key_replica = ApiKeyReplica.objects.filter(key=userid).last()
249+
if key_replica is None:
249250
raise AuthenticationFailed("API key is not valid")
251+
else:
252+
key = key_replica
250253
else:
251254
try:
252255
key = ApiKey.objects.get_from_cache(key=userid)
@@ -452,9 +455,9 @@ def accepts_auth(self, auth: list[bytes]) -> bool:
452455
return token_str.startswith(SENTRY_ORG_AUTH_TOKEN_PREFIX)
453456

454457
def authenticate_token(self, request: Request, token_str: str) -> tuple[Any, Any]:
455-
token = None
456458
token_hashed = hash_token(token_str)
457459

460+
token: OrgAuthTokenReplica | OrgAuthToken
458461
if SiloMode.get_current_mode() == SiloMode.REGION:
459462
try:
460463
token = OrgAuthTokenReplica.objects.get(

src/sentry/api/endpoints/artifact_bundles.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -135,14 +135,14 @@ def delete(self, request: Request, project) -> Response:
135135
if bundle_id:
136136
error = None
137137

138-
project_artifact_bundles = ProjectArtifactBundle.objects.filter(
138+
project_artifact_bundles_qs = ProjectArtifactBundle.objects.filter(
139139
organization_id=project.organization_id,
140140
artifact_bundle__bundle_id=bundle_id,
141141
).select_related("artifact_bundle")
142142
# We group the bundles by their id, since we might have multiple bundles with the same bundle_id due to a
143143
# problem that was fixed in https://github.com/getsentry/sentry/pull/49836.
144144
grouped_bundles = defaultdict(list)
145-
for project_artifact_bundle in project_artifact_bundles:
145+
for project_artifact_bundle in project_artifact_bundles_qs:
146146
grouped_bundles[project_artifact_bundle.artifact_bundle].append(
147147
project_artifact_bundle
148148
)

src/sentry/api/endpoints/artifact_lookup.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ def download_file(self, download_id, project: Project):
6262
)
6363
return HttpResponse({"Too many download requests"}, status=429)
6464

65-
file = None
65+
file_m: ArtifactBundle | ReleaseFile | None = None
6666
if ty == "artifact_bundle":
67-
file = (
67+
file_m = (
6868
ArtifactBundle.objects.filter(
6969
id=ty_id,
7070
projectartifactbundle__project_id=project.id,
@@ -76,16 +76,16 @@ def download_file(self, download_id, project: Project):
7676
elif ty == "release_file":
7777
# NOTE: `ReleaseFile` does have a `project_id`, but that seems to
7878
# be always empty, so using the `organization_id` instead.
79-
file = (
79+
file_m = (
8080
ReleaseFile.objects.filter(id=ty_id, organization_id=project.organization.id)
8181
.select_related("file")
8282
.first()
8383
)
8484
metrics.incr("sourcemaps.download.release_file")
8585

86-
if file is None:
86+
if file_m is None:
8787
raise Http404
88-
file = file.file
88+
file = file_m.file
8989

9090
try:
9191
fp = file.getfile()

src/sentry/api/endpoints/group_current_release.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@ def _get_current_release(self, group, environments):
2424
"release_id", flat=True
2525
)
2626

27-
release_envs = ReleaseEnvironment.objects.filter(
27+
release_envs_qs = ReleaseEnvironment.objects.filter(
2828
release_id__in=release_projects,
2929
organization_id=group.project.organization_id,
3030
)
3131
if environments:
32-
release_envs = release_envs.filter(environment_id__in=[env.id for env in environments])
33-
release_envs = release_envs.order_by("-first_seen").values_list("release_id", flat=True)
32+
release_envs_qs = release_envs_qs.filter(
33+
environment_id__in=[env.id for env in environments]
34+
)
35+
release_envs = release_envs_qs.order_by("-first_seen").values_list("release_id", flat=True)
3436

3537
group_releases = GroupRelease.objects.filter(
3638
group_id=group.id,

src/sentry/api/endpoints/group_details.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,11 @@ def get(self, request: Request, group) -> Response:
230230
data.update({"integrationIssues": integration_issues})
231231

232232
if "sentryAppIssues" in expand:
233-
external_issues = PlatformExternalIssue.objects.filter(group_id=group.id)
233+
platform_external_issues = PlatformExternalIssue.objects.filter(group_id=group.id)
234234
sentry_app_issues = serialize(
235-
list(external_issues), request, serializer=PlatformExternalIssueSerializer()
235+
list(platform_external_issues),
236+
request,
237+
serializer=PlatformExternalIssueSerializer(),
236238
)
237239
data.update({"sentryAppIssues": sentry_app_issues})
238240

src/sentry/api/endpoints/organization_artifactbundle_assemble.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,11 @@ def post(self, request: Request, organization) -> Response:
6060
if len(projects) == 0:
6161
return Response({"error": "You need to specify at least one project"}, status=400)
6262

63-
project_ids = Project.objects.filter(
64-
organization=organization, status=ObjectStatus.ACTIVE, slug__in=projects
65-
).values_list("id", flat=True)
63+
project_ids = list(
64+
Project.objects.filter(
65+
organization=organization, status=ObjectStatus.ACTIVE, slug__in=projects
66+
).values_list("id", flat=True)
67+
)
6668
if len(project_ids) != len(projects):
6769
return Response({"error": "One or more projects are invalid"}, status=400)
6870

src/sentry/api/endpoints/organization_codeowners_associations.py

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ def get(self, request: Request, organization: Organization):
4747
)
4848
result = {}
4949
for pco in project_code_owners:
50+
assert pco.raw is not None # XXX: model field `raw` is nullable? seems wrong?
5051
associations, errors = validate_codeowners_associations(pco.raw, pco.project)
5152
result[pco.project.slug] = {"associations": associations, "errors": errors}
5253
return self.respond(result, status=status.HTTP_200_OK)

src/sentry/api/endpoints/organization_release_meta.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
from __future__ import annotations
2+
13
from collections import defaultdict
4+
from typing import TypedDict
25

36
from rest_framework.request import Request
47
from rest_framework.response import Response
@@ -15,6 +18,15 @@
1518
from sentry.models.releases.release_project import ReleaseProject
1619

1720

21+
class _ProjectDict(TypedDict):
22+
id: int
23+
slug: str | None
24+
name: str
25+
newGroups: int | None
26+
platform: str | None
27+
platforms: list[str]
28+
29+
1830
@region_silo_endpoint
1931
class OrganizationReleaseMetaEndpoint(OrganizationReleasesBaseEndpoint):
2032
publish_status = {
@@ -70,7 +82,7 @@ def get(self, request: Request, organization, version) -> Response:
7082
platforms_by_project[project_id].append(platform)
7183

7284
# This must match what is returned from the `Release` serializer
73-
projects = [
85+
projects: list[_ProjectDict] = [
7486
{
7587
"id": pr["project__id"],
7688
"slug": pr["project__slug"],

src/sentry/api/endpoints/prompts_activity.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,10 @@ def get(self, request: Request, **kwargs) -> Response:
6262
condition = Q(feature=feature, **filters)
6363
conditions = condition if conditions is None else (conditions | condition)
6464

65-
result = PromptsActivity.objects.filter(conditions, user_id=request.user.id)
66-
featuredata = {k.feature: k.data for k in result}
65+
result_qs = PromptsActivity.objects.filter(conditions, user_id=request.user.id)
66+
featuredata = {k.feature: k.data for k in result_qs}
6767
if len(features) == 1:
68-
result = result.first()
68+
result = result_qs.first()
6969
data = None if result is None else result.data
7070
return Response({"data": data, "features": featuredata})
7171
else:

src/sentry/api/helpers/teams.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def get_teams(request, organization, teams=None):
2222
# do normal teams lookup based on request params
2323
requested_teams = set(request.GET.getlist("team", []) if teams is None else teams)
2424

25-
verified_ids = set()
25+
verified_ids: set[int] = set()
2626

2727
if "myteams" in requested_teams:
2828
requested_teams.remove("myteams")

src/sentry/api/serializers/models/filechange.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
from __future__ import annotations
2+
3+
from typing import Any
4+
15
from sentry.api.serializers import Serializer, register
26
from sentry.api.serializers.models.commit import get_users_for_commits
37
from sentry.models.commit import Commit
@@ -20,7 +24,7 @@ def get_attrs(self, item_list, user):
2024
).values_list("id", "name")
2125
)
2226

23-
result = {}
27+
result: dict[int, Any] = {}
2428
for item in item_list:
2529
commit = commits_by_id[item.commit_id]
2630
result[item] = {

src/sentry/api/serializers/models/release.py

+14-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import datetime
44
from collections import defaultdict
55
from collections.abc import Mapping, Sequence
6-
from typing import Any, TypedDict, Union
6+
from typing import Any, NotRequired, TypedDict, Union
77

88
from django.contrib.auth.models import AnonymousUser
99
from django.core.cache import cache
@@ -20,6 +20,7 @@
2020
from sentry.models.release import Release, ReleaseStatus
2121
from sentry.models.releaseprojectenvironment import ReleaseProjectEnvironment
2222
from sentry.models.releases.release_project import ReleaseProject
23+
from sentry.release_health.base import ReleaseHealthOverview
2324
from sentry.services.hybrid_cloud.user.serial import serialize_generic_user
2425
from sentry.services.hybrid_cloud.user.service import user_service
2526
from sentry.utils import metrics
@@ -291,6 +292,17 @@ def get_users_for_authors(organization_id, authors, user=None) -> Mapping[str, A
291292
return results
292293

293294

295+
class _ProjectDict(TypedDict):
296+
id: int
297+
slug: str | None
298+
name: str
299+
new_groups: int | None
300+
platform: str | None
301+
platforms: list[str]
302+
health_data: NotRequired[ReleaseHealthOverview | None]
303+
has_health_data: NotRequired[bool]
304+
305+
294306
@register(Release)
295307
class ReleaseSerializer(Serializer):
296308
def __get_project_id_list(self, item_list):
@@ -491,7 +503,7 @@ def get_attrs(self, item_list, user, **kwargs):
491503
has_health_data = {}
492504

493505
for pr in project_releases:
494-
pr_rv = {
506+
pr_rv: _ProjectDict = {
495507
"id": pr["project__id"],
496508
"slug": pr["project__slug"],
497509
"name": pr["project__name"],

src/sentry/api/serializers/models/relocation.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
from collections.abc import Mapping, MutableMapping, Sequence
33
from typing import Any
44

5+
from django.db.models import QuerySet
6+
57
from sentry.api.serializers import Serializer, register
6-
from sentry.db.models.manager.base import BaseManager
78
from sentry.models.importchunk import BaseImportChunk, ControlImportChunkReplica, RegionImportChunk
89
from sentry.models.relocation import Relocation
910
from sentry.models.user import User
@@ -29,7 +30,7 @@ class RelocationMetadata:
2930
imported_org_ids: list[int]
3031

3132

32-
def get_all_imported_ids_of_model(chunks: BaseManager[BaseImportChunk]) -> list[int]:
33+
def get_all_imported_ids_of_model(chunks: QuerySet[BaseImportChunk]) -> list[int]:
3334
all_imported_ids = set()
3435
for chunk in chunks:
3536
all_imported_ids |= (

src/sentry/api/validators/project_codeowners.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from __future__ import annotations
22

3-
from collections.abc import Collection, Mapping
3+
from collections.abc import Collection, Iterable, Mapping
44
from typing import Any
55

66
from django.db.models import Subquery
@@ -24,7 +24,7 @@ def validate_association_emails(
2424

2525
def validate_association_actors(
2626
raw_items: Collection[str],
27-
associations: Collection[ExternalActor],
27+
associations: Iterable[ExternalActor],
2828
) -> list[str]:
2929
raw_items_set = {str(item) for item in raw_items}
3030
# associations are ExternalActor objects

src/sentry/models/avatars/sentry_app_avatar.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
from collections import defaultdict
4+
from collections.abc import Iterable
45
from enum import Enum
56
from typing import TYPE_CHECKING, ClassVar
67

@@ -25,7 +26,9 @@ def get_choices(cls):
2526

2627

2728
class SentryAppAvatarManager(BaseManager["SentryAppAvatar"]):
28-
def get_by_apps_as_dict(self, sentry_apps: list[SentryApp]):
29+
def get_by_apps_as_dict(
30+
self, sentry_apps: Iterable[SentryApp]
31+
) -> dict[int, set[SentryAppAvatar]]:
2932
"""
3033
Returns a dict mapping sentry_app_id (key) to List[SentryAppAvatar] (value)
3134
"""

src/sentry/models/orgauthtoken.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ def get_org_auth_token_id_from_auth(auth: object) -> int | None:
149149
return None
150150

151151

152-
def update_org_auth_token_last_used(auth: object, project_ids: list[int]):
152+
def update_org_auth_token_last_used(auth: object, project_ids: list[int]) -> None:
153153
org_auth_token_id = get_org_auth_token_id_from_auth(auth)
154154
organization_id = getattr(auth, "organization_id", None)
155155
if org_auth_token_id is None or organization_id is None:

src/sentry/models/release.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ class Release(Model):
245245
# where they are "specialized" for a specific project. The goal is to
246246
# later split up releases by project again. This is for instance used
247247
# by the org release listing.
248-
_for_project_id = None
248+
_for_project_id: int | None = None
249249
# the user agent that set the release
250250
user_agent = models.TextField(null=True)
251251

0 commit comments

Comments
 (0)