prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Add search by github handle to API persons endpoint
  Would it be possible to add the functionality to search for people using their github handle through the API? i.e. `https://amy.software-carpentry.org/api/v1/persons/?github=fmichonneau`
  
  </issue>
  <code>
  [start of api/filters.py]
  1 from django_filters import rest_framework as filters
  2 
  3 from workshops.filters import AMYFilterSet
  4 from workshops.models import Event, Task, Tag, Person, Badge
  5 
  6 
  7 def filter_tag_by_name(queryset, name, values):
  8     tags = Tag.objects.filter(name__in=values)
  9     for tag in tags:
  10         queryset = queryset.filter(tags=tag)
  11     return queryset
  12 
  13 
  14 class EventFilter(filters.FilterSet):
  15     start_after = filters.DateFilter(name='start', lookup_expr='gte')
  16     start_before = filters.DateFilter(name='start', lookup_expr='lte')
  17     end_after = filters.DateFilter(name='end', lookup_expr='gte')
  18     end_before = filters.DateFilter(name='end', lookup_expr='lte')
  19     TAG_CHOICES = Tag.objects.all().values_list('name', 'name')
  20     tag = filters.MultipleChoiceFilter(
  21         choices=TAG_CHOICES, name='tags', method=filter_tag_by_name,
  22     )
  23 
  24     class Meta:
  25         model = Event
  26         fields = (
  27             'completed', 'tag',
  28             'start', 'start_before', 'start_after',
  29             'end', 'end_before', 'end_after',
  30         )
  31         order_by = ('-slug', 'slug', 'start', '-start', 'end', '-end')
  32 
  33 
  34 class TaskFilter(filters.FilterSet):
  35     role = filters.CharFilter(name='role__name')
  36 
  37     class Meta:
  38         model = Task
  39         fields = (
  40             'role',
  41         )
  42 
  43 
  44 def filter_instructors(queryset, name, value):
  45     instructor_badges = Badge.objects.instructor_badges()
  46     if value is True:
  47         return queryset.filter(badges__in=instructor_badges)
  48     elif value is False:
  49         return queryset.exclude(badges__in=instructor_badges)
  50     else:
  51         return queryset
  52 
  53 
  54 class PersonFilter(filters.FilterSet):
  55     is_instructor = filters.BooleanFilter(method=filter_instructors,
  56                                           label='Is instructor?')
  57 
  58     class Meta:
  59         model = Person
  60         fields = (
  61             'badges', 'username', 'personal', 'middle', 'family', 'email',
  62             'may_contact', 'publish_profile',
  63         )
  64         order_by = (
  65             'lastname', '-lastname', 'firstname', '-firstname', 'email',
  66             '-email',
  67         )
  68 
  69     def get_order_by(self, order_value):
  70         if order_value == 'firstname':
  71             return ['personal', 'middle', 'family']
  72         elif order_value == '-firstname':
  73             return ['-personal', '-middle', '-family']
  74         elif order_value == 'lastname':
  75             return ['family', 'middle', 'personal']
  76         elif order_value == '-lastname':
  77             return ['-family', '-middle', '-personal']
  78         return super().get_order_by(order_value)
  79 
  80 
  81 class InstructorsOverTimeFilter(AMYFilterSet):
  82     badges = filters.ModelMultipleChoiceFilter(
  83         queryset=Badge.objects.instructor_badges(),
  84         label='Badges',
  85         lookup_expr='in',
  86     )
  87 
  88     class Meta:
  89         model = Person
  90         fields = [
  91             'badges',
  92         ]
  93 
  94 
  95 class WorkshopsOverTimeFilter(AMYFilterSet):
  96     tags = filters.ModelMultipleChoiceFilter(
  97         queryset=Tag.objects.all(),
  98         label='Events with at least one of the following tags:',
  99     )
  100 
  101     class Meta:
  102         model = Event
  103         fields = [
  104             'tags',
  105         ]
  106 
  107 
  108 class LearnersOverTimeFilter(AMYFilterSet):
  109     tags = filters.ModelMultipleChoiceFilter(
  110         queryset=Tag.objects.all(),
  111         label='Events with all the following tags:',
  112         conjoined=True,
  113     )
  114 
  115     class Meta:
  116         model = Event
  117         fields = [
  118             'tags',
  119         ]
  120
  [end of api/filters.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/api/filters.py b/api/filters.py
  --- a/api/filters.py
  +++ b/api/filters.py
  @@ -59,7 +59,7 @@
           model = Person
           fields = (
               'badges', 'username', 'personal', 'middle', 'family', 'email',
  -            'may_contact', 'publish_profile',
  +            'may_contact', 'publish_profile', 'github',
           )
           order_by = (
               'lastname', '-lastname', 'firstname', '-firstname', 'email',
  
verification_info: {"golden_diff": "diff --git a/api/filters.py b/api/filters.py\n--- a/api/filters.py\n+++ b/api/filters.py\n@@ -59,7 +59,7 @@\n         model = Person\n         fields = (\n             'badges', 'username', 'personal', 'middle', 'family', 'email',\n-            'may_contact', 'publish_profile',\n+            'may_contact', 'publish_profile', 'github',\n         )\n         order_by = (\n             'lastname', '-lastname', 'firstname', '-firstname', 'email',\n", "issue": "Add search by github handle to API persons endpoint\nWould it be possible to add the functionality to search for people using their github handle through the API? i.e. `https://amy.software-carpentry.org/api/v1/persons/?github=fmichonneau`\n", "before_files": [{"content": "from django_filters import rest_framework as filters\n\nfrom workshops.filters import AMYFilterSet\nfrom workshops.models import Event, Task, Tag, Person, Badge\n\n\ndef filter_tag_by_name(queryset, name, values):\n    tags = Tag.objects.filter(name__in=values)\n    for tag in tags:\n        queryset = queryset.filter(tags=tag)\n    return queryset\n\n\nclass EventFilter(filters.FilterSet):\n    start_after = filters.DateFilter(name='start', lookup_expr='gte')\n    start_before = filters.DateFilter(name='start', lookup_expr='lte')\n    end_after = filters.DateFilter(name='end', lookup_expr='gte')\n    end_before = filters.DateFilter(name='end', lookup_expr='lte')\n    TAG_CHOICES = Tag.objects.all().values_list('name', 'name')\n    tag = filters.MultipleChoiceFilter(\n        choices=TAG_CHOICES, name='tags', method=filter_tag_by_name,\n    )\n\n    class Meta:\n        model = Event\n        fields = (\n            'completed', 'tag',\n            'start', 'start_before', 'start_after',\n            'end', 'end_before', 'end_after',\n        )\n        order_by = ('-slug', 'slug', 'start', '-start', 'end', '-end')\n\n\nclass TaskFilter(filters.FilterSet):\n    role = filters.CharFilter(name='role__name')\n\n    class Meta:\n        model = Task\n        fields = (\n            'role',\n        )\n\n\ndef filter_instructors(queryset, name, value):\n    instructor_badges = Badge.objects.instructor_badges()\n    if value is True:\n        return queryset.filter(badges__in=instructor_badges)\n    elif value is False:\n        return queryset.exclude(badges__in=instructor_badges)\n    else:\n        return queryset\n\n\nclass PersonFilter(filters.FilterSet):\n    is_instructor = filters.BooleanFilter(method=filter_instructors,\n                                          label='Is instructor?')\n\n    class Meta:\n        model = Person\n        fields = (\n            'badges', 'username', 'personal', 'middle', 'family', 'email',\n            'may_contact', 'publish_profile',\n        )\n        order_by = (\n            'lastname', '-lastname', 'firstname', '-firstname', 'email',\n            '-email',\n        )\n\n    def get_order_by(self, order_value):\n        if order_value == 'firstname':\n            return ['personal', 'middle', 'family']\n        elif order_value == '-firstname':\n            return ['-personal', '-middle', '-family']\n        elif order_value == 'lastname':\n            return ['family', 'middle', 'personal']\n        elif order_value == '-lastname':\n            return ['-family', '-middle', '-personal']\n        return super().get_order_by(order_value)\n\n\nclass InstructorsOverTimeFilter(AMYFilterSet):\n    badges = filters.ModelMultipleChoiceFilter(\n        queryset=Badge.objects.instructor_badges(),\n        label='Badges',\n        lookup_expr='in',\n    )\n\n    class Meta:\n        model = Person\n        fields = [\n            'badges',\n        ]\n\n\nclass WorkshopsOverTimeFilter(AMYFilterSet):\n    tags = filters.ModelMultipleChoiceFilter(\n        queryset=Tag.objects.all(),\n        label='Events with at least one of the following tags:',\n    )\n\n    class Meta:\n        model = Event\n        fields = [\n            'tags',\n        ]\n\n\nclass LearnersOverTimeFilter(AMYFilterSet):\n    tags = filters.ModelMultipleChoiceFilter(\n        queryset=Tag.objects.all(),\n        label='Events with all the following tags:',\n        conjoined=True,\n    )\n\n    class Meta:\n        model = Event\n        fields = [\n            'tags',\n        ]\n", "path": "api/filters.py"}]}