@@ -46,9 +46,7 @@ async def get_installation_access_token(installation_id: int, app_jwt: str) -> d
4646 except httpx .HTTPStatusError as e :
4747 if e .response .status_code == 401 :
4848 raise UnauthorizedError ("GitHub App JWT is invalid or expired" ) from e
49- raise ExternalServiceError (
50- f"GitHub API error: { e .response .status_code } "
51- ) from e
49+ raise ExternalServiceError (f"GitHub API error: { e .response .status_code } " ) from e
5250 return resp .json ()
5351
5452
@@ -106,9 +104,7 @@ async def create_installation(session: AsyncSession, webhook_data: dict) -> Inst
106104 return installation
107105
108106
109- async def soft_delete_installation (
110- session : AsyncSession , github_installation_id : int
111- ) -> Installation | None :
107+ async def soft_delete_installation (session : AsyncSession , github_installation_id : int ) -> Installation | None :
112108 """Soft-delete an installation by setting deleted_at. Returns None if not found."""
113109 result = await session .execute (
114110 select (Installation ).where (
@@ -128,9 +124,7 @@ async def soft_delete_installation(
128124 return installation
129125
130126
131- async def suspend_installation (
132- session : AsyncSession , github_installation_id : int
133- ) -> Installation | None :
127+ async def suspend_installation (session : AsyncSession , github_installation_id : int ) -> Installation | None :
134128 """Set suspended_at on an installation."""
135129 result = await session .execute (
136130 select (Installation ).where (
@@ -150,9 +144,7 @@ async def suspend_installation(
150144 return installation
151145
152146
153- async def unsuspend_installation (
154- session : AsyncSession , github_installation_id : int
155- ) -> Installation | None :
147+ async def unsuspend_installation (session : AsyncSession , github_installation_id : int ) -> Installation | None :
156148 """Clear suspended_at on an installation."""
157149 result = await session .execute (
158150 select (Installation ).where (
@@ -172,9 +164,7 @@ async def unsuspend_installation(
172164 return installation
173165
174166
175- async def get_installation_by_github_id (
176- session : AsyncSession , github_installation_id : int
177- ) -> Installation | None :
167+ async def get_installation_by_github_id (session : AsyncSession , github_installation_id : int ) -> Installation | None :
178168 """Lookup installation by GitHub ID, excluding soft-deleted records."""
179169 result = await session .execute (
180170 select (Installation ).where (
@@ -185,9 +175,7 @@ async def get_installation_by_github_id(
185175 return result .scalar_one_or_none ()
186176
187177
188- async def get_installations_for_user (
189- session : AsyncSession , user , settings : Settings
190- ) -> list [Installation ]:
178+ async def get_installations_for_user (session : AsyncSession , user , settings : Settings ) -> list [Installation ]:
191179 """Get installations the user has access to via the GitHub API."""
192180 try :
193181 github_token = fernet_decrypt (user .github_access_token_enc , settings .FERNET_KEY )
@@ -210,13 +198,9 @@ async def get_installations_for_user(
210198 except httpx .HTTPStatusError as e :
211199 if e .response .status_code == 401 :
212200 raise UnauthorizedError ("GitHub token is invalid or revoked" ) from e
213- raise ExternalServiceError (
214- f"GitHub API error: { e .response .status_code } "
215- ) from e
201+ raise ExternalServiceError (f"GitHub API error: { e .response .status_code } " ) from e
216202
217- user_installation_ids = {
218- inst ["id" ] for inst in resp .json ().get ("installations" , [])
219- }
203+ user_installation_ids = {inst ["id" ] for inst in resp .json ().get ("installations" , [])}
220204
221205 if not user_installation_ids :
222206 return []
@@ -230,9 +214,7 @@ async def get_installations_for_user(
230214 return list (result .scalars ().all ())
231215
232216
233- async def verify_admin_permission (
234- user , installation : Installation , settings : Settings
235- ) -> bool :
217+ async def verify_admin_permission (user , installation : Installation , settings : Settings ) -> bool :
236218 """Verify user has admin permission on the installation's org/repo."""
237219 try :
238220 github_token = fernet_decrypt (user .github_access_token_enc , settings .FERNET_KEY )
@@ -262,12 +244,8 @@ async def verify_admin_permission(
262244 if e .response .status_code == 401 :
263245 raise UnauthorizedError ("GitHub token is invalid or revoked" ) from e
264246 if e .response .status_code in (403 , 404 ):
265- raise ForbiddenError (
266- "You do not have admin access to this installation"
267- ) from e
268- raise ExternalServiceError (
269- f"GitHub API error: { e .response .status_code } "
270- ) from e
247+ raise ForbiddenError ("You do not have admin access to this installation" ) from e
248+ raise ExternalServiceError (f"GitHub API error: { e .response .status_code } " ) from e
271249
272250 membership = resp .json ()
273251 if membership .get ("role" ) != "admin" or membership .get ("state" ) != "active" :
@@ -298,9 +276,7 @@ async def validate_anthropic_api_key(api_key: str) -> bool:
298276 except httpx .TimeoutException as e :
299277 raise ExternalServiceError ("Anthropic API is temporarily unavailable" ) from e
300278 except httpx .HTTPStatusError as e :
301- raise ExternalServiceError (
302- f"Anthropic API error: { e .response .status_code } "
303- ) from e
279+ raise ExternalServiceError (f"Anthropic API error: { e .response .status_code } " ) from e
304280 except httpx .TransportError as e :
305281 raise ExternalServiceError ("Anthropic API is temporarily unavailable" ) from e
306282
@@ -314,9 +290,7 @@ async def configure_byok(
314290 """Configure BYOK key for an installation. Validates, encrypts, and upserts."""
315291 is_valid = await validate_anthropic_api_key (api_key )
316292 if not is_valid :
317- raise BYOKKeyInvalidError (
318- "API key validation failed -- check your key and try again"
319- )
293+ raise BYOKKeyInvalidError ("API key validation failed -- check your key and try again" )
320294
321295 encrypted_key = fernet_encrypt (api_key , fernet_key )
322296 key_hint = f"...{ api_key [- 4 :]} "
@@ -346,13 +320,9 @@ async def configure_byok(
346320 return config
347321
348322
349- async def get_byok_config (
350- session : AsyncSession , installation_id : uuid .UUID
351- ) -> BYOKConfig | None :
323+ async def get_byok_config (session : AsyncSession , installation_id : uuid .UUID ) -> BYOKConfig | None :
352324 """Get BYOK config for an installation."""
353- result = await session .execute (
354- select (BYOKConfig ).where (BYOKConfig .installation_id == installation_id )
355- )
325+ result = await session .execute (select (BYOKConfig ).where (BYOKConfig .installation_id == installation_id ))
356326 return result .scalar_one_or_none ()
357327
358328
@@ -364,9 +334,7 @@ def decrypt_byok_key(byok_config: BYOKConfig, fernet_key: str) -> str:
364334 raise BYOKKeyInvalidError ("Stored API key could not be decrypted" ) from e
365335
366336
367- async def delete_byok_config (
368- session : AsyncSession , installation_id : uuid .UUID
369- ) -> bool :
337+ async def delete_byok_config (session : AsyncSession , installation_id : uuid .UUID ) -> bool :
370338 """Hard delete BYOK config for an installation."""
371339 config = await get_byok_config (session , installation_id )
372340 if not config :
@@ -395,9 +363,7 @@ async def update_suppression_labels(
395363 raise DomainValidationError ("Maximum 20 suppression labels allowed" )
396364 for label in labels :
397365 if len (label ) > 50 :
398- raise DomainValidationError (
399- f"Label '{ label } ' exceeds maximum length of 50 characters"
400- )
366+ raise DomainValidationError (f"Label '{ label } ' exceeds maximum length of 50 characters" )
401367 if not LABEL_PATTERN .match (label ):
402368 raise DomainValidationError (
403369 f"Label '{ label } ' contains invalid characters. Only alphanumeric and hyphens allowed"
0 commit comments