Skip to content

Commit

Permalink
Merge pull request #25 from helxplatform/create-submission-nb
Browse files Browse the repository at this point in the history
Upload student notebook alongside submission API call
  • Loading branch information
Hoid authored Oct 16, 2024
2 parents 2e6e15e + 0884f5c commit dbe6eeb
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 19 deletions.
22 changes: 9 additions & 13 deletions eduhelx_jupyterlab_student/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,39 +247,35 @@ async def post(self):
}))
return

current_assignment_path = student_repo.get_assignment_path(student_repo.current_assignment)
student_notebook_path = current_assignment_path / student_repo.current_assignment["student_notebook_path"]

student_notebook_path = student_repo.current_assignment_path / student_repo.current_assignment["student_notebook_path"]
if not student_notebook_path.exists():
self.set_status(400)
self.finish(json.dumps({
"message": "Student notebook file does not exist"
"message": "Student notebook does not exist"
}))
return
student_notebook_content = student_notebook_path.read_text()

student_notebook_content = student_notebook_path.read()

rollback_id = get_head_commit_id(path=student_repo.repo_root)
stage_files(".", path=current_assignment_path)
stage_files(".", path=student_repo.current_assignment_path)

try:
commit_id = commit(
submission_summary,
submission_description if submission_description else None,
path=current_assignment_path
path=student_repo.current_assignment_path
)
except Exception as e:
# If the commit fails then unstage the assignment files.
git_reset(".", path=current_assignment_path)
git_reset(".", path=student_repo.current_assignment_path)
self.set_status(500)
self.finish(str(e))
return

try:
await self.api.create_submission(
student_repo.current_assignment["id"],
commit_id=commit_id,
student_notebook_content=student_notebook_content
commit_id,
student_notebook_content
)
except Exception as e:
# If the submission fails create in the API, rollback the local commit to the previous head.
Expand All @@ -292,7 +288,7 @@ async def post(self):
# so that we don't push the stages changes without actually creating a submission for the user
# (which would be very misleading)
try:
push(StudentClassRepo.ORIGIN_REMOTE_NAME, StudentClassRepo.MAIN_BRANCH_NAME, path=current_assignment_path)
push(StudentClassRepo.ORIGIN_REMOTE_NAME, StudentClassRepo.MAIN_BRANCH_NAME, path=student_repo.current_assignment_path)
self.finish()
except Exception as e:
# Need to rollback the commit if push failed too.
Expand Down
28 changes: 25 additions & 3 deletions eduhelx_jupyterlab_student/student_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
class NotStudentClassRepositoryException(Exception):
pass

class NotInAnAssignmentException(Exception):
pass


""" Note: this class is naive to the fixed repo path. It is designed for
relative interaction with class repository filepaths WHILE inside the repository. """
Expand All @@ -28,18 +31,21 @@ def __init__(self, course, assignments, current_path):

self.repo_root = self._compute_repo_root(self.course["name"], self.current_path)
self.current_assignment = self._compute_current_assignment(self.assignments, self.repo_root, self.current_path)

@property
def current_assignment_path(self) -> Path | None:
if self.current_assignment is None: return None
return self.get_assignment_path(self.current_assignment)

def get_assignment_path(self, assignment):
return os.path.join(self.repo_root, assignment["directory_path"])
return self.repo_root / assignment["directory_path"]

def get_protected_file_paths(self, assignment) -> list[Path]:
files = []
for glob_pattern in assignment["protected_files"]:
files += self.get_assignment_path(assignment).glob(glob_pattern)
return files



@classmethod
def _compute_repo_root(cls, course_name, current_path: str | None = None):
""" Validates that user is in the repository root if current_path is provided """
Expand All @@ -65,3 +71,19 @@ def _compute_current_assignment(assignments, repo_root, current_path):
break

return current_assignment

@classmethod
def from_assignment_no_path(cls, course, assignments, assignment_id: int):
try:
assignment = [a for a in assignments if a["id"] == assignment_id][0]
except IndexError:
raise NotInAnAssignmentException

repo_root = cls._compute_repo_root(course["name"]).resolve()
assignment_path = repo_root / assignment["directory_path"]

return cls(
course=course,
assignments=assignments,
current_path=assignment_path
)
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,14 @@ const AssignmentsBucket = ({
}: AssignmentsBucketProps) => {
const [expanded, setExpanded] = useState<boolean>(defaultExpanded)

const assignmentsSource = useMemo(() => (
assignments?.sort((a, b) => (a.adjustedDueDate?.getTime() ?? 0) - (b.adjustedDueDate?.getTime() ?? 0))
), [assignments])
const assignmentsSource = useMemo(() => assignments?.sort((a, b) => {
const aDue = a.adjustedDueDate?.getTime() ?? Infinity
const bDue = b.adjustedDueDate?.getTime() ?? Infinity
// Sort by date, or name if same date.
if (aDue > bDue) return 1
if (aDue < bDue) return -1
return a.name.localeCompare(b.name, undefined, { numeric: true })
}), [assignments])

const isEmpty = useMemo(() => !assignmentsSource || assignmentsSource.length === 0, [assignmentsSource])

Expand Down

0 comments on commit dbe6eeb

Please sign in to comment.