1
1
import logging
2
+ from collections .abc import Sequence
2
3
from dataclasses import dataclass , field
3
- from typing import Any
4
+ from typing import Annotated , Any , TypedDict
4
5
from urllib .parse import urlencode , urlparse , urlunparse
5
6
from uuid import uuid4
6
7
17
18
logger = logging .getLogger ("sentry.sentry_apps.external_requests" )
18
19
19
20
21
+ class SelectRequesterResult (TypedDict , total = False ):
22
+ # Each contained Sequence of strings is of length 2 i.e ["label", "value"]
23
+ choices : Sequence [Annotated [Sequence [str ], 2 ]]
24
+ defaultValue : str
25
+
26
+
20
27
@dataclass
21
28
class SelectRequester :
22
29
"""
@@ -34,7 +41,7 @@ class SelectRequester:
34
41
query : str | None = field (default = None )
35
42
dependent_data : str | None = field (default = None )
36
43
37
- def run (self ) -> dict [ str , Any ] :
44
+ def run (self ) -> SelectRequesterResult :
38
45
response : list [dict [str , str ]] = []
39
46
try :
40
47
url = self ._build_url ()
@@ -71,7 +78,9 @@ def run(self) -> dict[str, Any]:
71
78
message = "select-requester.request-failed"
72
79
73
80
logger .info (message , extra = extra )
74
- raise APIError from e
81
+ raise APIError (
82
+ f"Something went wrong while getting SelectFields from { self .sentry_app .slug } "
83
+ ) from e
75
84
76
85
if not self ._validate_response (response ):
77
86
logger .info (
@@ -85,7 +94,7 @@ def run(self) -> dict[str, Any]:
85
94
},
86
95
)
87
96
raise ValidationError (
88
- f"Invalid response format for SelectField in { self .sentry_app } from uri: { self .uri } "
97
+ f"Invalid response format for SelectField in { self .sentry_app . slug } from uri: { self .uri } "
89
98
)
90
99
return self ._format_response (response )
91
100
@@ -107,14 +116,16 @@ def _build_url(self) -> str:
107
116
urlparts [4 ] = urlencode (query )
108
117
return str (urlunparse (urlparts ))
109
118
110
- def _validate_response (self , resp : list [dict [str , Any ]]) -> bool :
119
+ # response format must be:
120
+ # https://docs.sentry.io/organization/integrations/integration-platform/ui-components/formfield/#uri-response-format
121
+ def _validate_response (self , resp : Sequence [dict [str , Any ]]) -> bool :
111
122
return validate (instance = resp , schema_type = "select" )
112
123
113
- def _format_response (self , resp : list [dict [str , Any ]]) -> dict [ str , Any ] :
124
+ def _format_response (self , resp : Sequence [dict [str , Any ]]) -> SelectRequesterResult :
114
125
# the UI expects the following form:
115
126
# choices: [[label, value]]
116
127
# default: [label, value]
117
- response : dict [ str , Any ] = {}
128
+ response : SelectRequesterResult = {}
118
129
choices : list [list [str ]] = []
119
130
120
131
for option in resp :
0 commit comments