2022-10-07 12:12:18 +01:00
|
|
|
from sqlite3 import IntegrityError
|
2021-12-26 06:30:21 -05:00
|
|
|
from subprocess import CalledProcessError
|
2022-07-03 10:43:59 -04:00
|
|
|
from typing import Any, ClassVar, Optional
|
2022-03-13 13:33:19 -04:00
|
|
|
|
2021-12-26 06:30:21 -05:00
|
|
|
from rest_framework.response import Response
|
2022-10-07 12:12:18 +01:00
|
|
|
from rest_framework.status import HTTP_400_BAD_REQUEST, HTTP_500_INTERNAL_SERVER_ERROR
|
2021-12-26 06:30:21 -05:00
|
|
|
|
|
|
|
|
from rest_framework.views import exception_handler
|
|
|
|
|
|
2022-02-20 09:21:38 -05:00
|
|
|
|
2022-07-03 10:43:59 -04:00
|
|
|
def custom_exception_handler(exc: Exception, context: Any) -> Optional[Response]:
|
2021-12-26 06:30:21 -05:00
|
|
|
# Call REST framework's default exception handler first,
|
|
|
|
|
# to get the standard error response.
|
|
|
|
|
response = exception_handler(exc, context)
|
|
|
|
|
|
|
|
|
|
if isinstance(exc, SubprocessError):
|
|
|
|
|
response = Response(
|
2022-02-20 09:21:38 -05:00
|
|
|
data={
|
2021-12-26 06:30:21 -05:00
|
|
|
"code": exc.SUBPROCESS_NAME,
|
|
|
|
|
"detail": exc.msg,
|
2022-02-20 09:21:38 -05:00
|
|
|
},
|
|
|
|
|
status=HTTP_400_BAD_REQUEST,
|
2021-12-26 06:30:21 -05:00
|
|
|
)
|
2022-10-07 12:12:18 +01:00
|
|
|
elif isinstance(exc, AssertionError) or isinstance(exc, IntegrityError):
|
|
|
|
|
response = Response(
|
|
|
|
|
data={
|
|
|
|
|
"detail": str(exc),
|
|
|
|
|
},
|
|
|
|
|
status=HTTP_500_INTERNAL_SERVER_ERROR,
|
|
|
|
|
)
|
2021-12-26 06:30:21 -05:00
|
|
|
|
2023-10-27 23:40:59 +09:00
|
|
|
if response is not None and isinstance(response.data, dict):
|
2022-02-22 19:37:45 +00:00
|
|
|
response.data["kind"] = exc.__class__.__name__
|
|
|
|
|
|
2021-12-26 06:30:21 -05:00
|
|
|
return response
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SubprocessError(Exception):
|
|
|
|
|
SUBPROCESS_NAME: ClassVar[str] = "Subprocess"
|
|
|
|
|
msg: str
|
|
|
|
|
stdout: str
|
|
|
|
|
stderr: str
|
|
|
|
|
|
|
|
|
|
def __init__(self, message: str):
|
|
|
|
|
self.msg = f"{self.SUBPROCESS_NAME} error: {message}"
|
|
|
|
|
|
|
|
|
|
super().__init__(self.msg)
|
|
|
|
|
self.stdout = ""
|
|
|
|
|
self.stderr = ""
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def from_process_error(ex: CalledProcessError) -> "SubprocessError":
|
|
|
|
|
error = SubprocessError(f"{ex.cmd[0]} returned {ex.returncode}")
|
|
|
|
|
error.stdout = ex.stdout
|
|
|
|
|
error.stderr = ex.stderr
|
2022-08-12 01:51:10 +09:00
|
|
|
error.msg = ex.stdout
|
2021-12-26 06:30:21 -05:00
|
|
|
return error
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DiffError(SubprocessError):
|
|
|
|
|
SUBPROCESS_NAME: ClassVar[str] = "Diff"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ObjdumpError(SubprocessError):
|
|
|
|
|
SUBPROCESS_NAME: ClassVar[str] = "objdump"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NmError(SubprocessError):
|
|
|
|
|
SUBPROCESS_NAME: ClassVar[str] = "nm"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CompilationError(SubprocessError):
|
|
|
|
|
SUBPROCESS_NAME: ClassVar[str] = "Compiler"
|
|
|
|
|
|
|
|
|
|
|
2022-01-25 11:02:08 -05:00
|
|
|
class SandboxError(SubprocessError):
|
|
|
|
|
SUBPROCESS_NAME: ClassVar[str] = "Sandbox"
|
|
|
|
|
|
|
|
|
|
|
2021-12-26 06:30:21 -05:00
|
|
|
class AssemblyError(SubprocessError):
|
|
|
|
|
SUBPROCESS_NAME: ClassVar[str] = "Compiler"
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def from_process_error(ex: CalledProcessError) -> "SubprocessError":
|
|
|
|
|
error = super(AssemblyError, AssemblyError).from_process_error(ex)
|
|
|
|
|
|
|
|
|
|
error_lines = []
|
2022-08-12 01:51:10 +09:00
|
|
|
for line in ex.stdout.splitlines():
|
2021-12-26 06:30:21 -05:00
|
|
|
if "asm.s:" in line:
|
|
|
|
|
error_lines.append(line[line.find("asm.s:") + len("asm.s:") :].strip())
|
|
|
|
|
else:
|
|
|
|
|
error_lines.append(line)
|
|
|
|
|
error.msg = "\n".join(error_lines)
|
|
|
|
|
|
|
|
|
|
return error
|