Skip to content

Commit

Permalink
Merge pull request #692 from eecs-autograder/revert-extended-due-date…
Browse files Browse the repository at this point in the history
…-changes

Revert to before #687 was merged
  • Loading branch information
james-perretta authored Sep 19, 2024
2 parents 5627a33 + 3e06891 commit 3a9045f
Show file tree
Hide file tree
Showing 14 changed files with 52 additions and 480 deletions.
37 changes: 0 additions & 37 deletions autograder/core/migrations/0108_group_soft_extended_due_date.py

This file was deleted.

This file was deleted.

14 changes: 0 additions & 14 deletions autograder/core/migrations/0110_merge_20240910_1659.py

This file was deleted.

65 changes: 4 additions & 61 deletions autograder/core/models/group/group.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from __future__ import annotations

import os
from typing import Any, Dict, Iterable, List, Optional, cast
from datetime import datetime
from typing import Any, Dict, Iterable, List, cast
import zoneinfo

import django.contrib.postgres.fields as pg_fields
Expand Down Expand Up @@ -50,9 +49,9 @@ def validate_and_create( # type: ignore
member_names = [
user.username for user in sorted(members, key=lambda user: user.username)]
group = self.model(_member_names=member_names, **kwargs)
group.full_clean()
group.save()
group.members.add(*members)
group.full_clean()
return group


Expand Down Expand Up @@ -94,40 +93,13 @@ def member_names(self) -> List[str]:
project = models.ForeignKey(Project, related_name="groups",
on_delete=models.CASCADE)

@property
def extended_due_date(self) -> Optional[datetime]:
"""
DEPRECATED. For API legacy use, you can continue to use this field as usual.
Do NOT mix usage of this field and the two new "hard_extended_due_date" and
"soft_extended_due_date" fields.
When this field is set, it indicates that members of this submission group can
submit until this specified date, overriding the project closing time.
Default value: None
"""
return self.soft_extended_due_date

@extended_due_date.setter
def extended_due_date(self, value: Optional[datetime]) -> None:
self.soft_extended_due_date = value
self.hard_extended_due_date = value

hard_extended_due_date = models.DateTimeField(
extended_due_date = models.DateTimeField(
null=True, default=None, blank=True,
help_text="""When this field is set, it indicates that members
of this submission group can submit until this specified
date, overriding the project closing time.
Default value: None""")

soft_extended_due_date = models.DateTimeField(
null=True, default=None, blank=True,
help_text="""When this field is set, it indicates the extended due date
that is visible to members of the group. Members of the group will
still be able to submit after this date but before the
extended_due_date.
Default value: None""")

# Remove in version 5.0.0
old_bonus_submissions_remaining = models.IntegerField(
blank=True,
Expand Down Expand Up @@ -207,28 +179,6 @@ def _is_towards_limit(submission: Submission) -> bool:

return utils.count_if(self.submissions.all(), _is_towards_limit)

def clean(self) -> None:
super().clean()

try:
clean_soft, clean_hard = core_ut.clean_and_validate_soft_and_hard_deadlines(
self.soft_extended_due_date, self.hard_extended_due_date)
except core_ut.InvalidSoftDeadlineError:
raise ValidationError(
{'soft_extended_due_date': (
'Soft extended due date must be a valid date')})
except core_ut.InvalidHardDeadlineError:
raise ValidationError(
{'hard_extended_due_date': (
'Hard extended due date must be a valid date')})
except core_ut.HardDeadlineBeforeSoftDeadlineError:
raise ValidationError(
{'hard_extended_due_date': (
'Hard extended due date must not be before soft extended due date')})

self.soft_extended_due_date = clean_soft
self.hard_extended_due_date = clean_hard

def save(self, *args: Any, **kwargs: Any) -> None:
super().save(*args, **kwargs)

Expand Down Expand Up @@ -284,8 +234,6 @@ def validate_and_update( # type: ignore
SERIALIZABLE_FIELDS = (
'pk',
'project',
'hard_extended_due_date',
'soft_extended_due_date',
'extended_due_date',
'member_names',
'members',
Expand All @@ -302,12 +250,7 @@ def validate_and_update( # type: ignore
)
SERIALIZE_RELATED = ('members',)

EDITABLE_FIELDS = (
'extended_due_date',
'hard_extended_due_date',
'soft_extended_due_date',
'bonus_submissions_remaining'
)
EDITABLE_FIELDS = ('extended_due_date', 'bonus_submissions_remaining')

def to_dict(self) -> Dict[str, object]:
result = super().to_dict()
Expand Down
28 changes: 10 additions & 18 deletions autograder/core/models/project/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,24 +238,16 @@ def clean(self) -> None:
{'max_group_size': ('Maximum group size must be greater than '
'or equal to minimum group size')})

try:
clean_soft, clean_hard = core_ut.clean_and_validate_soft_and_hard_deadlines(
self.soft_closing_time, self.closing_time)
except core_ut.InvalidSoftDeadlineError:
raise exceptions.ValidationError(
{'soft_closing_time': (
'Soft closing time must be a valid date')})
except core_ut.InvalidHardDeadlineError:
raise exceptions.ValidationError(
{'closing_time': (
'Closing time must be a valid date')})
except core_ut.HardDeadlineBeforeSoftDeadlineError:
raise exceptions.ValidationError(
{'closing_time': (
'Closing time must not be before soft closing time')})

self.soft_closing_time = clean_soft
self.closing_time = clean_hard
if self.closing_time is not None:
self.closing_time = self.closing_time.replace(second=0, microsecond=0)
if self.soft_closing_time is not None:
self.soft_closing_time = self.soft_closing_time.replace(second=0, microsecond=0)

if self.closing_time is not None and self.soft_closing_time is not None:
if self.closing_time < self.soft_closing_time:
raise exceptions.ValidationError(
{'soft_closing_time': (
'Soft closing time must be before hard closing time')})

@property
def has_handgrading_rubric(self) -> bool:
Expand Down
76 changes: 3 additions & 73 deletions autograder/core/tests/test_models/test_group/test_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,7 @@ def test_valid_initialization_no_defaults(self):

group.refresh_from_db()

self.assertEqual(
group.extended_due_date,
extended_due_date.replace(second=0, microsecond=0))
self.assertEqual(group.extended_due_date, extended_due_date)
self.assertCountEqual(self.student_users, group.members.all())
self.assertEqual(self.project, group.project)

Expand Down Expand Up @@ -204,8 +202,6 @@ def test_serializable_fields(self):
'members',
'project',
'extended_due_date',
'soft_extended_due_date',
'hard_extended_due_date',

'bonus_submissions_remaining',

Expand All @@ -225,10 +221,8 @@ def test_serializable_fields(self):
self.assertIsInstance(serialized['members'][0], dict)

def test_editable_fields(self):
self.assertCountEqual(
['extended_due_date', 'soft_extended_due_date', 'hard_extended_due_date',
'bonus_submissions_remaining'],
ag_models.Group.get_editable_fields())
self.assertCountEqual(['extended_due_date', 'bonus_submissions_remaining'],
ag_models.Group.get_editable_fields())


class BonusSubmissionTokenCountTestCase(test_ut.UnitTestBase):
Expand Down Expand Up @@ -638,67 +632,3 @@ def test_exception_group_mix_of_student_and_staff(self):
ag_models.Group.objects.validate_and_create(
members=self.staff_users + self.student_users,
project=self.project)


class ExtendedDueDateBackwardsCompatabilityTestCase(_SetUp):
def test_extended_due_date_sets_hard_and_soft_extended_due_dates(self):
extended_due_date = timezone.now() + datetime.timedelta(days=1)
group = ag_models.Group.objects.validate_and_create(
members=self.student_users,
project=self.project,
extended_due_date=extended_due_date)

group.refresh_from_db()
self.assertEqual(
extended_due_date.replace(second=0, microsecond=0),
group.extended_due_date)
self.assertEqual(
extended_due_date.replace(second=0, microsecond=0),
group.soft_extended_due_date)
self.assertEqual(
extended_due_date.replace(second=0, microsecond=0),
group.hard_extended_due_date)

def test_getting_extended_due_date_reads_soft_extended_due_date(self):
soft_extended_due_date = timezone.now() + datetime.timedelta(days=1)
hard_extended_due_date = soft_extended_due_date + datetime.timedelta(days=1)
group = ag_models.Group.objects.validate_and_create(
members=self.student_users,
project=self.project,
soft_extended_due_date=soft_extended_due_date,
hard_extended_due_date=hard_extended_due_date)

self.assertEqual(
soft_extended_due_date.replace(second=0, microsecond=0),
group.extended_due_date)
self.assertEqual(
hard_extended_due_date.replace(second=0, microsecond=0),
group.hard_extended_due_date)


class HardAndSoftExtendedDueDateTestCase(_SetUp):
def test_valid_soft_extended_due_date_None_hard_extended_due_date_not_None(self):
hard_extended_due_date = timezone.now() + datetime.timedelta(days=1)
group = ag_models.Group.objects.validate_and_create(
members=self.student_users,
project=self.project,
hard_extended_due_date=hard_extended_due_date,
soft_extended_due_date=None)

group.refresh_from_db()
self.assertEqual(
hard_extended_due_date.replace(second=0, microsecond=0),
group.hard_extended_due_date)
self.assertIsNone(group.soft_extended_due_date)

def test_error_soft_extended_due_date_after_hard_extended_due_date(self):
hard_extended_due_date = timezone.now() + timezone.timedelta(minutes=5)
soft_extended_due_date = hard_extended_due_date + timezone.timedelta(minutes=5)

with self.assertRaises(exceptions.ValidationError) as cm:
ag_models.Group.objects.validate_and_create(
members=self.student_users,
project=self.project,
hard_extended_due_date=hard_extended_due_date,
soft_extended_due_date=soft_extended_due_date)
self.assertIn('hard_extended_due_date', cm.exception.message_dict)
17 changes: 0 additions & 17 deletions autograder/core/tests/test_models/test_project/test_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,26 +220,9 @@ def test_error_soft_closing_time_after_closing_time(self):
name='stove', course=self.course,
closing_time=closing_time,
soft_closing_time=soft_closing_time)
self.assertIn('closing_time', cm.exception.message_dict)

def test_error_soft_closing_time_not_a_date(self):
soft_closing_time = "foobar"
with self.assertRaises(exceptions.ValidationError) as cm:
ag_models.Project.objects.validate_and_create(
name='stove', course=self.course,
soft_closing_time=soft_closing_time)

self.assertIn('soft_closing_time', cm.exception.message_dict)

def test_error_closing_time_not_a_date(self):
closing_time = "foobar"
with self.assertRaises(exceptions.ValidationError) as cm:
ag_models.Project.objects.validate_and_create(
name='stove', course=self.course,
closing_time=closing_time)

self.assertIn('closing_time', cm.exception.message_dict)


class ProjectMiscErrorTestCase(UnitTestBase):
def setUp(self):
Expand Down
Loading

0 comments on commit 3a9045f

Please sign in to comment.