* feat: log exceptions for fall-through exceptions * chore: remove unused XBlock handler * refactor: log errors for XBlock handlers * refactor: log bad ORA locations * feat: log lock/grade contest errors * feat: log output data for ESG endpoints * feat: unpack extra error info from more endpoints
120 lines
3.2 KiB
Python
120 lines
3.2 KiB
Python
""" Error codes and exceptions for ESG """
|
|
from rest_framework import serializers
|
|
from rest_framework.response import Response
|
|
|
|
from lms.djangoapps.ora_staff_grader.constants import (
|
|
ERR_BAD_ORA_LOCATION,
|
|
ERR_GRADE_CONTESTED,
|
|
ERR_INTERNAL,
|
|
ERR_LOCK_CONTESTED,
|
|
ERR_MISSING_PARAM,
|
|
ERR_UNKNOWN,
|
|
)
|
|
|
|
|
|
class ExceptionWithContext(Exception):
|
|
"""An exception with optional context dict to be supplied in serialized result"""
|
|
|
|
def __init__(self, context=None):
|
|
super().__init__(self)
|
|
self.context = context
|
|
|
|
|
|
class XBlockInternalError(ExceptionWithContext):
|
|
"""Errors from XBlock handlers"""
|
|
|
|
def __str__(self):
|
|
return str(self.context)
|
|
|
|
|
|
class LockContestedError(ExceptionWithContext):
|
|
"""Signal for trying to operate on a lock owned by someone else"""
|
|
|
|
|
|
class ErrorSerializer(serializers.Serializer):
|
|
"""Returns error code and unpacks additional context, returns unknown error code if not supplied"""
|
|
|
|
error = serializers.CharField(default=ERR_UNKNOWN)
|
|
|
|
def to_representation(self, instance):
|
|
"""Override to unpack context alongside error code"""
|
|
output = super().to_representation(instance)
|
|
|
|
if self.context:
|
|
for key, value in self.context.items():
|
|
output[key] = value
|
|
|
|
return output
|
|
|
|
|
|
class StaffGraderErrorResponse(Response):
|
|
"""An HTTP error response that returns serialized error data with additional provided context"""
|
|
|
|
status = 500
|
|
err_code = ERR_UNKNOWN
|
|
|
|
def __init__(self, context=None):
|
|
# Unpack provided content into error structure
|
|
content = ErrorSerializer({"error": self.err_code}, context=context).data
|
|
super().__init__(content, status=self.status)
|
|
|
|
|
|
class BadOraLocationResponse(StaffGraderErrorResponse):
|
|
"""
|
|
Error response for when the requested ORA_LOCATION could not be found in a course.
|
|
Returns an HTTP 400 with error code.
|
|
"""
|
|
|
|
status = 400
|
|
err_code = ERR_BAD_ORA_LOCATION
|
|
|
|
|
|
class MissingParamResponse(StaffGraderErrorResponse):
|
|
"""
|
|
Error response for when a request is missing a required param/body.
|
|
Returns an HTTP 400 with error code.
|
|
"""
|
|
|
|
status = 400
|
|
err_code = ERR_MISSING_PARAM
|
|
|
|
|
|
class LockContestedResponse(StaffGraderErrorResponse):
|
|
"""
|
|
Error response for when a user tries to operate on a submission that they do not have a lock for.
|
|
Returns an HTTP 409 with error code and updated lock status.
|
|
"""
|
|
|
|
status = 409
|
|
err_code = ERR_LOCK_CONTESTED
|
|
|
|
|
|
class GradeContestedResponse(StaffGraderErrorResponse):
|
|
"""
|
|
Error response for when a user tries to operate on a submission that they do not have a lock for.
|
|
Returns an HTTP 409 with error code and updated submission status.
|
|
"""
|
|
|
|
status = 409
|
|
err_code = ERR_GRADE_CONTESTED
|
|
|
|
|
|
class InternalErrorResponse(StaffGraderErrorResponse):
|
|
"""
|
|
Generic error response for an issue in an XBlock handler.
|
|
Returns an HTTP 500 with internal error code.
|
|
"""
|
|
|
|
status = 500
|
|
err_code = ERR_INTERNAL
|
|
|
|
|
|
class UnknownErrorResponse(StaffGraderErrorResponse):
|
|
"""
|
|
Blanket exception for when something strange breaks
|
|
Returns an HTTP 500 with generic error code.
|
|
"""
|
|
|
|
status = 500
|
|
err_code = ERR_UNKNOWN
|