prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  [Enhancement request] Meaningful error on labels naming conflict
  Feature description
  ---------
  Try rename a label to an existing name.
  
  You get a 500 error.
  
  Desired: a meaningful error.
  
  Related: #601, #826.
  
  </issue>
  <code>
  [start of app/api/views/label.py]
  1 import json
  2 
  3 from django.db import IntegrityError, transaction
  4 from django.shortcuts import get_object_or_404
  5 from rest_framework import generics, status
  6 from rest_framework.exceptions import ParseError
  7 from rest_framework.parsers import MultiPartParser
  8 from rest_framework.permissions import IsAuthenticated
  9 from rest_framework.response import Response
  10 from rest_framework.views import APIView
  11 
  12 from ..models import Label, Project
  13 from ..permissions import IsInProjectReadOnlyOrAdmin, IsProjectAdmin
  14 from ..serializers import LabelSerializer
  15 
  16 
  17 class LabelList(generics.ListCreateAPIView):
  18     serializer_class = LabelSerializer
  19     pagination_class = None
  20     permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin]
  21 
  22     def get_queryset(self):
  23         project = get_object_or_404(Project, pk=self.kwargs['project_id'])
  24         return project.labels
  25 
  26     def perform_create(self, serializer):
  27         project = get_object_or_404(Project, pk=self.kwargs['project_id'])
  28         serializer.save(project=project)
  29 
  30 
  31 class LabelDetail(generics.RetrieveUpdateDestroyAPIView):
  32     queryset = Label.objects.all()
  33     serializer_class = LabelSerializer
  34     lookup_url_kwarg = 'label_id'
  35     permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin]
  36 
  37 
  38 class LabelUploadAPI(APIView):
  39     parser_classes = (MultiPartParser,)
  40     permission_classes = [IsAuthenticated & IsProjectAdmin]
  41 
  42     @transaction.atomic
  43     def post(self, request, *args, **kwargs):
  44         if 'file' not in request.data:
  45             raise ParseError('Empty content')
  46         labels = json.load(request.data['file'])
  47         project = get_object_or_404(Project, pk=kwargs['project_id'])
  48         try:
  49             for label in labels:
  50                 serializer = LabelSerializer(data=label)
  51                 serializer.is_valid(raise_exception=True)
  52                 serializer.save(project=project)
  53             return Response(status=status.HTTP_201_CREATED)
  54         except IntegrityError:
  55             content = {'error': 'IntegrityError: you cannot create a label with same name or shortkey.'}
  56             return Response(content, status=status.HTTP_400_BAD_REQUEST)
  57
  [end of app/api/views/label.py]
  [start of app/api/exceptions.py]
  1 from rest_framework import status
  2 from rest_framework.exceptions import (APIException, PermissionDenied,
  3                                        ValidationError)
  4 
  5 
  6 class FileParseException(APIException):
  7     status_code = status.HTTP_400_BAD_REQUEST
  8     default_detail = 'Invalid file format, line {}: {}'
  9     default_code = 'invalid'
  10 
  11     def __init__(self, line_num, line, code=None):
  12         detail = self.default_detail.format(line_num, line)
  13         super().__init__(detail, code)
  14 
  15 
  16 class AutoLabelingException(APIException):
  17     status_code = status.HTTP_400_BAD_REQUEST
  18     default_detail = 'Auto labeling not allowed for the document with labels.'
  19 
  20 
  21 class AutoLabeliingPermissionDenied(PermissionDenied):
  22     default_detail = 'You do not have permission to perform auto labeling.' \
  23                      'Please ask the project administrators to add you.'
  24 
  25 
  26 class URLConnectionError(ValidationError):
  27     default_detail = 'Failed to establish a connection. Please check the URL or network.'
  28 
  29 
  30 class AWSTokenError(ValidationError):
  31     default_detail = 'The security token included in the request is invalid.'
  32 
  33 
  34 class SampleDataException(ValidationError):
  35     default_detail = 'The response is empty. Maybe the sample data is not appropriate.' \
  36                      'Please specify another sample data which returns at least one label.'
  37
  [end of app/api/exceptions.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/app/api/exceptions.py b/app/api/exceptions.py
  --- a/app/api/exceptions.py
  +++ b/app/api/exceptions.py
  @@ -34,3 +34,8 @@
   class SampleDataException(ValidationError):
       default_detail = 'The response is empty. Maybe the sample data is not appropriate.' \
                        'Please specify another sample data which returns at least one label.'
  +
  +
  +class LabelValidationError(APIException):
  +    status_code = status.HTTP_400_BAD_REQUEST
  +    default_detail = 'You cannot create a label with same name or shortcut key.'
  diff --git a/app/api/views/label.py b/app/api/views/label.py
  --- a/app/api/views/label.py
  +++ b/app/api/views/label.py
  @@ -9,6 +9,7 @@
   from rest_framework.response import Response
   from rest_framework.views import APIView
   
  +from ..exceptions import LabelValidationError
   from ..models import Label, Project
   from ..permissions import IsInProjectReadOnlyOrAdmin, IsProjectAdmin
   from ..serializers import LabelSerializer
  @@ -27,6 +28,11 @@
           project = get_object_or_404(Project, pk=self.kwargs['project_id'])
           serializer.save(project=project)
   
  +    def delete(self, request, *args, **kwargs):
  +        delete_ids = request.data['ids']
  +        Label.objects.filter(pk__in=delete_ids).delete()
  +        return Response(status=status.HTTP_204_NO_CONTENT)
  +
   
   class LabelDetail(generics.RetrieveUpdateDestroyAPIView):
       queryset = Label.objects.all()
  @@ -43,14 +49,14 @@
       def post(self, request, *args, **kwargs):
           if 'file' not in request.data:
               raise ParseError('Empty content')
  -        labels = json.load(request.data['file'])
           project = get_object_or_404(Project, pk=kwargs['project_id'])
           try:
  -            for label in labels:
  -                serializer = LabelSerializer(data=label)
  -                serializer.is_valid(raise_exception=True)
  -                serializer.save(project=project)
  +            labels = json.load(request.data['file'])
  +            serializer = LabelSerializer(data=labels, many=True)
  +            serializer.is_valid(raise_exception=True)
  +            serializer.save(project=project)
               return Response(status=status.HTTP_201_CREATED)
  +        except json.decoder.JSONDecodeError:
  +            raise ParseError('The file format is invalid.')
           except IntegrityError:
  -            content = {'error': 'IntegrityError: you cannot create a label with same name or shortkey.'}
  -            return Response(content, status=status.HTTP_400_BAD_REQUEST)
  +            raise LabelValidationError
  
verification_info: {"golden_diff": "diff --git a/app/api/exceptions.py b/app/api/exceptions.py\n--- a/app/api/exceptions.py\n+++ b/app/api/exceptions.py\n@@ -34,3 +34,8 @@\n class SampleDataException(ValidationError):\n     default_detail = 'The response is empty. Maybe the sample data is not appropriate.' \\\n                      'Please specify another sample data which returns at least one label.'\n+\n+\n+class LabelValidationError(APIException):\n+    status_code = status.HTTP_400_BAD_REQUEST\n+    default_detail = 'You cannot create a label with same name or shortcut key.'\ndiff --git a/app/api/views/label.py b/app/api/views/label.py\n--- a/app/api/views/label.py\n+++ b/app/api/views/label.py\n@@ -9,6 +9,7 @@\n from rest_framework.response import Response\n from rest_framework.views import APIView\n \n+from ..exceptions import LabelValidationError\n from ..models import Label, Project\n from ..permissions import IsInProjectReadOnlyOrAdmin, IsProjectAdmin\n from ..serializers import LabelSerializer\n@@ -27,6 +28,11 @@\n         project = get_object_or_404(Project, pk=self.kwargs['project_id'])\n         serializer.save(project=project)\n \n+    def delete(self, request, *args, **kwargs):\n+        delete_ids = request.data['ids']\n+        Label.objects.filter(pk__in=delete_ids).delete()\n+        return Response(status=status.HTTP_204_NO_CONTENT)\n+\n \n class LabelDetail(generics.RetrieveUpdateDestroyAPIView):\n     queryset = Label.objects.all()\n@@ -43,14 +49,14 @@\n     def post(self, request, *args, **kwargs):\n         if 'file' not in request.data:\n             raise ParseError('Empty content')\n-        labels = json.load(request.data['file'])\n         project = get_object_or_404(Project, pk=kwargs['project_id'])\n         try:\n-            for label in labels:\n-                serializer = LabelSerializer(data=label)\n-                serializer.is_valid(raise_exception=True)\n-                serializer.save(project=project)\n+            labels = json.load(request.data['file'])\n+            serializer = LabelSerializer(data=labels, many=True)\n+            serializer.is_valid(raise_exception=True)\n+            serializer.save(project=project)\n             return Response(status=status.HTTP_201_CREATED)\n+        except json.decoder.JSONDecodeError:\n+            raise ParseError('The file format is invalid.')\n         except IntegrityError:\n-            content = {'error': 'IntegrityError: you cannot create a label with same name or shortkey.'}\n-            return Response(content, status=status.HTTP_400_BAD_REQUEST)\n+            raise LabelValidationError\n", "issue": "[Enhancement request] Meaningful error on labels naming conflict\nFeature description\r\n---------\r\nTry rename a label to an existing name.\r\n\r\nYou get a 500 error.\r\n\r\nDesired: a meaningful error.\r\n\r\nRelated: #601, #826.\n", "before_files": [{"content": "import json\n\nfrom django.db import IntegrityError, transaction\nfrom django.shortcuts import get_object_or_404\nfrom rest_framework import generics, status\nfrom rest_framework.exceptions import ParseError\nfrom rest_framework.parsers import MultiPartParser\nfrom rest_framework.permissions import IsAuthenticated\nfrom rest_framework.response import Response\nfrom rest_framework.views import APIView\n\nfrom ..models import Label, Project\nfrom ..permissions import IsInProjectReadOnlyOrAdmin, IsProjectAdmin\nfrom ..serializers import LabelSerializer\n\n\nclass LabelList(generics.ListCreateAPIView):\n    serializer_class = LabelSerializer\n    pagination_class = None\n    permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin]\n\n    def get_queryset(self):\n        project = get_object_or_404(Project, pk=self.kwargs['project_id'])\n        return project.labels\n\n    def perform_create(self, serializer):\n        project = get_object_or_404(Project, pk=self.kwargs['project_id'])\n        serializer.save(project=project)\n\n\nclass LabelDetail(generics.RetrieveUpdateDestroyAPIView):\n    queryset = Label.objects.all()\n    serializer_class = LabelSerializer\n    lookup_url_kwarg = 'label_id'\n    permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin]\n\n\nclass LabelUploadAPI(APIView):\n    parser_classes = (MultiPartParser,)\n    permission_classes = [IsAuthenticated & IsProjectAdmin]\n\n    @transaction.atomic\n    def post(self, request, *args, **kwargs):\n        if 'file' not in request.data:\n            raise ParseError('Empty content')\n        labels = json.load(request.data['file'])\n        project = get_object_or_404(Project, pk=kwargs['project_id'])\n        try:\n            for label in labels:\n                serializer = LabelSerializer(data=label)\n                serializer.is_valid(raise_exception=True)\n                serializer.save(project=project)\n            return Response(status=status.HTTP_201_CREATED)\n        except IntegrityError:\n            content = {'error': 'IntegrityError: you cannot create a label with same name or shortkey.'}\n            return Response(content, status=status.HTTP_400_BAD_REQUEST)\n", "path": "app/api/views/label.py"}, {"content": "from rest_framework import status\nfrom rest_framework.exceptions import (APIException, PermissionDenied,\n                                       ValidationError)\n\n\nclass FileParseException(APIException):\n    status_code = status.HTTP_400_BAD_REQUEST\n    default_detail = 'Invalid file format, line {}: {}'\n    default_code = 'invalid'\n\n    def __init__(self, line_num, line, code=None):\n        detail = self.default_detail.format(line_num, line)\n        super().__init__(detail, code)\n\n\nclass AutoLabelingException(APIException):\n    status_code = status.HTTP_400_BAD_REQUEST\n    default_detail = 'Auto labeling not allowed for the document with labels.'\n\n\nclass AutoLabeliingPermissionDenied(PermissionDenied):\n    default_detail = 'You do not have permission to perform auto labeling.' \\\n                     'Please ask the project administrators to add you.'\n\n\nclass URLConnectionError(ValidationError):\n    default_detail = 'Failed to establish a connection. Please check the URL or network.'\n\n\nclass AWSTokenError(ValidationError):\n    default_detail = 'The security token included in the request is invalid.'\n\n\nclass SampleDataException(ValidationError):\n    default_detail = 'The response is empty. Maybe the sample data is not appropriate.' \\\n                     'Please specify another sample data which returns at least one label.'\n", "path": "app/api/exceptions.py"}]}