from rest_framework import serializers, status from rest_framework.response import Response from rest_framework.views import APIView from .algorithms import ProcessingError from .selectors import image_session_get, processing_job_get from .services import batch_job_create, image_session_create, image_session_process, processing_job_payload def error_response(message, code=status.HTTP_400_BAD_REQUEST): return Response({"detail": message}, status=code) class ImageUploadView(APIView): class InputSerializer(serializers.Serializer): image = serializers.ImageField(required=False) image_base64 = serializers.CharField(required=False, allow_blank=False) def validate(self, attrs): if not attrs.get("image") and not attrs.get("image_base64"): raise serializers.ValidationError("Provide image or image_base64.") return attrs def post(self, request): serializer = self.InputSerializer(data=request.data) serializer.is_valid(raise_exception=True) try: payload = image_session_create( uploaded_file=serializer.validated_data.get("image"), image_base64=serializer.validated_data.get("image_base64"), ) return Response(payload, status=status.HTTP_201_CREATED) except ProcessingError as exc: return error_response(str(exc)) class ProcessView(APIView): class InputSerializer(serializers.Serializer): session_id = serializers.UUIDField() operation = serializers.CharField() params = serializers.DictField(required=False, default=dict) def post(self, request): serializer = self.InputSerializer(data=request.data) serializer.is_valid(raise_exception=True) session = image_session_get(session_id=serializer.validated_data["session_id"]) if session is None: return error_response("Image session does not exist.", status.HTTP_404_NOT_FOUND) try: payload = image_session_process( session=session, operation=serializer.validated_data["operation"], params=serializer.validated_data.get("params", {}), ) return Response(payload) except ProcessingError as exc: code = status.HTTP_410_GONE if str(exc) == "Image session has expired." else status.HTTP_400_BAD_REQUEST return error_response(str(exc), code) class BatchView(APIView): class InputSerializer(serializers.Serializer): operation = serializers.ChoiceField(choices=["average", "subtract"]) session_ids = serializers.ListField(child=serializers.UUIDField(), min_length=2) params = serializers.DictField(required=False, default=dict) def post(self, request): serializer = self.InputSerializer(data=request.data) serializer.is_valid(raise_exception=True) job = batch_job_create( operation=serializer.validated_data["operation"], session_ids=serializer.validated_data["session_ids"], params=serializer.validated_data.get("params", {}), ) return Response({"job_id": str(job.id), "status": job.status}, status=status.HTTP_202_ACCEPTED) class JobDetailView(APIView): def get(self, request, job_id): job = processing_job_get(job_id=job_id) if job is None: return error_response("Job does not exist.", status.HTTP_404_NOT_FOUND) return Response(processing_job_payload(job=job)) class HealthView(APIView): def get(self, request): return Response({"status": "ok"})