prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Names show up multiple times in assignment pulldown
  1. Go to an event.
  2. Try to assign to assign to someone other than yourself.
  3. Selection dialog with pulldown appears so that you can choose person.
  4. Some names (currently Greg Wilson and Tracy Teal, possibly others) show up multiple times in that list.
  
  
  </issue>
  <code>
  [start of workshops/lookups.py]
  1 from functools import reduce
  2 import operator
  3 import re
  4 
  5 from django.contrib.auth.models import Group
  6 from django.db.models import Q
  7 
  8 from selectable.base import ModelLookup
  9 from selectable.registry import registry
  10 from selectable.decorators import login_required
  11 
  12 from workshops import models
  13 
  14 
  15 @login_required
  16 class EventLookup(ModelLookup):
  17     model = models.Event
  18     search_fields = ('slug__icontains', )
  19 
  20 
  21 @login_required
  22 class HostLookup(ModelLookup):
  23     model = models.Host
  24     search_fields = (
  25         'domain__icontains',
  26         'fullname__icontains'
  27     )
  28 
  29 
  30 @login_required
  31 class PersonLookup(ModelLookup):
  32     model = models.Person
  33     search_fields = (
  34         'personal__icontains',
  35         'family__icontains',
  36         'email__icontains',
  37         'username__icontains'
  38     )
  39 
  40     def get_query(self, request, term):
  41         """Override this method to allow for additional lookup method: """
  42         # original code from selectable.base.ModelLookup.get_query:
  43         qs = self.get_queryset()
  44         if term:
  45             search_filters = []
  46             if self.search_fields:
  47                 for field in self.search_fields:
  48                     search_filters.append(Q(**{field: term}))
  49 
  50             # tokenizing part
  51             tokens = re.split('\s+', term)
  52             if len(tokens) == 2:
  53                 name1, name2 = tokens
  54                 complex_q = (
  55                     Q(personal__icontains=name1) & Q(family__icontains=name2)
  56                 ) | (
  57                     Q(personal__icontains=name2) & Q(family__icontains=name1)
  58                 )
  59                 search_filters.append(complex_q)
  60 
  61             # this is brilliant: it applies OR to all search filters
  62             qs = qs.filter(reduce(operator.or_, search_filters))
  63 
  64         return qs
  65 
  66 
  67 @login_required
  68 class AdminLookup(ModelLookup):
  69     """The same as PersonLookup, but allows only to select administrators.
  70 
  71     Administrator is anyone with superuser power or in "administrators" group.
  72     """
  73     model = models.Person
  74     search_fields = (
  75         'personal__icontains',
  76         'family__icontains',
  77         'email__icontains',
  78         'username__icontains'
  79     )
  80 
  81     def get_query(self, request, term):
  82         results = super().get_query(request, term)
  83         admin_group = Group.objects.get(name='administrators')
  84         results = results.filter(
  85             Q(is_superuser=True) | Q(groups__in=[admin_group])
  86         )
  87         return results
  88 
  89 
  90 @login_required
  91 class AirportLookup(ModelLookup):
  92     model = models.Airport
  93     search_fields = (
  94         'iata__icontains',
  95         'fullname__icontains'
  96     )
  97 
  98 
  99 registry.register(EventLookup)
  100 registry.register(HostLookup)
  101 registry.register(PersonLookup)
  102 registry.register(AdminLookup)
  103 registry.register(AirportLookup)
  104
  [end of workshops/lookups.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/workshops/lookups.py b/workshops/lookups.py
  --- a/workshops/lookups.py
  +++ b/workshops/lookups.py
  @@ -83,7 +83,7 @@
           admin_group = Group.objects.get(name='administrators')
           results = results.filter(
               Q(is_superuser=True) | Q(groups__in=[admin_group])
  -        )
  +        ).distinct()
           return results
  
verification_info: {"golden_diff": "diff --git a/workshops/lookups.py b/workshops/lookups.py\n--- a/workshops/lookups.py\n+++ b/workshops/lookups.py\n@@ -83,7 +83,7 @@\n         admin_group = Group.objects.get(name='administrators')\n         results = results.filter(\n             Q(is_superuser=True) | Q(groups__in=[admin_group])\n-        )\n+        ).distinct()\n         return results\n", "issue": "Names show up multiple times in assignment pulldown\n1. Go to an event.\n2. Try to assign to assign to someone other than yourself.\n3. Selection dialog with pulldown appears so that you can choose person.\n4. Some names (currently Greg Wilson and Tracy Teal, possibly others) show up multiple times in that list.\n\n", "before_files": [{"content": "from functools import reduce\nimport operator\nimport re\n\nfrom django.contrib.auth.models import Group\nfrom django.db.models import Q\n\nfrom selectable.base import ModelLookup\nfrom selectable.registry import registry\nfrom selectable.decorators import login_required\n\nfrom workshops import models\n\n\n@login_required\nclass EventLookup(ModelLookup):\n    model = models.Event\n    search_fields = ('slug__icontains', )\n\n\n@login_required\nclass HostLookup(ModelLookup):\n    model = models.Host\n    search_fields = (\n        'domain__icontains',\n        'fullname__icontains'\n    )\n\n\n@login_required\nclass PersonLookup(ModelLookup):\n    model = models.Person\n    search_fields = (\n        'personal__icontains',\n        'family__icontains',\n        'email__icontains',\n        'username__icontains'\n    )\n\n    def get_query(self, request, term):\n        \"\"\"Override this method to allow for additional lookup method: \"\"\"\n        # original code from selectable.base.ModelLookup.get_query:\n        qs = self.get_queryset()\n        if term:\n            search_filters = []\n            if self.search_fields:\n                for field in self.search_fields:\n                    search_filters.append(Q(**{field: term}))\n\n            # tokenizing part\n            tokens = re.split('\\s+', term)\n            if len(tokens) == 2:\n                name1, name2 = tokens\n                complex_q = (\n                    Q(personal__icontains=name1) & Q(family__icontains=name2)\n                ) | (\n                    Q(personal__icontains=name2) & Q(family__icontains=name1)\n                )\n                search_filters.append(complex_q)\n\n            # this is brilliant: it applies OR to all search filters\n            qs = qs.filter(reduce(operator.or_, search_filters))\n\n        return qs\n\n\n@login_required\nclass AdminLookup(ModelLookup):\n    \"\"\"The same as PersonLookup, but allows only to select administrators.\n\n    Administrator is anyone with superuser power or in \"administrators\" group.\n    \"\"\"\n    model = models.Person\n    search_fields = (\n        'personal__icontains',\n        'family__icontains',\n        'email__icontains',\n        'username__icontains'\n    )\n\n    def get_query(self, request, term):\n        results = super().get_query(request, term)\n        admin_group = Group.objects.get(name='administrators')\n        results = results.filter(\n            Q(is_superuser=True) | Q(groups__in=[admin_group])\n        )\n        return results\n\n\n@login_required\nclass AirportLookup(ModelLookup):\n    model = models.Airport\n    search_fields = (\n        'iata__icontains',\n        'fullname__icontains'\n    )\n\n\nregistry.register(EventLookup)\nregistry.register(HostLookup)\nregistry.register(PersonLookup)\nregistry.register(AdminLookup)\nregistry.register(AirportLookup)\n", "path": "workshops/lookups.py"}]}