11from rest_framework import serializers
22
3- from api . public . v2 . owner . serializers import OwnerSerializer
4- from api . shared . commit . serializers import CommitTotalsSerializer
5- from core . models import Pull , PullStates
3+ from compare . models import CommitComparison
4+ from core . models import Pull
5+ from services . comparison import ComparisonReport
66
77
88class PullSerializer (serializers .ModelSerializer ):
9- pullid = serializers .IntegerField (label = "pull ID number" )
10- title = serializers .CharField (label = "title of the pull" )
11- base_totals = CommitTotalsSerializer (label = "coverage totals of base commit" )
12- head_totals = CommitTotalsSerializer (label = "coverage totals of head commit" )
13- updatestamp = serializers .DateTimeField (label = "last updated timestamp" )
14- state = serializers .ChoiceField (
15- label = "state of the pull" , choices = PullStates .choices
16- )
17- ci_passed = serializers .BooleanField (
18- label = "indicates whether the CI process passed for the head commit of this pull"
19- )
20- author = OwnerSerializer (label = "pull author" )
9+ patch = serializers .SerializerMethodField ()
2110
2211 class Meta :
2312 model = Pull
@@ -30,5 +19,42 @@ class Meta:
3019 "state" ,
3120 "ci_passed" ,
3221 "author" ,
22+ "patch" ,
3323 )
3424 fields = read_only_fields
25+
26+ def get_patch (self , obj : Pull ):
27+ # 1) Fetch the CommitComparison for (compared_to, head)
28+ comparison_qs = CommitComparison .objects .filter (
29+ base_commit__commitid = obj .compared_to ,
30+ compare_commit__commitid = obj .head ,
31+ base_commit__repository_id = obj .repository_id ,
32+ compare_commit__repository_id = obj .repository_id ,
33+ ).select_related ("compare_commit" , "base_commit" )
34+
35+ commit_comparison = comparison_qs .first ()
36+ if not commit_comparison or not commit_comparison .is_processed :
37+ return None
38+
39+ # 2) Wrap it in ComparisonReport
40+ cr = ComparisonReport (commit_comparison )
41+
42+ # 3) Summation of patch coverage across impacted files
43+ hits = misses = partials = 0
44+ for f in cr .impacted_files :
45+ pc = f .patch_coverage
46+ if pc :
47+ hits += pc .hits
48+ misses += pc .misses
49+ partials += pc .partials
50+
51+ total_branches = hits + misses + partials
52+ if total_branches == 0 :
53+ return None
54+
55+ return dict (
56+ hits = hits ,
57+ misses = misses ,
58+ partials = partials ,
59+ coverage = 100 * hits / total_branches ,
60+ )
0 commit comments