Skip to content

Commit

Permalink
Black
Browse files Browse the repository at this point in the history
  • Loading branch information
Clue88 committed Mar 28, 2024
1 parent ba90562 commit 4749c7d
Show file tree
Hide file tree
Showing 13 changed files with 410 additions and 137 deletions.
11 changes: 10 additions & 1 deletion backend/degree/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@
from django.urls import reverse
from django.utils.html import format_html

from degree.models import Degree, DegreePlan, DoubleCountRestriction, Rule, SatisfactionStatus, Fulfillment
from degree.models import (
Degree,
DegreePlan,
DoubleCountRestriction,
Rule,
SatisfactionStatus,
Fulfillment,
)


# Register your models here.
Expand All @@ -18,10 +25,12 @@ class RuleAdmin(admin.ModelAdmin):
admin.site.register(DegreePlan)
admin.site.register(SatisfactionStatus)


@admin.register(Fulfillment)
class FulfillmentAdmin(admin.ModelAdmin):
autocomplete_fields = ["rules"]


@admin.register(DoubleCountRestriction)
class DoubleCountRestrictionAdmin(admin.ModelAdmin):
autocomplete_fields = ["rule", "other_rule"]
Expand Down
318 changes: 267 additions & 51 deletions backend/degree/migrations/0001_initial.py

Large diffs are not rendered by default.

12 changes: 8 additions & 4 deletions backend/degree/migrations/0002_alter_degreeplan_degrees.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@
class Migration(migrations.Migration):

dependencies = [
('degree', '0001_initial'),
("degree", "0001_initial"),
]

operations = [
migrations.AlterField(
model_name='degreeplan',
name='degrees',
field=models.ManyToManyField(blank=True, help_text='The degrees this degree plan is associated with.', to='degree.Degree'),
model_name="degreeplan",
name="degrees",
field=models.ManyToManyField(
blank=True,
help_text="The degrees this degree plan is associated with.",
to="degree.Degree",
),
),
]
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
class Migration(migrations.Migration):

dependencies = [
('degree', '0002_alter_degreeplan_degrees'),
("degree", "0002_alter_degreeplan_degrees"),
]

operations = [
migrations.AlterUniqueTogether(
name='fulfillment',
unique_together={('degree_plan', 'full_code')},
name="fulfillment",
unique_together={("degree_plan", "full_code")},
),
]
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
class Migration(migrations.Migration):

dependencies = [
('degree', '0003_alter_fulfillment_unique_together'),
("degree", "0003_alter_fulfillment_unique_together"),
]

operations = [
migrations.RemoveField(
model_name='fulfillment',
name='historical_course',
model_name="fulfillment",
name="historical_course",
),
]
13 changes: 9 additions & 4 deletions backend/degree/migrations/0005_degree_credits.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@
class Migration(migrations.Migration):

dependencies = [
('degree', '0004_remove_fulfillment_historical_course'),
("degree", "0004_remove_fulfillment_historical_course"),
]

operations = [
migrations.AddField(
model_name='degree',
name='credits',
field=models.DecimalField(decimal_places=2, default=32, help_text='\nThe minimum number of CUs required for this degree.\n', max_digits=4),
model_name="degree",
name="credits",
field=models.DecimalField(
decimal_places=2,
default=32,
help_text="\nThe minimum number of CUs required for this degree.\n",
max_digits=4,
),
preserve_default=False,
),
]
35 changes: 28 additions & 7 deletions backend/degree/migrations/0006_auto_20240229_1903.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,41 @@ class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('degree', '0005_degree_credits'),
("degree", "0005_degree_credits"),
]

