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

Commit 3ac41b8

Browse files
authored
Merge branch 'main' into jan_06_cache_config
2 parents 98f08fc + a0c8267 commit 3ac41b8

File tree

32 files changed

+257
-166
lines changed

32 files changed

+257
-166
lines changed

api/internal/commit/serializers.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
from typing import Dict, List
23

34
import shared.reports.api_report_service as report_service
45
from rest_framework import serializers
@@ -32,7 +33,7 @@ class Meta:
3233
class CommitWithFileLevelReportSerializer(CommitSerializer):
3334
report = serializers.SerializerMethodField()
3435

35-
def get_report(self, commit: Commit):
36+
def get_report(self, commit: Commit) -> Dict[str, List[Dict] | Dict] | None:
3637
report = report_service.build_report_from_commit(commit)
3738
if report is None:
3839
return None

api/internal/feature/views.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import logging
22
import pickle
3+
from typing import Any, Dict, List
34

45
from rest_framework import status
6+
from rest_framework.request import Request
57
from rest_framework.response import Response
68
from rest_framework.views import APIView
79
from shared.django_apps.rollouts.models import FeatureFlag
@@ -20,15 +22,15 @@ class FeaturesView(APIView):
2022
skip_feature_cache = get_config("setup", "skip_feature_cache", default=False)
2123
timeout = 300
2224

23-
def __init__(self, *args, **kwargs):
25+
def __init__(self, *args: Any, **kwargs: Any) -> None:
2426
self.redis = get_redis_connection()
2527
super().__init__(*args, **kwargs)
2628

27-
def get_many_from_redis(self, keys):
29+
def get_many_from_redis(self, keys: List) -> Dict[str, Any]:
2830
ret = self.redis.mget(keys)
2931
return {k: pickle.loads(v) for k, v in zip(keys, ret) if v is not None}
3032

31-
def set_many_to_redis(self, data):
33+
def set_many_to_redis(self, data: Dict[str, Any]) -> None:
3234
pipeline = self.redis.pipeline()
3335
pipeline.mset({k: pickle.dumps(v) for k, v in data.items()})
3436

@@ -38,7 +40,7 @@ def set_many_to_redis(self, data):
3840
pipeline.expire(key, self.timeout)
3941
pipeline.execute()
4042

41-
def post(self, request):
43+
def post(self, request: Request) -> Response:
4244
serializer = FeatureRequestSerializer(data=request.data)
4345
if serializer.is_valid():
4446
flag_evaluations = {}

api/internal/owner/serializers.py

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import logging
22
from datetime import datetime
3+
from typing import Any, Dict
34

45
from dateutil.relativedelta import relativedelta
56
from django.conf import settings
@@ -37,7 +38,7 @@ class Meta:
3738

3839
read_only_fields = fields
3940

40-
def get_stats(self, obj):
41+
def get_stats(self, obj: Owner) -> str | None:
4142
if obj.cache and "stats" in obj.cache:
4243
return obj.cache["stats"]
4344

@@ -50,7 +51,7 @@ class StripeLineItemSerializer(serializers.Serializer):
5051
plan_name = serializers.SerializerMethodField()
5152
quantity = serializers.IntegerField()
5253

53-
def get_plan_name(self, line_item):
54+
def get_plan_name(self, line_item: Dict[str, str]) -> str | None:
5455
plan = line_item.get("plan")
5556
if plan:
5657
return plan.get("name")
@@ -85,7 +86,7 @@ class StripeDiscountSerializer(serializers.Serializer):
8586
duration_in_months = serializers.IntegerField(source="coupon.duration_in_months")
8687
expires = serializers.SerializerMethodField()
8788

88-
def get_expires(self, customer):
89+
def get_expires(self, customer: Dict[str, Dict]) -> int | None:
8990
coupon = customer.get("coupon")
9091
if coupon:
9192
months = coupon.get("duration_in_months")
@@ -121,7 +122,7 @@ class PlanSerializer(serializers.Serializer):
121122
benefits = serializers.JSONField(read_only=True)
122123
quantity = serializers.IntegerField(required=False)
123124

