We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add max_submissions in the course points API endpoint
This API endpoint `/api/v2/courses/COURSEID/points/USERID/` for course points shows the user's points in exercises. It also includes some exercise info that is also provided by the exercise endpoint (`/api/v2/exercises/ID/`). The points API already contains `max_points` and `points_to_pass`, so why not also include `max_submissions` (maximum number of allowed submissions)?

Relevant code:
https://github.com/apluslms/a-plus/blob/d34f94b7c9a8e4d22cd28d08968b36787bb344c4/exercise/api/views.py#L420
https://github.com/apluslms/a-plus/blob/d34f94b7c9a8e4d22cd28d08968b36787bb344c4/exercise/api/custom_serializers.py#L76

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `exercise/api/serializers.py`
Content:
```
1 from rest_framework import serializers
2 from rest_framework.reverse import reverse
3 
4 from lib.api.fields import NestedHyperlinkedIdentityField
5 from lib.api.serializers import AplusModelSerializer, HtmlViewField
6 from userprofile.api.serializers import UserBriefSerializer
7 from ..models import Submission, SubmittedFile, BaseExercise
8 
9 
10 __all__ = [
11     'ExerciseBriefSerializer',
12     'SubmissionBriefSerializer',
13     'SubmittedFileBriefSerializer',
14     'SubmitterStatsBriefSerializer',
15 ]
16 
17 
18 class ExerciseBriefSerializer(AplusModelSerializer):
19     url = NestedHyperlinkedIdentityField(
20         view_name='api:exercise-detail',
21         lookup_map='exercise.api.views.ExerciseViewSet',
22     )
23     display_name = serializers.CharField(source='__str__')
24 
25     class Meta(AplusModelSerializer.Meta):
26         model = BaseExercise
27         fields = (
28             'url',
29             'html_url',
30             'display_name',
31         )
32 
33 
34 class SubmissionBriefSerializer(AplusModelSerializer):
35     #display_name = serializers.CharField(source='__str__')
36 
37     class Meta(AplusModelSerializer.Meta):
38         model = Submission
39         fields = (
40             'submission_time',
41         )
42         extra_kwargs = {
43             'url': {
44                 'view_name': 'api:submission-detail',
45                 'lookup_map': 'exercise.api.views.SubmissionViewSet',
46             }
47         }
48 
49 
50 class SubmittedFileBriefSerializer(AplusModelSerializer):
51     #url = HtmlViewField()
52     url = NestedHyperlinkedIdentityField(
53         view_name='api:submission-files-detail',
54         lookup_map='exercise.api.views.SubmissionFileViewSet',
55     )
56 
57     class Meta(AplusModelSerializer.Meta):
58         model = SubmittedFile
59         fields = (
60             'url',
61             'filename',
62             'param_name',
63         )
64 
65 
66 class SubmitterStatsBriefSerializer(UserBriefSerializer):
67     stats = serializers.SerializerMethodField()
68 
69     def get_stats(self, profile):
70         return reverse(
71             'api:exercise-submitter_stats-detail',
72             kwargs={
73                 'exercise_id': self.context['view'].exercise.id,
74                 'user_id': profile.user.id,
75             },
76             request=self.context['request']
77         )
78 
79     class Meta(UserBriefSerializer.Meta):
80         fields = UserBriefSerializer.Meta.fields + (
81             'stats',
82         )
83
```