operations = [
migrations.CreateModel(
name='DockedCourse',
name="DockedCourse",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('full_code', models.CharField(blank=True, help_text='The dash-joined department and code of the course, e.g., `CIS-120`', max_length=16)),
('person', models.ForeignKey(help_text='The user the docked course belongs to.', on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
(
"id",
models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
(
"full_code",
models.CharField(
blank=True,
help_text="The dash-joined department and code of the course, e.g., `CIS-120`",
max_length=16,
),
),
(
"person",
models.ForeignKey(
help_text="The user the docked course belongs to.",
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
),
),
],
),
migrations.AddConstraint(
model_name='dockedcourse',
constraint=models.UniqueConstraint(fields=('person', 'full_code'), name='unique docked course'),
model_name="dockedcourse",
constraint=models.UniqueConstraint(
fields=("person", "full_code"), name="unique docked course"
),
),
]
13 changes: 9 additions & 4 deletions backend/degree/migrations/0007_alter_dockedcourse_full_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@
class Migration(migrations.Migration):

dependencies = [
('degree', '0006_auto_20240229_1903'),
("degree", "0006_auto_20240229_1903"),
]

operations = [
migrations.AlterField(
model_name='dockedcourse',
name='full_code',
field=models.CharField(blank=True, db_index=True, help_text='The dash-joined department and code of the course, e.g., `CIS-120`', max_length=16),
model_name="dockedcourse",
name="full_code",
field=models.CharField(
blank=True,
db_index=True,
help_text="The dash-joined department and code of the course, e.g., `CIS-120`",
max_length=16,
),
),
]
44 changes: 31 additions & 13 deletions backend/degree/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,23 @@

from courses.models import Course
from courses.serializers import CourseListSerializer, CourseDetailSerializer
from degree.models import Degree, DegreePlan, DoubleCountRestriction, Fulfillment, Rule, DockedCourse
from degree.models import (
Degree,
DegreePlan,
DoubleCountRestriction,
Fulfillment,
Rule,
DockedCourse,
)
from courses.util import get_current_semester


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


class SimpleCourseSerializer(serializers.ModelSerializer):
id = serializers.ReadOnlyField(
source="full_code",
Expand All @@ -24,19 +33,19 @@ class SimpleCourseSerializer(serializers.ModelSerializer):
)

course_quality = serializers.DecimalField(
max_digits=4, decimal_places=3, read_only=True, help_text='course_quality_help'
max_digits=4, decimal_places=3, read_only=True, help_text="course_quality_help"
)
difficulty = serializers.DecimalField(
max_digits=4, decimal_places=3, read_only=True, help_text='difficulty_help'
max_digits=4, decimal_places=3, read_only=True, help_text="difficulty_help"
)
instructor_quality = serializers.DecimalField(
max_digits=4,
decimal_places=3,
read_only=True,
help_text='instructor_quality_help',
help_text="instructor_quality_help",
)
work_required = serializers.DecimalField(
max_digits=4, decimal_places=3, read_only=True, help_text='work_required_help'
max_digits=4, decimal_places=3, read_only=True, help_text="work_required_help"
)

class Meta:
Expand All @@ -53,13 +62,14 @@ class Meta:
]
read_only_fields = fields


class RuleSerializer(serializers.ModelSerializer):
q_json = serializers.ReadOnlyField(help_text="JSON representation of the q object")

class Meta:
model = Rule
fields = "__all__"

def to_representation(self, instance):
data = super(RuleSerializer, self).to_representation(instance)
data.q = ""
Expand Down Expand Up @@ -89,14 +99,23 @@ class Meta:

class FulfillmentSerializer(serializers.ModelSerializer):
course = serializers.SerializerMethodField()

def get_course(self, obj):
course = Course.with_reviews.filter(full_code=obj.full_code, semester__lte=get_current_semester()).order_by("-semester").first()
course = (
Course.with_reviews.filter(
full_code=obj.full_code, semester__lte=get_current_semester()
)
.order_by("-semester")
.first()
)
if course is not None:
return SimpleCourseSerializer(course).data
return None

# TODO: add a get_queryset method to only allow rules from the degree plan
rules = serializers.PrimaryKeyRelatedField(many=True, queryset=Rule.objects.all(), required=False)
rules = serializers.PrimaryKeyRelatedField(
many=True, queryset=Rule.objects.all(), required=False
)

def to_internal_value(self, data):
data = data.copy()
Expand Down Expand Up @@ -149,7 +168,7 @@ class DegreePlanListSerializer(serializers.ModelSerializer):

# degree_ids = serializers.PrimaryKeyRelatedField(
# many=True,
# required=False,
# required=False,
# source="degrees",
# queryset=Degree.objects.all(),
# help_text="The degree_id this degree plan belongs to.",
Expand All @@ -167,8 +186,7 @@ class DegreePlanDetailSerializer(serializers.ModelSerializer):
# help_text="The courses used to fulfill degree plan.",
# )
degrees = DegreeDetailSerializer(
many=True,
help_text="The degrees belonging to this degree plan"
many=True, help_text="The degrees belonging to this degree plan"
)

person = serializers.HiddenField(default=serializers.CurrentUserDefault())
Expand All @@ -184,4 +202,4 @@ class DockedCourseSerializer(serializers.ModelSerializer):

class Meta:
model = DockedCourse
fields = "__all__"
fields = "__all__"
12 changes: 10 additions & 2 deletions backend/degree/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,22 @@
from rest_framework.routers import DefaultRouter
from rest_framework_nested.routers import NestedDefaultRouter

from degree.views import DegreePlanViewset, DegreeViewset, FulfillmentViewSet, courses_for_rule, DockedCourseViewset
from degree.views import (
DegreePlanViewset,
DegreeViewset,
FulfillmentViewSet,
courses_for_rule,
DockedCourseViewset,
)


router = DefaultRouter(trailing_slash=False)
router.register(r"degreeplans", DegreePlanViewset, basename="degreeplan")
router.register(r"degrees", DegreeViewset, basename="degree")
router.register(r"docked", DockedCourseViewset)
fulfillments_router = NestedDefaultRouter(router, r"degreeplans", lookup="degreeplan", trailing_slash=False)
fulfillments_router = NestedDefaultRouter(
router, r"degreeplans", lookup="degreeplan", trailing_slash=False
)
fulfillments_router.register(r"fulfillments", FulfillmentViewSet, basename="degreeplan-fulfillment")

urlpatterns = [
Expand Down
33 changes: 9 additions & 24 deletions backend/degree/utils/model_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def q(self, n):
(clause,) = n
return clause


class JSONTransformer(Transformer):
"""
This class transforms the Abstract Syntax Tree (AST) generated by the parser
Expand All @@ -83,36 +84,20 @@ def array(self, n):
def and_clause(self, clauses):
if len(clauses) == 1:
return clauses[0]
return {
'type': 'AND',
'clauses': clauses
}
return {"type": "AND", "clauses": clauses}

def or_clause(self, clauses):
return {
'type': 'OR',
'clauses': clauses
}
return {"type": "OR", "clauses": clauses}

def not_clause(self, clauses):
return {
'type': 'NOT',
'clauses': clauses
}
return {"type": "NOT", "clauses": clauses}

def condition(self, n):
key, value = n
if key == 'full_code':
return {
'type': 'COURSE',
'full_code': value
}
else:
return {
'type': 'LEAF',
'key': key,
'value': value
}
if key == "full_code":
return {"type": "COURSE", "full_code": value}
else:
return {"type": "LEAF", "key": key, "value": value}

def string(self, s):
(s,) = s
Expand Down Expand Up @@ -183,4 +168,4 @@ def q(self, n):
start="q",
transformer=JSONTransformer(),
parser="lalr",
)
)
2 changes: 1 addition & 1 deletion backend/degree/utils/parse_degreeworks.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ def parse_degreeworks(json: dict, degree: Degree) -> list[Rule] | None:
# check if this requirement actually has anything in it
if degree_req == rules[-1] and not degree_req.q:
rules.pop()

# special case for Additional majors
if degree.credits is None:
logging.error("Skipped degree because it has not total credits requirement.")
Expand Down
Loading

0 comments on commit 4749c7d

Please sign in to comment.