6363scanpipe_app = apps .get_app_config ("scanpipe" )
6464
6565
66+ class ErrorResponse (Response ):
67+ def __init__ (self , message , status_code = status .HTTP_400_BAD_REQUEST , ** kwargs ):
68+ # If message is already a dict, use it as-is
69+ if isinstance (message , dict ):
70+ data = message
71+ else :
72+ # Otherwise, wrap string in {"status": message}
73+ data = {"status" : message }
74+
75+ super ().__init__ (data = data , status = status_code , ** kwargs )
76+
77+
6678class ProjectFilterSet (django_filters .rest_framework .FilterSet ):
6779 name = django_filters .CharFilter ()
6880 name__contains = django_filters .CharFilter (
@@ -178,8 +190,7 @@ def results_download(self, request, *args, **kwargs):
178190 elif format == "all_outputs" :
179191 output_file = output .to_all_outputs (project )
180192 else :
181- message = {"status" : f"Format { format } not supported." }
182- return Response (message , status = status .HTTP_400_BAD_REQUEST )
193+ return ErrorResponse (f"Format { format } not supported." )
183194
184195 filename = output .safe_filename (f"scancodeio_{ project .name } _{ output_file .name } " )
185196 return FileResponse (
@@ -198,8 +209,7 @@ def summary(self, request, *args, **kwargs):
198209 summary_file = project .get_latest_output (filename = "summary" )
199210
200211 if not summary_file :
201- message = {"error" : "Summary file not available" }
202- return Response (message , status = status .HTTP_400_BAD_REQUEST )
212+ return ErrorResponse ({"error" : "Summary file not available" })
203213
204214 summary_json = json .loads (summary_file .read_text ())
205215 return Response (summary_json )
@@ -226,14 +236,14 @@ def report(self, request, *args, **kwargs):
226236 ),
227237 "choices" : ", " .join (model_choices ),
228238 }
229- return Response (message , status = status . HTTP_400_BAD_REQUEST )
239+ return ErrorResponse (message )
230240
231241 if model not in model_choices :
232242 message = {
233243 "error" : f"{ model } is not on of the valid choices" ,
234244 "choices" : ", " .join (model_choices ),
235245 }
236- return Response (message , status = status . HTTP_400_BAD_REQUEST )
246+ return ErrorResponse (message )
237247
238248 output_file = output .get_xlsx_report (
239249 project_qs = project_qs ,
@@ -256,8 +266,7 @@ def get_filtered_response(
256266 """
257267 filterset = filterset_class (data = request .GET , queryset = queryset )
258268 if not filterset .is_valid ():
259- message = {"errors" : filterset .errors }
260- return Response (message , status = status .HTTP_400_BAD_REQUEST )
269+ return ErrorResponse ({"errors" : filterset .errors })
261270
262271 queryset = filterset .qs
263272 paginated_qs = self .paginate_queryset (queryset )
@@ -315,14 +324,12 @@ def file_content(self, request, *args, **kwargs):
315324 try :
316325 codebase_resource = codebase_resources .get (path = path )
317326 except ObjectDoesNotExist :
318- message = {"status" : "Resource not found. Use ?path=<resource_path>" }
319- return Response (message , status = status .HTTP_400_BAD_REQUEST )
327+ return ErrorResponse ("Resource not found. Use ?path=<resource_path>" )
320328
321329 try :
322330 file_content = codebase_resource .file_content
323331 except OSError :
324- message = {"status" : "File not available" }
325- return Response (message , status = status .HTTP_400_BAD_REQUEST )
332+ return ErrorResponse ("File not available" )
326333
327334 return Response ({"file_content" : file_content })
328335
@@ -341,32 +348,29 @@ def add_pipeline(self, request, *args, **kwargs):
341348 {"status" : "Pipeline added." }, status = status .HTTP_201_CREATED
342349 )
343350
344- message = {"status" : f"{ pipeline } is not a valid pipeline." }
345- return Response (message , status = status .HTTP_400_BAD_REQUEST )
351+ return ErrorResponse (f"{ pipeline } is not a valid pipeline." )
346352
347353 message = {
348354 "status" : "Pipeline required." ,
349355 "pipelines" : list (scanpipe_app .pipelines .keys ()),
350356 }
351- return Response (message , status = status . HTTP_400_BAD_REQUEST )
357+ return ErrorResponse (message )
352358
353359 @action (detail = True , methods = ["get" , "post" ])
354360 def add_input (self , request , * args , ** kwargs ):
355361 project = self .get_object ()
356362
357363 if not project .can_change_inputs :
358- message = {
359- "status" : "Cannot add inputs once a pipeline has started to execute."
360- }
361- return Response (message , status = status .HTTP_400_BAD_REQUEST )
364+ return ErrorResponse (
365+ "Cannot add inputs once a pipeline has started to execute."
366+ )
362367
363368 upload_file = request .data .get ("upload_file" )
364369 upload_file_tag = request .data .get ("upload_file_tag" , "" )
365370 input_urls = request .data .get ("input_urls" , [])
366371
367372 if not (upload_file or input_urls ):
368- message = {"status" : "upload_file or input_urls required." }
369- return Response (message , status = status .HTTP_400_BAD_REQUEST )
373+ return ErrorResponse ("upload_file or input_urls required." )
370374
371375 if upload_file :
372376 project .add_upload (upload_file , tag = upload_file_tag )
@@ -398,16 +402,13 @@ def add_webhook(self, request, *args, **kwargs):
398402 )
399403
400404 # Return validation errors
401- return Response (serializer .errors , status = status . HTTP_400_BAD_REQUEST )
405+ return ErrorResponse (serializer .errors )
402406
403407 def destroy (self , request , * args , ** kwargs ):
404408 try :
405409 return super ().destroy (request , * args , ** kwargs )
406410 except RunInProgressError :
407- return Response (
408- {"status" : "Cannot delete project while a run is in progress." },
409- status = status .HTTP_400_BAD_REQUEST ,
410- )
411+ return ErrorResponse ("Cannot delete project while a run is in progress." )
411412
412413 @action (detail = True , methods = ["get" , "post" ])
413414 def archive (self , request , * args , ** kwargs ):
@@ -429,10 +430,7 @@ def archive(self, request, *args, **kwargs):
429430 remove_output = request .data .get ("remove_output" ),
430431 )
431432 except RunInProgressError :
432- return Response (
433- {"status" : "Cannot archive project while a run is in progress." },
434- status = status .HTTP_400_BAD_REQUEST ,
435- )
433+ return ErrorResponse ("Cannot archive project while a run is in progress." )
436434
437435 return Response ({"status" : f"The project { project } has been archived." })
438436
@@ -451,10 +449,7 @@ def reset(self, request, *args, **kwargs):
451449 execute_now = request .data .get ("execute_now" , False ),
452450 )
453451 except RunInProgressError :
454- return Response (
455- {"status" : "Cannot reset project while a run is in progress." },
456- status = status .HTTP_400_BAD_REQUEST ,
457- )
452+ return ErrorResponse ("Cannot reset project while a run is in progress." )
458453 else :
459454 message = f"The { project } project has been reset."
460455 return Response ({"status" : message })
@@ -468,8 +463,7 @@ def outputs(self, request, *args, **kwargs):
468463 if file_path .exists ():
469464 return FileResponse (file_path .open ("rb" ))
470465
471- message = {"status" : f"Output file { filename } not found" }
472- return Response (message , status = status .HTTP_400_BAD_REQUEST )
466+ return ErrorResponse (f"Output file { filename } not found" )
473467
474468 action_url = self .reverse_action (self .outputs .url_name , args = [project .pk ])
475469 output_data = [
@@ -544,14 +538,11 @@ class RunViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
544538 def start_pipeline (self , request , * args , ** kwargs ):
545539 run = self .get_object ()
546540 if run .task_end_date :
547- message = {"status" : "Pipeline already executed." }
548- return Response (message , status = status .HTTP_400_BAD_REQUEST )
541+ return ErrorResponse ("Pipeline already executed." )
549542 elif run .task_start_date :
550- message = {"status" : "Pipeline already started." }
551- return Response (message , status = status .HTTP_400_BAD_REQUEST )
543+ return ErrorResponse ("Pipeline already started." )
552544 elif run .task_id :
553- message = {"status" : "Pipeline already queued." }
554- return Response (message , status = status .HTTP_400_BAD_REQUEST )
545+ return ErrorResponse ("Pipeline already queued." )
555546
556547 transaction .on_commit (run .start )
557548
@@ -562,8 +553,7 @@ def stop_pipeline(self, request, *args, **kwargs):
562553 run = self .get_object ()
563554
564555 if run .status != run .Status .RUNNING :
565- message = {"status" : "Pipeline is not running." }
566- return Response (message , status = status .HTTP_400_BAD_REQUEST )
556+ return ErrorResponse ("Pipeline is not running." )
567557
568558 run .stop_task ()
569559 return Response ({"status" : f"Pipeline { run .pipeline_name } stopped." })
@@ -573,8 +563,7 @@ def delete_pipeline(self, request, *args, **kwargs):
573563 run = self .get_object ()
574564
575565 if run .status not in [run .Status .NOT_STARTED , run .Status .QUEUED ]:
576- message = {"status" : "Only non started or queued pipelines can be deleted." }
577- return Response (message , status = status .HTTP_400_BAD_REQUEST )
566+ return ErrorResponse ("Only non started or queued pipelines can be deleted." )
578567
579568 run .delete_task ()
580569 return Response ({"status" : f"Pipeline { run .pipeline_name } deleted." })
0 commit comments