124-
def validate_value(self, value):
125+
def validate_value(self, value: str) -> str:
125126
current_org = self.context["view"].owner
126127
current_owner = self.context["request"].current_owner
127128

@@ -136,11 +137,11 @@ def validate_value(self, value):
136137
extra=dict(owner_id=current_owner.pk, plan=value),
137138
)
138139
raise serializers.ValidationError(
139-
f"Invalid value for plan: {value}; " f"must be one of {plan_values}"
140+
f"Invalid value for plan: {value}; must be one of {plan_values}"
140141
)
141142
return value
142143

143-
def validate(self, plan):
144+
def validate(self, plan: Dict[str, Any]) -> Dict[str, Any]:
144145
current_org = self.context["view"].owner
145146
if current_org.account:
146147
raise serializers.ValidationError(
@@ -206,7 +207,7 @@ class StripeScheduledPhaseSerializer(serializers.Serializer):
206207
plan = serializers.SerializerMethodField()
207208
quantity = serializers.SerializerMethodField()
208209

209-
def get_plan(self, phase):
210+
def get_plan(self, phase: Dict[str, Any]) -> str:
210211
plan_id = phase["items"][0]["plan"]
211212
stripe_plan_dict = settings.STRIPE_PLAN_IDS
212213
plan_name = list(stripe_plan_dict.keys())[
@@ -215,15 +216,15 @@ def get_plan(self, phase):
215216
marketing_plan_name = PAID_PLANS[plan_name].billing_rate
216217
return marketing_plan_name
217218

218-
def get_quantity(self, phase):
219+
def get_quantity(self, phase: Dict[str, Any]) -> int:
219220
return phase["items"][0]["quantity"]
220221

221222

222223
class ScheduleDetailSerializer(serializers.Serializer):
223224
id = serializers.CharField()
224225
scheduled_phase = serializers.SerializerMethodField()
225226

226-
def get_scheduled_phase(self, schedule):
227+
def get_scheduled_phase(self, schedule: Dict[str, Any]) -> Dict[str, Any] | None:
227228
if len(schedule["phases"]) > 1:
228229
return StripeScheduledPhaseSerializer(schedule["phases"][-1]).data
229230
else:
@@ -291,44 +292,44 @@ class Meta:
291292
"uses_invoice",
292293
)
293294

294-
def _get_billing(self):
295+
def _get_billing(self) -> BillingService:
295296
current_owner = self.context["request"].current_owner
296297
return BillingService(requesting_user=current_owner)
297298

298-
def get_subscription_detail(self, owner):
299+
def get_subscription_detail(self, owner: Owner) -> Dict[str, Any] | None:
299300
subscription_detail = self._get_billing().get_subscription(owner)
300301
if subscription_detail:
301302
return SubscriptionDetailSerializer(subscription_detail).data
302303

303-
def get_schedule_detail(self, owner):
304+
def get_schedule_detail(self, owner: Owner) -> Dict[str, Any] | None:
304305
schedule_detail = self._get_billing().get_schedule(owner)
305306
if schedule_detail:
306307
return ScheduleDetailSerializer(schedule_detail).data
307308

308-
def get_checkout_session_id(self, _):
309+
def get_checkout_session_id(self, _: Any) -> str:
309310
return self.context.get("checkout_session_id")
310311

311-
def get_activated_student_count(self, owner):
312+
def get_activated_student_count(self, owner: Owner) -> int:
312313
if owner.account:
313314
return owner.account.activated_student_count
314315
return owner.activated_student_count
315316

316-
def get_activated_user_count(self, owner):
317+
def get_activated_user_count(self, owner: Owner) -> int:
317318
if owner.account:
318319
return owner.account.activated_user_count
319320
return owner.activated_user_count
320321

321-
def get_delinquent(self, owner):
322+
def get_delinquent(self, owner: Owner) -> bool:
322323
if owner.account:
323324
return owner.account.is_delinquent
324325
return owner.delinquent
325326

326-
def get_uses_invoice(self, owner):
327+
def get_uses_invoice(self, owner: Owner) -> bool:
327328
if owner.account:
328329
return owner.account.invoice_billing.filter(is_active=True).exists()
329330
return owner.uses_invoice
330331

331-
def update(self, instance, validated_data):
332+
def update(self, instance: Owner, validated_data: Dict[str, Any]) -> object:
332333
if "pretty_plan" in validated_data:
333334
desired_plan = validated_data.pop("pretty_plan")
334335
checkout_session_id_or_none = self._get_billing().update_plan(
@@ -367,7 +368,7 @@ class Meta:
367368
"last_pull_timestamp",
368369
)
369370

370-
def update(self, instance, validated_data):
371+
def update(self, instance: Owner, validated_data: Dict[str, Any]) -> object:
371372
owner = self.context["view"].owner
372373

373374
if "activated" in validated_data:
@@ -391,7 +392,7 @@ def update(self, instance, validated_data):
391392
# Re-fetch from DB to set activated and admin fields
392393
return self.context["view"].get_object()
393394

394-
def get_last_pull_timestamp(self, obj):
395+
def get_last_pull_timestamp(self, obj: Owner) -> str | None:
395396
# this field comes from an annotation that may not always be applied to the queryset
396397
if hasattr(obj, "last_pull_timestamp"):
397398
return obj.last_pull_timestamp

codecov_auth/commands/owner/interactors/save_terms_agreement.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from dataclasses import dataclass
2-
from typing import Optional
2+
from typing import Any, Optional
33

44
from django.utils import timezone
55

@@ -20,7 +20,7 @@ class TermsAgreementInput:
2020
class SaveTermsAgreementInteractor(BaseInteractor):
2121
requires_service = False
2222

23-
def validate(self, input: TermsAgreementInput):
23+
def validate(self, input: TermsAgreementInput) -> None:
2424
valid_customer_intents = ["Business", "BUSINESS", "Personal", "PERSONAL"]
2525
if (
2626
input.customer_intent
@@ -30,7 +30,7 @@ def validate(self, input: TermsAgreementInput):
3030
if not self.current_user.is_authenticated:
3131
raise Unauthenticated()
3232

33-
def update_terms_agreement(self, input: TermsAgreementInput):
33+
def update_terms_agreement(self, input: TermsAgreementInput) -> None:
3434
self.current_user.terms_agreement = input.terms_agreement
3535
self.current_user.terms_agreement_at = timezone.now()
3636
self.current_user.customer_intent = input.customer_intent
@@ -44,14 +44,14 @@ def update_terms_agreement(self, input: TermsAgreementInput):
4444
if input.marketing_consent:
4545
self.send_data_to_marketo()
4646

47-
def send_data_to_marketo(self):
47+
def send_data_to_marketo(self) -> None:
4848
event_data = {
4949
"email": self.current_user.email,
5050
}
5151
AnalyticsService().opt_in_email(self.current_user.id, event_data)
5252

5353
@sync_to_async
54-
def execute(self, input):
54+
def execute(self, input: Any) -> None:
5555
typed_input = TermsAgreementInput(
5656
business_email=input.get("business_email"),
5757
terms_agreement=input.get("terms_agreement"),

codecov_auth/commands/owner/interactors/set_yaml_on_owner.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ def convert_yaml_to_dict(self, yaml_input: str) -> Optional[dict]:
4242
except yaml.scanner.ScannerError as e:
4343
line = e.problem_mark.line
4444
column = e.problem_mark.column
45-
message = f"Syntax error at line {line+1}, column {column+1}: {e.problem}"
45+
message = (
46+
f"Syntax error at line {line + 1}, column {column + 1}: {e.problem}"
47+
)
4648
raise ValidationError(message)
4749
if not yaml_dict:
4850
return None
@@ -52,7 +54,7 @@ def convert_yaml_to_dict(self, yaml_input: str) -> Optional[dict]:
5254
message = f"Error at {str(e.error_location)}: {e.error_message}"
5355
raise ValidationError(message)
5456

55-
def yaml_side_effects(self, old_yaml: dict, new_yaml: dict):
57+
def yaml_side_effects(self, old_yaml: dict | None, new_yaml: dict | None) -> None:
5658
old_yaml_branch = old_yaml and old_yaml.get("codecov", {}).get("branch")
5759
new_yaml_branch = new_yaml and new_yaml.get("codecov", {}).get("branch")
5860

codecov_auth/commands/owner/interactors/tests/test_set_yaml_on_owner.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ async def test_user_is_part_of_org_and_yaml_is_good(self):
9696
"codecov": {
9797
"require_ci_to_pass": True,
9898
},
99-
"to_string": "\n" "codecov:\n" " require_ci_to_pass: yes\n",
99+
"to_string": "\ncodecov:\n require_ci_to_pass: yes\n",
100100
}
101101

102102
async def test_user_is_part_of_org_and_yaml_has_quotes(self):
@@ -109,7 +109,7 @@ async def test_user_is_part_of_org_and_yaml_has_quotes(self):
109109
"codecov": {
110110
"bot": "codecov",
111111
},
112-
"to_string": "\n" "codecov:\n" " bot: 'codecov'\n",
112+
"to_string": "\ncodecov:\n bot: 'codecov'\n",
113113
}
114114

115115
async def test_user_is_part_of_org_and_yaml_is_empty(self):

codecov_auth/management/commands/set_trial_status_values.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from datetime import datetime
2+
from typing import Any
23

34
from django.core.management.base import BaseCommand, CommandParser
45
from django.db.models import Q
@@ -20,7 +21,7 @@ class Command(BaseCommand):
2021
def add_arguments(self, parser: CommandParser) -> None:
2122
parser.add_argument("trial_status_type", type=str)
2223

23-
def handle(self, *args, **options) -> None:
24+
def handle(self, *args: Any, **options: Any) -> None:
2425
trial_status_type = options.get("trial_status_type", {})
2526

2627
# NOT_STARTED

codecov_auth/signals.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, Dict, Optional, Type
1+
from typing import Any, Dict, Optional, Type, cast
22

33
from django.db.models.signals import post_save
44
from django.dispatch import receiver
@@ -38,7 +38,7 @@ def update_owner(
3838
"""
3939
Shelter tracks a limited set of Owner fields - only update if those fields have changed.
4040
"""
41-
created: bool = kwargs["created"]
41+
created: bool = cast(bool, kwargs["created"])
4242
tracked_fields = [
4343
"upload_token_required_for_public_repos",
4444
"username",

codecov_auth/views/sentry.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ def _perform_login(self, request: HttpRequest) -> HttpResponse:
123123
# user has not connected any owners yet
124124
return redirect(f"{settings.CODECOV_DASHBOARD_URL}/sync")
125125

126-
def _login_user(self, request: HttpRequest, user_data: dict):
126+
def _login_user(self, request: HttpRequest, user_data: dict) -> User:
127127
sentry_id = user_data["user"]["id"]
128128
user_name = user_data["user"].get("name")
129129
user_email = user_data["user"].get("email")
@@ -177,7 +177,7 @@ def _login_user(self, request: HttpRequest, user_data: dict):
177177
login(request, current_user)
178178
return current_user
179179

180-
def get(self, request):
180+
def get(self, request: HttpRequest) -> HttpResponse:
181181
if request.GET.get("code"):
182182
return self._perform_login(request)
183183
else:

core/commands/commit/interactors/get_file_content.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import logging
2+
from typing import Any, Coroutine
23

34
from codecov.commands.base import BaseInteractor
5+
from core.models import Commit
46
from services.repo_providers import RepoProviderService
57

68
log = logging.getLogger(__name__)
79

810

911
class GetFileContentInteractor(BaseInteractor):
10-
async def get_file_from_service(self, commit, path):
12+
async def get_file_from_service(self, commit: Commit, path: str) -> str | None:
1113
try:
1214
repository_service = await RepoProviderService().async_get_adapter(
1315
owner=self.current_owner, repo=commit.repository
@@ -27,5 +29,5 @@ async def get_file_from_service(self, commit, path):
2729
)
2830
return None
2931

30-
def execute(self, commit, path):
32+
def execute(self, commit: Commit, path: str) -> Coroutine[Any, Any, str | None]:
3133
return self.get_file_from_service(commit, path)

0 commit comments

Comments
 (0)