prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  make a test case to test the permissions
  we have implemented a lot of different restrictions to views. create a unit test to automate the testing process.
  
  </issue>
  <code>
  [start of django/cantusdb_project/main_app/views/sequence.py]
  1 from django.views.generic import DetailView, ListView, UpdateView
  2 from main_app.models import Sequence
  3 from django.db.models import Q
  4 from main_app.forms import SequenceEditForm
  5 from django.contrib.auth.mixins import LoginRequiredMixin
  6 from django.contrib import messages
  7 from django.contrib.auth.mixins import UserPassesTestMixin
  8 from django.core.exceptions import PermissionDenied
  9 from django.http import Http404
  10 
  11 
  12 
  13 class SequenceDetailView(DetailView):
  14     """
  15     Displays a single Sequence object. Accessed with ``sequences/<int:pk>``
  16     """
  17 
  18     model = Sequence
  19     context_object_name = "sequence"
  20     template_name = "sequence_detail.html"
  21 
  22     def get_context_data(self, **kwargs):
  23 
  24         # if the sequence's source isn't public, only logged-in users should be able to view the sequence's detail page
  25         sequence = self.get_object()
  26         source = sequence.source
  27         if (source.public is False) and (not self.request.user.is_authenticated):
  28             raise PermissionDenied()
  29         
  30         context = super().get_context_data(**kwargs)
  31         context["concordances"] = Sequence.objects.filter(
  32             cantus_id=self.get_object().cantus_id
  33         ).order_by("siglum")
  34         return context
  35 
  36 
  37 class SequenceListView(ListView):
  38     """
  39     Displays a list of Sequence objects. Accessed with ``sequences/``
  40     """
  41 
  42     model = Sequence
  43     paginate_by = 100
  44     context_object_name = "sequences"
  45     template_name = "sequence_list.html"
  46 
  47     def get_queryset(self):
  48         queryset = super().get_queryset()
  49         q_obj_filter = Q(source__visible=True)
  50         q_obj_filter &= Q(source__public=True)
  51 
  52         if self.request.GET.get("incipit"):
  53             incipit = self.request.GET.get("incipit")
  54             q_obj_filter &= Q(incipit__icontains=incipit)
  55         if self.request.GET.get("siglum"):
  56             siglum = self.request.GET.get("siglum")
  57             q_obj_filter &= Q(siglum__icontains=siglum)
  58         if self.request.GET.get("cantus_id"):
  59             cantus_id = self.request.GET.get("cantus_id")
  60             q_obj_filter &= Q(cantus_id__icontains=cantus_id)
  61 
  62         return queryset.filter(q_obj_filter).order_by("siglum", "sequence")
  63 
  64 class SequenceEditView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
  65     template_name = "sequence_edit.html"
  66     model = Sequence
  67     form_class = SequenceEditForm
  68     pk_url_kwarg = "sequence_id"
  69 
  70     def form_valid(self, form):
  71         messages.success(
  72             self.request,
  73             "Sequence updated successfully!",
  74         )
  75         return super().form_valid(form)
  76 
  77     def test_func(self):
  78         user = self.request.user
  79         sequence_id = self.kwargs.get(self.pk_url_kwarg)
  80         try:
  81             sequence = Sequence.objects.get(id=sequence_id)
  82         except:
  83             raise Http404("This sequence does not exist")
  84         # find the source of this sequence
  85         source = sequence.source
  86         # checks if the user is an editor or a proofreader,
  87         # and if the user is given privilege to edit this source and thus, it's sequences
  88         is_editor_proofreader = user.groups.filter(Q(name="editor")|Q(name="proofreader")).exists()
  89         can_edit_sequences_in_source = user.sources_user_can_edit.filter(id=source.id)
  90         # checks if the user is a project manager (they should have the privilege to edit any sequence)
  91         is_project_manager = user.groups.filter(name="project manager").exists()
  92         # checks if the user is a contributor,
  93         # and if the user is the creator of this source 
  94         # (they should only have the privilege to edit sequences in a source they have created)
  95         is_contributor = user.groups.filter(name="contributor").exists()
  96 
  97         if ((is_editor_proofreader and can_edit_sequences_in_source) 
  98             or (is_project_manager) 
  99             or (is_contributor and source.created_by == user)):
  100             return True
  101         else:
  102             return False
  103
  [end of django/cantusdb_project/main_app/views/sequence.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/django/cantusdb_project/main_app/views/sequence.py b/django/cantusdb_project/main_app/views/sequence.py
  --- a/django/cantusdb_project/main_app/views/sequence.py
  +++ b/django/cantusdb_project/main_app/views/sequence.py
  @@ -76,27 +76,10 @@
   
       def test_func(self):
           user = self.request.user
  -        sequence_id = self.kwargs.get(self.pk_url_kwarg)
  -        try:
  -            sequence = Sequence.objects.get(id=sequence_id)
  -        except:
  -            raise Http404("This sequence does not exist")
  -        # find the source of this sequence
  -        source = sequence.source
  -        # checks if the user is an editor or a proofreader,
  -        # and if the user is given privilege to edit this source and thus, it's sequences
  -        is_editor_proofreader = user.groups.filter(Q(name="editor")|Q(name="proofreader")).exists()
  -        can_edit_sequences_in_source = user.sources_user_can_edit.filter(id=source.id)
           # checks if the user is a project manager (they should have the privilege to edit any sequence)
           is_project_manager = user.groups.filter(name="project manager").exists()
  -        # checks if the user is a contributor,
  -        # and if the user is the creator of this source 
  -        # (they should only have the privilege to edit sequences in a source they have created)
  -        is_contributor = user.groups.filter(name="contributor").exists()
  -
  -        if ((is_editor_proofreader and can_edit_sequences_in_source) 
  -            or (is_project_manager) 
  -            or (is_contributor and source.created_by == user)):
  +
  +        if is_project_manager:
               return True
           else:
               return False
  
verification_info: {"golden_diff": "diff --git a/django/cantusdb_project/main_app/views/sequence.py b/django/cantusdb_project/main_app/views/sequence.py\n--- a/django/cantusdb_project/main_app/views/sequence.py\n+++ b/django/cantusdb_project/main_app/views/sequence.py\n@@ -76,27 +76,10 @@\n \n     def test_func(self):\n         user = self.request.user\n-        sequence_id = self.kwargs.get(self.pk_url_kwarg)\n-        try:\n-            sequence = Sequence.objects.get(id=sequence_id)\n-        except:\n-            raise Http404(\"This sequence does not exist\")\n-        # find the source of this sequence\n-        source = sequence.source\n-        # checks if the user is an editor or a proofreader,\n-        # and if the user is given privilege to edit this source and thus, it's sequences\n-        is_editor_proofreader = user.groups.filter(Q(name=\"editor\")|Q(name=\"proofreader\")).exists()\n-        can_edit_sequences_in_source = user.sources_user_can_edit.filter(id=source.id)\n         # checks if the user is a project manager (they should have the privilege to edit any sequence)\n         is_project_manager = user.groups.filter(name=\"project manager\").exists()\n-        # checks if the user is a contributor,\n-        # and if the user is the creator of this source \n-        # (they should only have the privilege to edit sequences in a source they have created)\n-        is_contributor = user.groups.filter(name=\"contributor\").exists()\n-\n-        if ((is_editor_proofreader and can_edit_sequences_in_source) \n-            or (is_project_manager) \n-            or (is_contributor and source.created_by == user)):\n+\n+        if is_project_manager:\n             return True\n         else:\n             return False\n", "issue": "make a test case to test the permissions\nwe have implemented a lot of different restrictions to views. create a unit test to automate the testing process.\n", "before_files": [{"content": "from django.views.generic import DetailView, ListView, UpdateView\nfrom main_app.models import Sequence\nfrom django.db.models import Q\nfrom main_app.forms import SequenceEditForm\nfrom django.contrib.auth.mixins import LoginRequiredMixin\nfrom django.contrib import messages\nfrom django.contrib.auth.mixins import UserPassesTestMixin\nfrom django.core.exceptions import PermissionDenied\nfrom django.http import Http404\n\n\n\nclass SequenceDetailView(DetailView):\n    \"\"\"\n    Displays a single Sequence object. Accessed with ``sequences/<int:pk>``\n    \"\"\"\n\n    model = Sequence\n    context_object_name = \"sequence\"\n    template_name = \"sequence_detail.html\"\n\n    def get_context_data(self, **kwargs):\n\n        # if the sequence's source isn't public, only logged-in users should be able to view the sequence's detail page\n        sequence = self.get_object()\n        source = sequence.source\n        if (source.public is False) and (not self.request.user.is_authenticated):\n            raise PermissionDenied()\n        \n        context = super().get_context_data(**kwargs)\n        context[\"concordances\"] = Sequence.objects.filter(\n            cantus_id=self.get_object().cantus_id\n        ).order_by(\"siglum\")\n        return context\n\n\nclass SequenceListView(ListView):\n    \"\"\"\n    Displays a list of Sequence objects. Accessed with ``sequences/``\n    \"\"\"\n\n    model = Sequence\n    paginate_by = 100\n    context_object_name = \"sequences\"\n    template_name = \"sequence_list.html\"\n\n    def get_queryset(self):\n        queryset = super().get_queryset()\n        q_obj_filter = Q(source__visible=True)\n        q_obj_filter &= Q(source__public=True)\n\n        if self.request.GET.get(\"incipit\"):\n            incipit = self.request.GET.get(\"incipit\")\n            q_obj_filter &= Q(incipit__icontains=incipit)\n        if self.request.GET.get(\"siglum\"):\n            siglum = self.request.GET.get(\"siglum\")\n            q_obj_filter &= Q(siglum__icontains=siglum)\n        if self.request.GET.get(\"cantus_id\"):\n            cantus_id = self.request.GET.get(\"cantus_id\")\n            q_obj_filter &= Q(cantus_id__icontains=cantus_id)\n\n        return queryset.filter(q_obj_filter).order_by(\"siglum\", \"sequence\")\n\nclass SequenceEditView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):\n    template_name = \"sequence_edit.html\"\n    model = Sequence\n    form_class = SequenceEditForm\n    pk_url_kwarg = \"sequence_id\"\n\n    def form_valid(self, form):\n        messages.success(\n            self.request,\n            \"Sequence updated successfully!\",\n        )\n        return super().form_valid(form)\n\n    def test_func(self):\n        user = self.request.user\n        sequence_id = self.kwargs.get(self.pk_url_kwarg)\n        try:\n            sequence = Sequence.objects.get(id=sequence_id)\n        except:\n            raise Http404(\"This sequence does not exist\")\n        # find the source of this sequence\n        source = sequence.source\n        # checks if the user is an editor or a proofreader,\n        # and if the user is given privilege to edit this source and thus, it's sequences\n        is_editor_proofreader = user.groups.filter(Q(name=\"editor\")|Q(name=\"proofreader\")).exists()\n        can_edit_sequences_in_source = user.sources_user_can_edit.filter(id=source.id)\n        # checks if the user is a project manager (they should have the privilege to edit any sequence)\n        is_project_manager = user.groups.filter(name=\"project manager\").exists()\n        # checks if the user is a contributor,\n        # and if the user is the creator of this source \n        # (they should only have the privilege to edit sequences in a source they have created)\n        is_contributor = user.groups.filter(name=\"contributor\").exists()\n\n        if ((is_editor_proofreader and can_edit_sequences_in_source) \n            or (is_project_manager) \n            or (is_contributor and source.created_by == user)):\n            return True\n        else:\n            return False\n", "path": "django/cantusdb_project/main_app/views/sequence.py"}]}