Path: `exercise/api/full_serializers.py`
Content:
```
1 from rest_framework import serializers
2 
3 from lib.api.fields import NestedHyperlinkedIdentityField
4 from lib.api.serializers import (
5     AlwaysListSerializer,
6     CompositeListSerializer,
7     AplusSerializerMeta,
8     AplusModelSerializerBase,
9 )
10 from course.api.serializers import CourseBriefSerializer
11 from userprofile.api.serializers import UserBriefSerializer, UserListField
12 
13 from ..models import Submission
14 from .serializers import (
15     ExerciseBriefSerializer,
16     SubmissionBriefSerializer,
17     SubmittedFileBriefSerializer,
18 )
19 
20 
21 __all__ = [
22     'ExerciseSerializer',
23     'ExerciseGraderSerializer',
24     'SubmissionSerializer',
25     'SubmissionGraderSerializer',
26 ]
27 
28 
29 class ExerciseSerializer(ExerciseBriefSerializer):
30     course = CourseBriefSerializer(source='course_instance')
31     post_url = serializers.SerializerMethodField()
32     exercise_info = serializers.JSONField()
33     submissions = NestedHyperlinkedIdentityField(
34         view_name='api:exercise-submissions-list',
35         lookup_map='exercise.api.views.ExerciseViewSet',
36     )
37     my_submissions = NestedHyperlinkedIdentityField(
38         view_name='api:exercise-submissions-detail',
39         lookup_map={
40             'exercise_id': 'id',
41             'user_id': lambda o=None: 'me',
42         },
43     )
44     my_stats = NestedHyperlinkedIdentityField(
45         view_name='api:exercise-submitter_stats-detail',
46         lookup_map={
47             'exercise_id': 'id',
48             'user_id': lambda o=None: 'me',
49         },
50     )
51 
52     def get_post_url(self, obj):
53         # FIXME: obj should implement .get_post_url() and that should be used here
54         if obj.is_submittable:
55             request = self.context['request']
56             url = obj.get_url("exercise")
57             return request.build_absolute_uri(url)
58         return None
59 
60     class Meta(ExerciseBriefSerializer.Meta):
61         fields = (
62             'name',
63             'course',
64             'is_submittable',
65             'post_url',
66             'max_points',
67             'max_submissions',
68             'exercise_info',
69             'templates',
70             'submissions',
71             'my_submissions',
72             'my_stats',
73         )
74 
75 
76 class ExerciseGraderSerializer(AplusModelSerializerBase):
77     url = NestedHyperlinkedIdentityField(
78         view_name='api:exercise-grader',
79         lookup_map='exercise.api.views.ExerciseViewSet',
80     )
81     exercise = ExerciseBriefSerializer(source='*')
82 
83     class Meta(AplusSerializerMeta):
84         model = Submission
85         fields = (
86             'url',
87             'exercise',
88         )
89 
90 
91 class SubmitterLinks(AlwaysListSerializer, UserBriefSerializer):
92     pass
93 
94 
95 class SubmittedFileLinks(AlwaysListSerializer, SubmittedFileBriefSerializer):
96     pass
97 
98 
99 class SubmissionSerializer(SubmissionBriefSerializer):
100     exercise = ExerciseBriefSerializer()
101     submitters = SubmitterLinks()
102     submission_data = serializers.JSONField()
103     files = SubmittedFileLinks()
104     grader = UserBriefSerializer()
105     grading_data = serializers.JSONField()
106 
107     class Meta(SubmissionBriefSerializer.Meta):
108         fields = (
109             'html_url',
110             'exercise',
111             'submitters',
112             'submission_data',
113             'files',
114             'status',
115             'grade',
116             'late_penalty_applied',
117             'grading_time',
118             'grader',
119             'feedback',
120             'assistant_feedback',
121             'grading_data',
122         )
123 
124 
125 class SubmissionInGraderSerializer(SubmissionBriefSerializer):
126     class Meta(SubmissionBriefSerializer.Meta):
127         fields = (
128             'html_url',
129         )
130 
131 
132 class SubmissionGraderSerializer(AplusModelSerializerBase):
133     url = NestedHyperlinkedIdentityField(
134         view_name='api:submission-grader',
135         lookup_map='exercise.api.views.SubmissionViewSet',
136     )
137     submission = SubmissionInGraderSerializer(source='*')
138     exercise = ExerciseBriefSerializer()
139 
140     class Meta(AplusSerializerMeta):
141         model = Submission
142         fields = (
143             'url',
144             'submission',
145             'exercise',
146             'grading_data',
147             'is_graded',
148         )
149
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/exercise/api/full_serializers.py b/exercise/api/full_serializers.py
--- a/exercise/api/full_serializers.py
+++ b/exercise/api/full_serializers.py
@@ -63,8 +63,6 @@
             'course',
             'is_submittable',
             'post_url',
-            'max_points',
-            'max_submissions',
             'exercise_info',
             'templates',
             'submissions',
diff --git a/exercise/api/serializers.py b/exercise/api/serializers.py
--- a/exercise/api/serializers.py
+++ b/exercise/api/serializers.py
@@ -28,6 +28,8 @@
             'url',
             'html_url',
             'display_name',
+            'max_points',
+            'max_submissions',
         )

{"golden_diff": "diff --git a/exercise/api/full_serializers.py b/exercise/api/full_serializers.py\n--- a/exercise/api/full_serializers.py\n+++ b/exercise/api/full_serializers.py\n@@ -63,8 +63,6 @@\n             'course',\n             'is_submittable',\n             'post_url',\n-            'max_points',\n-            'max_submissions',\n             'exercise_info',\n             'templates',\n             'submissions',\ndiff --git a/exercise/api/serializers.py b/exercise/api/serializers.py\n--- a/exercise/api/serializers.py\n+++ b/exercise/api/serializers.py\n@@ -28,6 +28,8 @@\n             'url',\n             'html_url',\n             'display_name',\n+            'max_points',\n+            'max_submissions',\n         )\n", "issue": "Add max_submissions in the course points API endpoint\nThis API endpoint `/api/v2/courses/COURSEID/points/USERID/` for course points shows the user's points in exercises. It also includes some exercise info that is also provided by the exercise endpoint (`/api/v2/exercises/ID/`). The points API already contains `max_points` and `points_to_pass`, so why not also include `max_submissions` (maximum number of allowed submissions)?\r\n\r\nRelevant code:\r\nhttps://github.com/apluslms/a-plus/blob/d34f94b7c9a8e4d22cd28d08968b36787bb344c4/exercise/api/views.py#L420\r\nhttps://github.com/apluslms/a-plus/blob/d34f94b7c9a8e4d22cd28d08968b36787bb344c4/exercise/api/custom_serializers.py#L76\n", "before_files": [{"content": "from rest_framework import serializers\nfrom rest_framework.reverse import reverse\n\nfrom lib.api.fields import NestedHyperlinkedIdentityField\nfrom lib.api.serializers import AplusModelSerializer, HtmlViewField\nfrom userprofile.api.serializers import UserBriefSerializer\nfrom ..models import Submission, SubmittedFile, BaseExercise\n\n\n__all__ = [\n    'ExerciseBriefSerializer',\n    'SubmissionBriefSerializer',\n    'SubmittedFileBriefSerializer',\n    'SubmitterStatsBriefSerializer',\n]\n\n\nclass ExerciseBriefSerializer(AplusModelSerializer):\n    url = NestedHyperlinkedIdentityField(\n        view_name='api:exercise-detail',\n        lookup_map='exercise.api.views.ExerciseViewSet',\n    )\n    display_name = serializers.CharField(source='__str__')\n\n    class Meta(AplusModelSerializer.Meta):\n        model = BaseExercise\n        fields = (\n            'url',\n            'html_url',\n            'display_name',\n        )\n\n\nclass SubmissionBriefSerializer(AplusModelSerializer):\n    #display_name = serializers.CharField(source='__str__')\n\n    class Meta(AplusModelSerializer.Meta):\n        model = Submission\n        fields = (\n            'submission_time',\n        )\n        extra_kwargs = {\n            'url': {\n                'view_name': 'api:submission-detail',\n                'lookup_map': 'exercise.api.views.SubmissionViewSet',\n            }\n        }\n\n\nclass SubmittedFileBriefSerializer(AplusModelSerializer):\n    #url = HtmlViewField()\n    url = NestedHyperlinkedIdentityField(\n        view_name='api:submission-files-detail',\n        lookup_map='exercise.api.views.SubmissionFileViewSet',\n    )\n\n    class Meta(AplusModelSerializer.Meta):\n        model = SubmittedFile\n        fields = (\n            'url',\n            'filename',\n            'param_name',\n        )\n\n\nclass SubmitterStatsBriefSerializer(UserBriefSerializer):\n    stats = serializers.SerializerMethodField()\n\n    def get_stats(self, profile):\n        return reverse(\n            'api:exercise-submitter_stats-detail',\n            kwargs={\n                'exercise_id': self.context['view'].exercise.id,\n                'user_id': profile.user.id,\n            },\n            request=self.context['request']\n        )\n\n    class Meta(UserBriefSerializer.Meta):\n        fields = UserBriefSerializer.Meta.fields + (\n            'stats',\n        )\n", "path": "exercise/api/serializers.py"}, {"content": "from rest_framework import serializers\n\nfrom lib.api.fields import NestedHyperlinkedIdentityField\nfrom lib.api.serializers import (\n    AlwaysListSerializer,\n    CompositeListSerializer,\n    AplusSerializerMeta,\n    AplusModelSerializerBase,\n)\nfrom course.api.serializers import CourseBriefSerializer\nfrom userprofile.api.serializers import UserBriefSerializer, UserListField\n\nfrom ..models import Submission\nfrom .serializers import (\n    ExerciseBriefSerializer,\n    SubmissionBriefSerializer,\n    SubmittedFileBriefSerializer,\n)\n\n\n__all__ = [\n    'ExerciseSerializer',\n    'ExerciseGraderSerializer',\n    'SubmissionSerializer',\n    'SubmissionGraderSerializer',\n]\n\n\nclass ExerciseSerializer(ExerciseBriefSerializer):\n    course = CourseBriefSerializer(source='course_instance')\n    post_url = serializers.SerializerMethodField()\n    exercise_info = serializers.JSONField()\n    submissions = NestedHyperlinkedIdentityField(\n        view_name='api:exercise-submissions-list',\n        lookup_map='exercise.api.views.ExerciseViewSet',\n    )\n    my_submissions = NestedHyperlinkedIdentityField(\n        view_name='api:exercise-submissions-detail',\n        lookup_map={\n            'exercise_id': 'id',\n            'user_id': lambda o=None: 'me',\n        },\n    )\n    my_stats = NestedHyperlinkedIdentityField(\n        view_name='api:exercise-submitter_stats-detail',\n        lookup_map={\n            'exercise_id': 'id',\n            'user_id': lambda o=None: 'me',\n        },\n    )\n\n    def get_post_url(self, obj):\n        # FIXME: obj should implement .get_post_url() and that should be used here\n        if obj.is_submittable:\n            request = self.context['request']\n            url = obj.get_url(\"exercise\")\n            return request.build_absolute_uri(url)\n        return None\n\n    class Meta(ExerciseBriefSerializer.Meta):\n        fields = (\n            'name',\n            'course',\n            'is_submittable',\n            'post_url',\n            'max_points',\n            'max_submissions',\n            'exercise_info',\n            'templates',\n            'submissions',\n            'my_submissions',\n            'my_stats',\n        )\n\n\nclass ExerciseGraderSerializer(AplusModelSerializerBase):\n    url = NestedHyperlinkedIdentityField(\n        view_name='api:exercise-grader',\n        lookup_map='exercise.api.views.ExerciseViewSet',\n    )\n    exercise = ExerciseBriefSerializer(source='*')\n\n    class Meta(AplusSerializerMeta):\n        model = Submission\n        fields = (\n            'url',\n            'exercise',\n        )\n\n\nclass SubmitterLinks(AlwaysListSerializer, UserBriefSerializer):\n    pass\n\n\nclass SubmittedFileLinks(AlwaysListSerializer, SubmittedFileBriefSerializer):\n    pass\n\n\nclass SubmissionSerializer(SubmissionBriefSerializer):\n    exercise = ExerciseBriefSerializer()\n    submitters = SubmitterLinks()\n    submission_data = serializers.JSONField()\n    files = SubmittedFileLinks()\n    grader = UserBriefSerializer()\n    grading_data = serializers.JSONField()\n\n    class Meta(SubmissionBriefSerializer.Meta):\n        fields = (\n            'html_url',\n            'exercise',\n            'submitters',\n            'submission_data',\n            'files',\n            'status',\n            'grade',\n            'late_penalty_applied',\n            'grading_time',\n            'grader',\n            'feedback',\n            'assistant_feedback',\n            'grading_data',\n        )\n\n\nclass SubmissionInGraderSerializer(SubmissionBriefSerializer):\n    class Meta(SubmissionBriefSerializer.Meta):\n        fields = (\n            'html_url',\n        )\n\n\nclass SubmissionGraderSerializer(AplusModelSerializerBase):\n    url = NestedHyperlinkedIdentityField(\n        view_name='api:submission-grader',\n        lookup_map='exercise.api.views.SubmissionViewSet',\n    )\n    submission = SubmissionInGraderSerializer(source='*')\n    exercise = ExerciseBriefSerializer()\n\n    class Meta(AplusSerializerMeta):\n        model = Submission\n        fields = (\n            'url',\n            'submission',\n            'exercise',\n            'grading_data',\n            'is_graded',\n        )\n", "path": "exercise/api/full_serializers.py"}], "after_files": [{"content": "from rest_framework import serializers\nfrom rest_framework.reverse import reverse\n\nfrom lib.api.fields import NestedHyperlinkedIdentityField\nfrom lib.api.serializers import AplusModelSerializer, HtmlViewField\nfrom userprofile.api.serializers import UserBriefSerializer\nfrom ..models import Submission, SubmittedFile, BaseExercise\n\n\n__all__ = [\n    'ExerciseBriefSerializer',\n    'SubmissionBriefSerializer',\n    'SubmittedFileBriefSerializer',\n    'SubmitterStatsBriefSerializer',\n]\n\n\nclass ExerciseBriefSerializer(AplusModelSerializer):\n    url = NestedHyperlinkedIdentityField(\n        view_name='api:exercise-detail',\n        lookup_map='exercise.api.views.ExerciseViewSet',\n    )\n    display_name = serializers.CharField(source='__str__')\n\n    class Meta(AplusModelSerializer.Meta):\n        model = BaseExercise\n        fields = (\n            'url',\n            'html_url',\n            'display_name',\n            'max_points',\n            'max_submissions',\n        )\n\n\nclass SubmissionBriefSerializer(AplusModelSerializer):\n    #display_name = serializers.CharField(source='__str__')\n\n    class Meta(AplusModelSerializer.Meta):\n        model = Submission\n        fields = (\n            'submission_time',\n        )\n        extra_kwargs = {\n            'url': {\n                'view_name': 'api:submission-detail',\n                'lookup_map': 'exercise.api.views.SubmissionViewSet',\n            }\n        }\n\n\nclass SubmittedFileBriefSerializer(AplusModelSerializer):\n    #url = HtmlViewField()\n    url = NestedHyperlinkedIdentityField(\n        view_name='api:submission-files-detail',\n        lookup_map='exercise.api.views.SubmissionFileViewSet',\n    )\n\n    class Meta(AplusModelSerializer.Meta):\n        model = SubmittedFile\n        fields = (\n            'url',\n            'filename',\n            'param_name',\n        )\n\n\nclass SubmitterStatsBriefSerializer(UserBriefSerializer):\n    stats = serializers.SerializerMethodField()\n\n    def get_stats(self, profile):\n        return reverse(\n            'api:exercise-submitter_stats-detail',\n            kwargs={\n                'exercise_id': self.context['view'].exercise.id,\n                'user_id': profile.user.id,\n            },\n            request=self.context['request']\n        )\n\n    class Meta(UserBriefSerializer.Meta):\n        fields = UserBriefSerializer.Meta.fields + (\n            'stats',\n        )\n", "path": "exercise/api/serializers.py"}, {"content": "from rest_framework import serializers\n\nfrom lib.api.fields import NestedHyperlinkedIdentityField\nfrom lib.api.serializers import (\n    AlwaysListSerializer,\n    CompositeListSerializer,\n    AplusSerializerMeta,\n    AplusModelSerializerBase,\n)\nfrom course.api.serializers import CourseBriefSerializer\nfrom userprofile.api.serializers import UserBriefSerializer, UserListField\n\nfrom ..models import Submission\nfrom .serializers import (\n    ExerciseBriefSerializer,\n    SubmissionBriefSerializer,\n    SubmittedFileBriefSerializer,\n)\n\n\n__all__ = [\n    'ExerciseSerializer',\n    'ExerciseGraderSerializer',\n    'SubmissionSerializer',\n    'SubmissionGraderSerializer',\n]\n\n\nclass ExerciseSerializer(ExerciseBriefSerializer):\n    course = CourseBriefSerializer(source='course_instance')\n    post_url = serializers.SerializerMethodField()\n    exercise_info = serializers.JSONField()\n    submissions = NestedHyperlinkedIdentityField(\n        view_name='api:exercise-submissions-list',\n        lookup_map='exercise.api.views.ExerciseViewSet',\n    )\n    my_submissions = NestedHyperlinkedIdentityField(\n        view_name='api:exercise-submissions-detail',\n        lookup_map={\n            'exercise_id': 'id',\n            'user_id': lambda o=None: 'me',\n        },\n    )\n    my_stats = NestedHyperlinkedIdentityField(\n        view_name='api:exercise-submitter_stats-detail',\n        lookup_map={\n            'exercise_id': 'id',\n            'user_id': lambda o=None: 'me',\n        },\n    )\n\n    def get_post_url(self, obj):\n        # FIXME: obj should implement .get_post_url() and that should be used here\n        if obj.is_submittable:\n            request = self.context['request']\n            url = obj.get_url(\"exercise\")\n            return request.build_absolute_uri(url)\n        return None\n\n    class Meta(ExerciseBriefSerializer.Meta):\n        fields = (\n            'name',\n            'course',\n            'is_submittable',\n            'post_url',\n            'exercise_info',\n            'templates',\n            'submissions',\n            'my_submissions',\n            'my_stats',\n        )\n\n\nclass ExerciseGraderSerializer(AplusModelSerializerBase):\n    url = NestedHyperlinkedIdentityField(\n        view_name='api:exercise-grader',\n        lookup_map='exercise.api.views.ExerciseViewSet',\n    )\n    exercise = ExerciseBriefSerializer(source='*')\n\n    class Meta(AplusSerializerMeta):\n        model = Submission\n        fields = (\n            'url',\n            'exercise',\n        )\n\n\nclass SubmitterLinks(AlwaysListSerializer, UserBriefSerializer):\n    pass\n\n\nclass SubmittedFileLinks(AlwaysListSerializer, SubmittedFileBriefSerializer):\n    pass\n\n\nclass SubmissionSerializer(SubmissionBriefSerializer):\n    exercise = ExerciseBriefSerializer()\n    submitters = SubmitterLinks()\n    submission_data = serializers.JSONField()\n    files = SubmittedFileLinks()\n    grader = UserBriefSerializer()\n    grading_data = serializers.JSONField()\n\n    class Meta(SubmissionBriefSerializer.Meta):\n        fields = (\n            'html_url',\n            'exercise',\n            'submitters',\n            'submission_data',\n            'files',\n            'status',\n            'grade',\n            'late_penalty_applied',\n            'grading_time',\n            'grader',\n            'feedback',\n            'assistant_feedback',\n            'grading_data',\n        )\n\n\nclass SubmissionInGraderSerializer(SubmissionBriefSerializer):\n    class Meta(SubmissionBriefSerializer.Meta):\n        fields = (\n            'html_url',\n        )\n\n\nclass SubmissionGraderSerializer(AplusModelSerializerBase):\n    url = NestedHyperlinkedIdentityField(\n        view_name='api:submission-grader',\n        lookup_map='exercise.api.views.SubmissionViewSet',\n    )\n    submission = SubmissionInGraderSerializer(source='*')\n    exercise = ExerciseBriefSerializer()\n\n    class Meta(AplusSerializerMeta):\n        model = Submission\n        fields = (\n            'url',\n            'submission',\n            'exercise',\n            'grading_data',\n            'is_graded',\n        )\n", "path": "exercise/api/full_serializers.py"}]}