prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  search_phase_execution_exception in ES on huuuge ?page params
  https://sentry.prod.mozaws.net/operations/mdn-prod/issues/6620806/
  
  ```
  TransportError: TransportError(500, u'search_phase_execution_exception', u'Result window is too large, from + size must be less than or equal to: [10000] but was [33010]. See the scroll api for a more efficient way to request large data sets. This limit can be set by changing the [index.max_result_window] index level setting.')
  (24 additional frame(s) were not displayed)
  ...
    File "rest_framework/views.py", line 492, in dispatch
      response = handler(request, *args, **kwargs)
    File "rest_framework/generics.py", line 201, in get
      return self.list(request, *args, **kwargs)
    File "rest_framework/mixins.py", line 42, in list
      page = self.paginate_queryset(queryset)
    File "rest_framework/generics.py", line 173, in paginate_queryset
      return self.paginator.paginate_queryset(queryset, self.request, view=self)
    File "rest_framework/pagination.py", line 204, in paginate_queryset
      self.page = paginator.page(page_number)
  
  TransportError: TransportError(500, u'search_phase_execution_exception', u'Result window is too large, from + size must be less than or equal to: [10000] but was [33010]. See the scroll api for a more efficient way to request large data sets. This limit can be set by changing the [index.max_result_window] index level setting.')
  ```
  
  </issue>
  <code>
  [start of kuma/search/paginator.py]
  1 from django.core.paginator import EmptyPage, Page, PageNotAnInteger, Paginator
  2 from django.utils.functional import cached_property
  3 
  4 
  5 class SearchPaginator(Paginator):
  6     """
  7     A better paginator for search results
  8 
  9     The normal Paginator does a .count() query and then a slice. Since ES
  10     results contain the total number of results, we can take an optimistic
  11     slice and then adjust the count.
  12     """
  13 
  14     def __init__(self, *args, **kwargs):
  15         super(SearchPaginator, self).__init__(*args, **kwargs)
  16         self._result_total = None
  17 
  18     def validate_number(self, number):
  19         """
  20         Validates the given 1-based page number.
  21 
  22         This class overrides the default behavior and ignores the upper bound.
  23         """
  24         try:
  25             number = int(number)
  26         except (TypeError, ValueError):
  27             raise PageNotAnInteger('That page number is not an integer')
  28         if number < 1:
  29             raise EmptyPage('That page number is less than 1')
  30         return number
  31 
  32     def page(self, number):
  33         """
  34         Returns a page object.
  35 
  36         This class overrides the default behavior and ignores "orphans" and
  37         assigns the count from the ES result to the Paginator.
  38         """
  39         number = self.validate_number(number)
  40         bottom = (number - 1) * self.per_page
  41         top = bottom + self.per_page
  42 
  43         # Force the search to evaluate and then attach the count. We want to
  44         # avoid an extra useless query even if there are no results, so we
  45         # directly fetch the count from hits.
  46         result = self.object_list[bottom:top].execute()
  47         page = Page(result.hits, number, self)
  48         # Set the count to the results after post_filter
  49         self._result_total = result.hits.total
  50         # Also store the aggregations, if any.
  51         page.aggregations = getattr(result, 'aggregations', None)
  52 
  53         # Now that we have the count validate that the page number isn't higher
  54         # than the possible number of pages and adjust accordingly.
  55         if number > self.num_pages:
  56             if number == 1 and self.allow_empty_first_page:
  57                 pass
  58             else:
  59                 raise EmptyPage('That page contains no results')
  60         return page
  61 
  62     @cached_property
  63     def count(self):
  64         """
  65         Returns the total number of results.
  66 
  67         Paginator's count property will call .count() on the search object,
  68         which returns results before the pre_filter. This will result in a
  69         count that is too high. Instead, use 'total' from the results,
  70         executing if needed.
  71         """
  72         if self._result_total is not None:
  73             return self._result_total
  74         return self.object_list.execute().hits.total
  75
  [end of kuma/search/paginator.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/kuma/search/paginator.py b/kuma/search/paginator.py
  --- a/kuma/search/paginator.py
  +++ b/kuma/search/paginator.py
  @@ -1,4 +1,5 @@
  -from django.core.paginator import EmptyPage, Page, PageNotAnInteger, Paginator
  +from django.core.paginator import (
  +    EmptyPage, InvalidPage, Page, PageNotAnInteger, Paginator)
   from django.utils.functional import cached_property
   
   
  @@ -19,7 +20,7 @@
           """
           Validates the given 1-based page number.
   
  -        This class overrides the default behavior and ignores the upper bound.
  +        We also check that the number isn't too large.
           """
           try:
               number = int(number)
  @@ -27,6 +28,19 @@
               raise PageNotAnInteger('That page number is not an integer')
           if number < 1:
               raise EmptyPage('That page number is less than 1')
  +
  +        if number >= 1000:
  +            # Anything >=1,000 will result in a hard error in
  +            # Elasticsearch which would happen before we even get a chance
  +            # to validate that the range is too big. The error you would
  +            # get from Elasticsearch 6.x is something like this:
  +            #
  +            #     Result window is too large, from + size must be less
  +            #     than or equal to: [10000] but was [11000].
  +            #
  +            # See https://github.com/mdn/kuma/issues/6092
  +            raise InvalidPage('Page number too large')
  +
           return number
   
       def page(self, number):
  
verification_info: {"golden_diff": "diff --git a/kuma/search/paginator.py b/kuma/search/paginator.py\n--- a/kuma/search/paginator.py\n+++ b/kuma/search/paginator.py\n@@ -1,4 +1,5 @@\n-from django.core.paginator import EmptyPage, Page, PageNotAnInteger, Paginator\n+from django.core.paginator import (\n+    EmptyPage, InvalidPage, Page, PageNotAnInteger, Paginator)\n from django.utils.functional import cached_property\n \n \n@@ -19,7 +20,7 @@\n         \"\"\"\n         Validates the given 1-based page number.\n \n-        This class overrides the default behavior and ignores the upper bound.\n+        We also check that the number isn't too large.\n         \"\"\"\n         try:\n             number = int(number)\n@@ -27,6 +28,19 @@\n             raise PageNotAnInteger('That page number is not an integer')\n         if number < 1:\n             raise EmptyPage('That page number is less than 1')\n+\n+        if number >= 1000:\n+            # Anything >=1,000 will result in a hard error in\n+            # Elasticsearch which would happen before we even get a chance\n+            # to validate that the range is too big. The error you would\n+            # get from Elasticsearch 6.x is something like this:\n+            #\n+            #     Result window is too large, from + size must be less\n+            #     than or equal to: [10000] but was [11000].\n+            #\n+            # See https://github.com/mdn/kuma/issues/6092\n+            raise InvalidPage('Page number too large')\n+\n         return number\n \n     def page(self, number):\n", "issue": "search_phase_execution_exception in ES on huuuge ?page params\nhttps://sentry.prod.mozaws.net/operations/mdn-prod/issues/6620806/\n\n```\nTransportError: TransportError(500, u'search_phase_execution_exception', u'Result window is too large, from + size must be less than or equal to: [10000] but was [33010]. See the scroll api for a more efficient way to request large data sets. This limit can be set by changing the [index.max_result_window] index level setting.')\n(24 additional frame(s) were not displayed)\n...\n  File \"rest_framework/views.py\", line 492, in dispatch\n    response = handler(request, *args, **kwargs)\n  File \"rest_framework/generics.py\", line 201, in get\n    return self.list(request, *args, **kwargs)\n  File \"rest_framework/mixins.py\", line 42, in list\n    page = self.paginate_queryset(queryset)\n  File \"rest_framework/generics.py\", line 173, in paginate_queryset\n    return self.paginator.paginate_queryset(queryset, self.request, view=self)\n  File \"rest_framework/pagination.py\", line 204, in paginate_queryset\n    self.page = paginator.page(page_number)\n\nTransportError: TransportError(500, u'search_phase_execution_exception', u'Result window is too large, from + size must be less than or equal to: [10000] but was [33010]. See the scroll api for a more efficient way to request large data sets. This limit can be set by changing the [index.max_result_window] index level setting.')\n```\n", "before_files": [{"content": "from django.core.paginator import EmptyPage, Page, PageNotAnInteger, Paginator\nfrom django.utils.functional import cached_property\n\n\nclass SearchPaginator(Paginator):\n    \"\"\"\n    A better paginator for search results\n\n    The normal Paginator does a .count() query and then a slice. Since ES\n    results contain the total number of results, we can take an optimistic\n    slice and then adjust the count.\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        super(SearchPaginator, self).__init__(*args, **kwargs)\n        self._result_total = None\n\n    def validate_number(self, number):\n        \"\"\"\n        Validates the given 1-based page number.\n\n        This class overrides the default behavior and ignores the upper bound.\n        \"\"\"\n        try:\n            number = int(number)\n        except (TypeError, ValueError):\n            raise PageNotAnInteger('That page number is not an integer')\n        if number < 1:\n            raise EmptyPage('That page number is less than 1')\n        return number\n\n    def page(self, number):\n        \"\"\"\n        Returns a page object.\n\n        This class overrides the default behavior and ignores \"orphans\" and\n        assigns the count from the ES result to the Paginator.\n        \"\"\"\n        number = self.validate_number(number)\n        bottom = (number - 1) * self.per_page\n        top = bottom + self.per_page\n\n        # Force the search to evaluate and then attach the count. We want to\n        # avoid an extra useless query even if there are no results, so we\n        # directly fetch the count from hits.\n        result = self.object_list[bottom:top].execute()\n        page = Page(result.hits, number, self)\n        # Set the count to the results after post_filter\n        self._result_total = result.hits.total\n        # Also store the aggregations, if any.\n        page.aggregations = getattr(result, 'aggregations', None)\n\n        # Now that we have the count validate that the page number isn't higher\n        # than the possible number of pages and adjust accordingly.\n        if number > self.num_pages:\n            if number == 1 and self.allow_empty_first_page:\n                pass\n            else:\n                raise EmptyPage('That page contains no results')\n        return page\n\n    @cached_property\n    def count(self):\n        \"\"\"\n        Returns the total number of results.\n\n        Paginator's count property will call .count() on the search object,\n        which returns results before the pre_filter. This will result in a\n        count that is too high. Instead, use 'total' from the results,\n        executing if needed.\n        \"\"\"\n        if self._result_total is not None:\n            return self._result_total\n        return self.object_list.execute().hits.total\n", "path": "kuma/search/paginator.py"}]}