Skip to content
This repository was archived by the owner on Jun 13, 2025. It is now read-only.

Commit e0a8e09

Browse files
authored
API Improvements: Fix typings for various files pt1 (#1040)
1 parent e3b3e49 commit e0a8e09

File tree

21 files changed

+216
-117
lines changed

21 files changed

+216
-117
lines changed

api/public/v2/component/views.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
from typing import Any
2+
13
from drf_spectacular.types import OpenApiTypes
24
from drf_spectacular.utils import OpenApiParameter, extend_schema
35
from rest_framework import viewsets
6+
from rest_framework.request import Request
47
from rest_framework.response import Response
58

69
from api.public.v2.component.serializers import ComponentSerializer
@@ -34,7 +37,7 @@ class ComponentViewSet(viewsets.ViewSet, RepoPropertyMixin):
3437
permission_classes = [RepositoryArtifactPermissions]
3538

3639
@extend_schema(summary="Component list")
37-
def list(self, request, *args, **kwargs):
40+
def list(self, request: Request, *args: Any, **kwargs: Any) -> Response:
3841
"""
3942
Returns a list of components for the specified repository
4043
"""

billing/views.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import logging
22
from datetime import datetime
3-
from typing import List
3+
from typing import Any, List
44

55
import stripe
66
from django.conf import settings
@@ -410,7 +410,7 @@ def checkout_session_completed(
410410

411411
self._log_updated([owner])
412412

413-
def post(self, request: HttpRequest, *args, **kwargs) -> Response:
413+
def post(self, request: HttpRequest, *args: Any, **kwargs: Any) -> Response:
414414
if settings.STRIPE_ENDPOINT_SECRET is None:
415415
log.critical(
416416
"Stripe endpoint secret improperly configured -- webhooks will not be processed."

codecov_auth/authentication/repo_auth.py

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import json
22
import logging
3-
from typing import List
3+
from typing import Any, Dict, List, Optional, Tuple
44
from uuid import UUID
55

66
from django.core.exceptions import ObjectDoesNotExist
@@ -10,6 +10,7 @@
1010
from jwt import PyJWTError
1111
from rest_framework import authentication, exceptions, serializers
1212
from rest_framework.exceptions import NotAuthenticated
13+
from rest_framework.response import Response
1314
from rest_framework.views import exception_handler
1415
from shared.django_apps.codecov_auth.models import Owner
1516

@@ -32,7 +33,9 @@
3233
log = logging.getLogger(__name__)
3334

3435

35-
def repo_auth_custom_exception_handler(exc, context):
36+
def repo_auth_custom_exception_handler(
37+
exc: Exception, context: Dict[str, Any]
38+
) -> Response:
3639
"""
3740
User arrives here if they have correctly supplied a Token or the Tokenless Headers,
3841
but their Token has not matched with any of our Authentication methods. The goal is to
@@ -60,17 +63,17 @@ def repo_auth_custom_exception_handler(exc, context):
6063

6164

6265
class LegacyTokenRepositoryAuth(RepositoryAuthInterface):
63-
def __init__(self, repository, auth_data):
66+
def __init__(self, repository: Repository, auth_data: Dict[str, Any]) -> None:
6467
self._auth_data = auth_data
6568
self._repository = repository
6669

67-
def get_scopes(self):
70+
def get_scopes(self) -> List[TokenTypeChoices]:
6871
return [TokenTypeChoices.UPLOAD]
6972

70-
def get_repositories(self):
73+
def get_repositories(self) -> List[Repository]:
7174
return [self._repository]
7275

73-
def allows_repo(self, repository):
76+
def allows_repo(self, repository: Repository) -> bool:
7477
return repository in self.get_repositories()
7578

7679

@@ -79,17 +82,17 @@ class OIDCTokenRepositoryAuth(LegacyTokenRepositoryAuth):
7982

8083

8184
class TableTokenRepositoryAuth(RepositoryAuthInterface):
82-
def __init__(self, repository, token):
85+
def __init__(self, repository: Repository, token: RepositoryToken) -> None:
8386
self._token = token
8487
self._repository = repository
8588

86-
def get_scopes(self):
89+
def get_scopes(self) -> List[str]:
8790
return [self._token.token_type]
8891

89-
def get_repositories(self):
92+
def get_repositories(self) -> List[Repository]:
9093
return [self._repository]
9194

92-
def allows_repo(self, repository):
95+
def allows_repo(self, repository: Repository) -> bool:
9396
return repository in self.get_repositories()
9497

9598

@@ -98,10 +101,10 @@ def __init__(self, token: OrganizationLevelToken) -> None:
98101
self._token = token
99102
self._org = token.owner
100103

101-
def get_scopes(self):
104+
def get_scopes(self) -> List[str]:
102105
return [self._token.token_type]
103106

104-
def allows_repo(self, repository):
107+
def allows_repo(self, repository: Repository) -> bool:
105108
return repository.author.ownerid == self._org.ownerid
106109

107110
def get_repositories_queryset(self) -> QuerySet:
@@ -120,18 +123,20 @@ class TokenlessAuth(RepositoryAuthInterface):
120123
def __init__(self, repository: Repository) -> None:
121124
self._repository = repository
122125

123-
def get_scopes(self):
126+
def get_scopes(self) -> List[TokenTypeChoices]:
124127
return [TokenTypeChoices.UPLOAD]
125128

126-
def allows_repo(self, repository):
129+
def allows_repo(self, repository: Repository) -> bool:
127130
return repository in self.get_repositories()
128131

129132
def get_repositories(self) -> List[Repository]:
130133
return [self._repository]
131134

132135

133136
class RepositoryLegacyQueryTokenAuthentication(authentication.BaseAuthentication):
134-
def authenticate(self, request):
137+
def authenticate(
138+
self, request: HttpRequest
139+
) -> Optional[Tuple[RepositoryAsUser, LegacyTokenRepositoryAuth]]:
135140
token = request.GET.get("token")
136141
if not token:
137142
return None
@@ -150,22 +155,26 @@ def authenticate(self, request):
150155

151156

152157
class RepositoryLegacyTokenAuthentication(authentication.TokenAuthentication):
153-
def authenticate_credentials(self, token):
158+
def authenticate_credentials(
159+
self, token: str
160+
) -> Optional[Tuple[RepositoryAsUser, LegacyTokenRepositoryAuth]]:
154161
try:
155-
token = UUID(token)
156-
repository = Repository.objects.get(upload_token=token)
162+
token_uuid = UUID(token)
163+
repository = Repository.objects.get(upload_token=token_uuid)
157164
except (ValueError, TypeError, Repository.DoesNotExist):
158165
return None # continue to next auth class
159166
return (
160167
RepositoryAsUser(repository),
161-
LegacyTokenRepositoryAuth(repository, {"token": token}),
168+
LegacyTokenRepositoryAuth(repository, {"token": token_uuid}),
162169
)
163170

164171

165172
class RepositoryTokenAuthentication(authentication.TokenAuthentication):
166173
keyword = "Repotoken"
167174

168-
def authenticate_credentials(self, key):
175+
def authenticate_credentials(
176+
self, key: str
177+
) -> Optional[Tuple[RepositoryAsUser, TableTokenRepositoryAuth]]:
169178
try:
170179
token = RepositoryToken.objects.select_related("repository").get(key=key)
171180
except RepositoryToken.DoesNotExist:
@@ -182,7 +191,9 @@ def authenticate_credentials(self, key):
182191

183192

184193
class GlobalTokenAuthentication(authentication.TokenAuthentication):
185-
def authenticate(self, request):
194+
def authenticate(
195+
self, request: HttpRequest
196+
) -> Optional[Tuple[RepositoryAsUser, LegacyTokenRepositoryAuth]]:
186197
global_tokens = get_global_tokens()
187198
token = self.get_token(request)
188199
using_global_token = token in global_tokens
@@ -219,7 +230,9 @@ def get_token(self, request: HttpRequest) -> str | None:
219230

220231

221232
class OrgLevelTokenAuthentication(authentication.TokenAuthentication):
222-
def authenticate_credentials(self, key):
233+
def authenticate_credentials(
234+
self, key: str
235+
) -> Optional[Tuple[Owner, OrgLevelTokenRepositoryAuth]]:
223236
if is_uuid(key): # else, continue to next auth class
224237
# Actual verification for org level tokens
225238
token = OrganizationLevelToken.objects.filter(token=key).first()
@@ -236,7 +249,9 @@ def authenticate_credentials(self, key):
236249

237250

238251
class GitHubOIDCTokenAuthentication(authentication.TokenAuthentication):
239-
def authenticate_credentials(self, token):
252+
def authenticate_credentials(
253+
self, token: str
254+
) -> Optional[Tuple[RepositoryAsUser, OIDCTokenRepositoryAuth]]:
240255
if not token or is_uuid(token):
241256
return None # continue to next auth class
242257

@@ -283,7 +298,12 @@ def _get_info_from_request_path(
283298

284299
return repo, commitid
285300

286-
def get_branch(self, request, repoid=None, commitid=None):
301+
def get_branch(
302+
self,
303+
request: HttpRequest,
304+
repoid: Optional[int] = None,
305+
commitid: Optional[str] = None,
306+
) -> Optional[str]:
287307
if repoid and commitid:
288308
commit = Commit.objects.filter(
289309
repository_id=repoid, commitid=commitid
@@ -299,7 +319,9 @@ def get_branch(self, request, repoid=None, commitid=None):
299319
else:
300320
return body.get("branch")
301321

302-
def authenticate(self, request):
322+
def authenticate(
323+
self, request: HttpRequest
324+
) -> Tuple[RepositoryAsUser, TokenlessAuth]:
303325
repository, commitid = self._get_info_from_request_path(request)
304326

305327
if repository is None or repository.private:
@@ -341,7 +363,12 @@ def _get_info_from_request_path(
341363
# Validate provider
342364
raise exceptions.AuthenticationFailed(self.auth_failed_message)
343365

344-
def get_branch(self, request, repoid=None, commitid=None):
366+
def get_branch(
367+
self,
368+
request: HttpRequest,
369+
repoid: Optional[int] = None,
370+
commitid: Optional[str] = None,
371+
) -> str:
345372
body = json.loads(str(request.body, "utf8"))
346373

347374
# If commit is not created yet (ie first upload for this commit), we just validate branch format.
@@ -419,7 +446,7 @@ class UploadTokenRequiredGetFromBodyAuthenticationCheck(
419446
then use the same authenticate() as parent class.
420447
"""
421448

422-
def _get_git(self, validated_data):
449+
def _get_git(self, validated_data: Dict[str, str]) -> Optional[str]:
423450
"""
424451
BA sends this in as git_service, TA sends this in as service.
425452
Use this function so this Check class can be used by both views.

codecov_auth/commands/owner/interactors/get_uploads_number_per_user.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from typing import Optional
2+
13
from shared.plan.service import PlanService
24
from shared.upload.utils import query_monthly_coverage_measurements
35

@@ -11,7 +13,7 @@
1113

1214
class GetUploadsNumberPerUserInteractor(BaseInteractor):
1315
@sync_to_async
14-
def execute(self, owner: Owner):
16+
def execute(self, owner: Owner) -> Optional[int]:
1517
plan_service = PlanService(current_org=owner)
1618
monthly_limit = plan_service.monthly_uploads_limit
1719
if monthly_limit is not None:

core/commands/repository/repository.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import uuid
2-
from typing import Optional
2+
from typing import Awaitable, Optional
33

44
from codecov.commands.base import BaseCommand
5-
from codecov_auth.models import Owner
5+
from codecov_auth.models import Owner, RepositoryToken
66
from core.models import Repository
7-
from timeseries.models import MeasurementName
7+
from timeseries.models import Dataset, MeasurementName
88

99
from .interactors.activate_measurements import ActivateMeasurementsInteractor
1010
from .interactors.encode_secret_string import EncodeSecretStringInteractor
@@ -22,8 +22,8 @@
2222
class RepositoryCommands(BaseCommand):
2323
def fetch_repository(
2424
self,
25-
owner,
26-
name,
25+
owner: Owner,
26+
name: str,
2727
okta_authenticated_accounts: list[int],
2828
exclude_okta_enforced_repos: bool = True,
2929
) -> Repository:
@@ -38,7 +38,7 @@ def regenerate_repository_upload_token(
3838
self,
3939
repo_name: str,
4040
owner_username: str,
41-
) -> uuid.UUID:
41+
) -> Awaitable[uuid.UUID]:
4242
return self.get_interactor(RegenerateRepositoryUploadTokenInteractor).execute(
4343
repo_name, owner_username
4444
)
@@ -49,37 +49,39 @@ def update_repository(
4949
owner: Owner,
5050
default_branch: Optional[str],
5151
activated: Optional[bool],
52-
):
52+
) -> None:
5353
return self.get_interactor(UpdateRepositoryInteractor).execute(
5454
repo_name, owner, default_branch, activated
5555
)
5656

57-
def get_upload_token(self, repository):
57+
def get_upload_token(self, repository: Repository) -> uuid.UUID:
5858
return self.get_interactor(GetUploadTokenInteractor).execute(repository)
5959

60-
def get_repository_token(self, repository, token_type):
60+
def get_repository_token(
61+
self, repository: Repository, token_type: RepositoryToken.TokenType
62+
) -> str:
6163
return self.get_interactor(GetRepositoryTokenInteractor).execute(
6264
repository, token_type
6365
)
6466

6567
def regenerate_repository_token(
66-
self, repo_name: str, owner_username: str, token_type: str
67-
):
68+
self, repo_name: str, owner_username: str, token_type: RepositoryToken.TokenType
69+
) -> str:
6870
return self.get_interactor(RegenerateRepositoryTokenInteractor).execute(
6971
repo_name, owner_username, token_type
7072
)
7173

7274
def activate_measurements(
7375
self, repo_name: str, owner_name: str, measurement_type: MeasurementName
74-
):
76+
) -> Dataset:
7577
return self.get_interactor(ActivateMeasurementsInteractor).execute(
7678
repo_name, owner_name, measurement_type
7779
)
7880

79-
def erase_repository(self, repo_name: str, owner: Owner):
81+
def erase_repository(self, repo_name: str, owner: Owner) -> None:
8082
return self.get_interactor(EraseRepositoryInteractor).execute(repo_name, owner)
8183

82-
def encode_secret_string(self, owner: Owner, repo_name: str, value: str):
84+
def encode_secret_string(self, owner: Owner, repo_name: str, value: str) -> str:
8385
return self.get_interactor(EncodeSecretStringInteractor).execute(
8486
owner, repo_name, value
8587
)

core/signals.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import logging
2-
from typing import Any, Dict, List, Type
2+
from typing import Any, Dict, List, Type, cast
33

44
from django.db.models.signals import post_save
55
from django.dispatch import receiver
@@ -16,7 +16,7 @@ def update_repository(
1616
sender: Type[Repository], instance: Repository, **kwargs: Dict[str, Any]
1717
) -> None:
1818
log.info(f"Signal triggered for repository {instance.repoid}")
19-
created: bool = kwargs["created"]
19+
created: bool = cast(bool, kwargs["created"])
2020
changes: Dict[str, Any] = instance.tracker.changed()
2121
tracked_fields: List[str] = ["name", "upload_token", "activated", "active"]
2222

graphql_api/types/account/account.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
from typing import Any, Coroutine, Optional
2+
13
from ariadne import ObjectType
24
from graphql import GraphQLResolveInfo
35

46
from codecov.db import sync_to_async
5-
from codecov_auth.models import Account, OktaSettings
7+
from codecov_auth.models import Account, OktaSettings, Owner
68
from graphql_api.helpers.ariadne import ariadne_load_local_graphql
79
from graphql_api.helpers.connection import (
810
build_connection_graphql,
@@ -43,9 +45,9 @@ def resolve_activated_user_count(account: Account, info: GraphQLResolveInfo) ->
4345
def resolve_organizations(
4446
account: Account,
4547
info: GraphQLResolveInfo,
46-
ordering_direction=OrderingDirection.ASC,
47-
**kwargs,
48-
):
48+
ordering_direction: Optional[OrderingDirection] = OrderingDirection.ASC,
49+
**kwargs: Any,
50+
) -> Coroutine[Any, Any, Owner]:
4951
return queryset_to_connection(
5052
account.organizations,
5153
ordering=("username",),

0 commit comments

Comments
 (0)