Skip to content

Commit

Permalink
linting
Browse files Browse the repository at this point in the history
  • Loading branch information
AaDalal committed Feb 5, 2024
1 parent e1c74e2 commit 5a20e6c
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 330 deletions.
2 changes: 1 addition & 1 deletion backend/degree/admin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.contrib import admin

from degree.models import Degree, Rule, DegreePlan, SatisfactionStatus, DoubleCountRestriction
from degree.models import Degree, DegreePlan, DoubleCountRestriction, Rule, SatisfactionStatus


# Register your models here.
Expand Down
20 changes: 12 additions & 8 deletions backend/degree/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
from django.db import models
from django.db.models import Count, DecimalField, Q, Sum
from django.db.models.functions import Coalesce
from django.db.models.signals import m2m_changed
from django.utils import timezone

from courses.models import Course
from degree.utils.model_utils import q_object_parser
from django.db.models.signals import m2m_changed


program_choices = [
Expand Down Expand Up @@ -203,7 +203,7 @@ def evaluate(self, full_codes: Iterable[str]) -> bool:
if self.num is not None and count < self.num:
return False
return True

def get_q_object(self) -> Q | None:
if not self.q:
return None
Expand Down Expand Up @@ -316,7 +316,8 @@ class Fulfillment(models.Model):
related_name="+",
help_text=dedent(
"""
The last offering of the course with the full code, or null if there is no such historical course.
The last offering of the course with the full code, or null if
there is no such historical course.
"""
),
)
Expand Down Expand Up @@ -363,28 +364,31 @@ def save(self, *args, **kwargs):
)
if course is not None:
course = course.topic.most_recent

self.historical_course = course

super().save(*args, **kwargs)


def update_satisfaction_statuses(sender, instance, action, pk_set, **kwargs):
"""
This function updates the SatisfactionStatuses associated with a DegreePlan when the rules
associated with a Fulfillment change.
"""
if action == "pre_clear" or action == "pre_remove":
instance.degree_plan.satisfactions.filter(rule__in=pk_set).delete()
return
return

if action == "post_add" or action == "post_remove" or action == "post_clear":
degree_plan = instance.degree_plan
for rule in degree_plan.degree.rules.all():
status, _ = SatisfactionStatus.objects.get_or_create(
degree_plan=degree_plan, rule=rule
status, _ = SatisfactionStatus.objects.get_or_create(degree_plan=degree_plan, rule=rule)
status.satisfied = rule.evaluate(
[fulfillment.full_code for fulfillment in degree_plan.fulfillments.all()]
)
status.satisfied = rule.evaluate([fulfillment.full_code for fulfillment in degree_plan.fulfillments.all()])
status.save()


m2m_changed.connect(update_satisfaction_statuses, sender=Fulfillment.rules.through)


Expand Down
18 changes: 11 additions & 7 deletions backend/degree/serializers.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
from textwrap import dedent

from django.db.models import Q
from rest_framework import serializers
from rest_framework.fields import empty

from courses.models import Course
from courses.serializers import CourseListSerializer
from degree.models import Degree, DegreePlan, DoubleCountRestriction, Fulfillment, Rule
from django.db.models import Q


class DegreeListSerializer(serializers.ModelSerializer):
class Meta:
model = Degree
fields = "__all__"


class RuleSerializer(serializers.ModelSerializer):
class Meta:
model = Rule
fields = "__all__"


# Allow recursive serialization of rules
RuleSerializer._declared_fields["rules"] = RuleSerializer(
many=True, read_only=True, source="children"
Expand All @@ -39,6 +42,7 @@ class Meta:
fields = "__all__"
read_only_fields = "__all__"


class FulfillmentSerializer(serializers.ModelSerializer):
course = CourseListSerializer(
read_only=True,
Expand All @@ -48,7 +52,7 @@ class FulfillmentSerializer(serializers.ModelSerializer):
The details of the fulfilling course. This is the most recent course with the full code,
or null if no course exists with the full code.
"""
)
),
)
# TODO: add a get_queryset method to only allow rules from the degree plan
rules = serializers.PrimaryKeyRelatedField(many=True, queryset=Rule.objects.all())
Expand All @@ -64,12 +68,12 @@ class Meta:

def validate(self, data):
data = super().validate(data)
rules = data.get("rules") # for patch requests without a rules field
rules = data.get("rules") # for patch requests without a rules field
full_code = data.get("full_code")
degree_plan = data.get("degree_plan")

if rules is None and full_code is None:
return data # Nothing to validate
return data # Nothing to validate
if rules is None:
rules = self.instance.rules.all()
if full_code is None:
Expand All @@ -83,7 +87,7 @@ def validate(self, data):
raise serializers.ValidationError(
f"Course {full_code} does not satisfy rule {rule.id}"
)

# Check for double count restrictions
double_count_restrictions = DoubleCountRestriction.objects.filter(
Q(rule__in=rules) | Q(other_rule__in=rules)
Expand All @@ -93,7 +97,7 @@ def validate(self, data):
raise serializers.ValidationError(
f"Double count restriction {restriction.id} violated"
)

return data


Expand Down
6 changes: 4 additions & 2 deletions backend/degree/urls.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from rest_framework_nested.routers import NestedDefaultRouter

from degree.views import (
DegreeDetail,
DegreeList,
Expand All @@ -9,10 +10,11 @@
courses_for_rule,
)


router = DefaultRouter()
router.register(r"degreeplans", DegreePlanViewset, basename="degreeplan")
fulfillments_router = NestedDefaultRouter(router, r'degreeplans', lookup='degreeplan')
fulfillments_router.register(r'fulfillments', FulfillmentViewSet, basename='degreeplan-fulfillment')
fulfillments_router = NestedDefaultRouter(router, r"degreeplans", lookup="degreeplan")
fulfillments_router.register(r"fulfillments", FulfillmentViewSet, basename="degreeplan-fulfillment")

urlpatterns = [
path("degrees/", DegreeList.as_view(), name="degree-list"),
Expand Down
4 changes: 2 additions & 2 deletions backend/degree/views.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from django.core.exceptions import ObjectDoesNotExist
from django_auto_prefetching import AutoPrefetchViewSetMixin
from rest_framework import generics, mixins, status, viewsets
from rest_framework import generics, status, viewsets
from rest_framework.decorators import api_view
from rest_framework.exceptions import ValidationError
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.exceptions import ValidationError

from courses.models import Course
from courses.serializers import CourseListSerializer
Expand Down
Loading

0 comments on commit 5a20e6c

Please sign in to comment.