We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Default search message
We need to add a message for when a search doesn't match any packages.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `warehouse/utils/paginate.py`
Content:
```
1 # Licensed under the Apache License, Version 2.0 (the "License");
2 # you may not use this file except in compliance with the License.
3 # You may obtain a copy of the License at
4 #
5 # http://www.apache.org/licenses/LICENSE-2.0
6 #
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS,
9 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 # See the License for the specific language governing permissions and
11 # limitations under the License.
12 
13 from paginate import Page
14 
15 
16 class _ElasticsearchWrapper:
17 
18     def __init__(self, query):
19         self.query = query
20         self.results = None
21 
22     def __getitem__(self, range):
23         if self.results is not None:
24             raise RuntimeError("Cannot reslice after having already sliced.")
25         self.results = self.query[range].execute()
26 
27         return list(self.results)
28 
29     def __len__(self):
30         if self.results is None:
31             raise RuntimeError("Cannot get length until a slice.")
32         return self.results.hits.total
33 
34 
35 def ElasticsearchPage(*args, **kwargs):  # noqa
36     kwargs.setdefault("wrapper_class", _ElasticsearchWrapper)
37     return Page(*args, **kwargs)
38 
39 
40 def paginate_url_factory(request, query_arg="page"):
41     def make_url(page):
42         query_seq = [
43             (k, v)
44             for k, vs in request.GET.dict_of_lists().items()
45             for v in vs
46             if k != query_arg
47         ]
48         query_seq += [(query_arg, page)]
49         return request.current_route_path(_query=query_seq)
50     return make_url
51
```

Path: `warehouse/views.py`
Content:
```
1 # Licensed under the Apache License, Version 2.0 (the "License");
2 # you may not use this file except in compliance with the License.
3 # You may obtain a copy of the License at
4 #
5 # http://www.apache.org/licenses/LICENSE-2.0
6 #
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS,
9 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 # See the License for the specific language governing permissions and
11 # limitations under the License.
12 
13 from pyramid.httpexceptions import (
14     HTTPException, HTTPSeeOther, HTTPMovedPermanently,
15 )
16 from pyramid.view import (
17     notfound_view_config, forbidden_view_config, view_config,
18 )
19 from sqlalchemy import func
20 from sqlalchemy.orm import aliased, joinedload
21 
22 from warehouse.accounts import REDIRECT_FIELD_NAME
23 from warehouse.accounts.models import User
24 from warehouse.cache.origin import origin_cache
25 from warehouse.cache.http import cache_control
26 from warehouse.csrf import csrf_exempt
27 from warehouse.packaging.models import Project, Release, File
28 from warehouse.sessions import uses_session
29 from warehouse.utils.row_counter import RowCount
30 from warehouse.utils.paginate import ElasticsearchPage, paginate_url_factory
31 
32 
33 @view_config(context=HTTPException, decorator=[csrf_exempt])
34 @notfound_view_config(
35     append_slash=HTTPMovedPermanently,
36     decorator=[csrf_exempt],
37 )
38 def httpexception_view(exc, request):
39     return exc
40 
41 
42 @forbidden_view_config()
43 def forbidden(exc, request):
44     # If the forbidden error is because the user isn't logged in, then we'll
45     # redirect them to the log in page.
46     if request.authenticated_userid is None:
47         url = request.route_url(
48             "accounts.login",
49             _query={REDIRECT_FIELD_NAME: request.path_qs},
50         )
51         return HTTPSeeOther(url)
52 
53     # If we've reached here, then the user is logged in and they are genuinely
54     # not allowed to access this page.
55     # TODO: Style the forbidden page.
56     return exc
57 
58 
59 @view_config(
60     route_name="robots.txt",
61     renderer="robots.txt",
62     decorator=[
63         cache_control(1 * 24 * 60 * 60),         # 1 day
64         origin_cache(
65             1 * 24 * 60 * 60,                    # 1 day
66             stale_while_revalidate=6 * 60 * 60,  # 6 hours
67             stale_if_error=1 * 24 * 60 * 60,     # 1 day
68         ),
69     ],
70 )
71 def robotstxt(request):
72     request.response.content_type = "text/plain"
73     return {}
74 
75 
76 @view_config(
77     route_name="index",
78     renderer="index.html",
79     decorator=[
80         origin_cache(
81             1 * 60 * 60,                      # 1 hour
82             stale_while_revalidate=10 * 60,   # 10 minutes
83             stale_if_error=1 * 24 * 60 * 60,  # 1 day
84             keys=["all-projects"],
85         ),
86     ]
87 )
88 def index(request):
89     project_names = [
90         r[0] for r in (
91             request.db.query(File.name)
92                    .group_by(File.name)
93                    .order_by(func.sum(File.downloads).desc())
94                    .limit(5)
95                    .all())
96     ]
97     release_a = aliased(
98         Release,
99         request.db.query(Release)
100                   .distinct(Release.name)
101                   .filter(Release.name.in_(project_names))
102                   .order_by(Release.name, Release._pypi_ordering.desc())
103                   .subquery(),
104     )
105     top_projects = (
106         request.db.query(release_a)
107                .options(joinedload(release_a.project),
108                         joinedload(release_a.uploader))
109                .order_by(func.array_idx(project_names, release_a.name))
110                .all()
111     )
112 
113     latest_releases = (
114         request.db.query(Release)
115                   .options(joinedload(Release.project),
116                            joinedload(Release.uploader))
117                   .order_by(Release.created.desc())
118                   .limit(5)
119                   .all()
120     )
121 
122     counts = dict(
123         request.db.query(RowCount.table_name, RowCount.count)
124                   .filter(
125                       RowCount.table_name.in_([
126                           Project.__tablename__,
127                           Release.__tablename__,
128                           File.__tablename__,
129                           User.__tablename__,
130                       ]))
131                   .all()
132     )
133 
134     return {
135         "latest_releases": latest_releases,
136         "top_projects": top_projects,
137         "num_projects": counts.get(Project.__tablename__, 0),
138         "num_releases": counts.get(Release.__tablename__, 0),
139         "num_files": counts.get(File.__tablename__, 0),
140         "num_users": counts.get(User.__tablename__, 0),
141     }
142 
143 
144 @view_config(
145     route_name="search",
146     renderer="search/results.html",
147     decorator=[
148         origin_cache(
149             1 * 60 * 60,                      # 1 hour
150             stale_while_revalidate=10 * 60,   # 10 minutes
151             stale_if_error=1 * 24 * 60 * 60,  # 1 day
152             keys=["all-projects"],
153         )
154     ],
155 )
156 def search(request):
157     if request.params.get("q"):
158         query = request.es.query(
159             "multi_match",
160             query=request.params["q"],
161             fields=[
162                 "name", "version", "author", "author_email", "maintainer",
163                 "maintainer_email", "home_page", "license", "summary",
164                 "description", "keywords", "platform", "download_url",
165             ],
166         )
167     else:
168         query = request.es.query()
169 
170     page = ElasticsearchPage(
171         query,
172         page=int(request.params.get("page", 1)),
173         url_maker=paginate_url_factory(request),
174     )
175 
176     return {"page": page, "term": request.params.get("q")}
177 
178 
179 @view_config(
180     route_name="includes.current-user-indicator",
181     renderer="includes/current-user-indicator.html",
182     decorator=[uses_session],
183 )
184 def current_user_indicator(request):
185     return {}
186
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/warehouse/utils/paginate.py b/warehouse/utils/paginate.py
--- a/warehouse/utils/paginate.py
+++ b/warehouse/utils/paginate.py
@@ -18,12 +18,18 @@
     def __init__(self, query):
         self.query = query
         self.results = None
+        self.best_guess = None
 
     def __getitem__(self, range):
         if self.results is not None:
             raise RuntimeError("Cannot reslice after having already sliced.")
         self.results = self.query[range].execute()
 
+        if hasattr(self.results, "suggest"):
+            suggestion = self.results.suggest.name_suggestion[0]
+            if suggestion.options:
+                self.best_guess = suggestion.options[0]
+
         return list(self.results)
 
     def __len__(self):
diff --git a/warehouse/views.py b/warehouse/views.py
--- a/warehouse/views.py
+++ b/warehouse/views.py
@@ -163,6 +163,10 @@
                 "maintainer_email", "home_page", "license", "summary",
                 "description", "keywords", "platform", "download_url",
             ],
+        ).suggest(
+            name="name_suggestion",
+            text=request.params["q"],
+            term={"field": "name"}
         )
     else:
         query = request.es.query()

{"golden_diff": "diff --git a/warehouse/utils/paginate.py b/warehouse/utils/paginate.py\n--- a/warehouse/utils/paginate.py\n+++ b/warehouse/utils/paginate.py\n@@ -18,12 +18,18 @@\n     def __init__(self, query):\n         self.query = query\n         self.results = None\n+        self.best_guess = None\n \n     def __getitem__(self, range):\n         if self.results is not None:\n             raise RuntimeError(\"Cannot reslice after having already sliced.\")\n         self.results = self.query[range].execute()\n \n+        if hasattr(self.results, \"suggest\"):\n+            suggestion = self.results.suggest.name_suggestion[0]\n+            if suggestion.options:\n+                self.best_guess = suggestion.options[0]\n+\n         return list(self.results)\n \n     def __len__(self):\ndiff --git a/warehouse/views.py b/warehouse/views.py\n--- a/warehouse/views.py\n+++ b/warehouse/views.py\n@@ -163,6 +163,10 @@\n                 \"maintainer_email\", \"home_page\", \"license\", \"summary\",\n                 \"description\", \"keywords\", \"platform\", \"download_url\",\n             ],\n+        ).suggest(\n+            name=\"name_suggestion\",\n+            text=request.params[\"q\"],\n+            term={\"field\": \"name\"}\n         )\n     else:\n         query = request.es.query()\n", "issue": "Default search message\nWe need to add a message for when a search doesn't match any packages.\n\n", "before_files": [{"content": "# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom paginate import Page\n\n\nclass _ElasticsearchWrapper:\n\n    def __init__(self, query):\n        self.query = query\n        self.results = None\n\n    def __getitem__(self, range):\n        if self.results is not None:\n            raise RuntimeError(\"Cannot reslice after having already sliced.\")\n        self.results = self.query[range].execute()\n\n        return list(self.results)\n\n    def __len__(self):\n        if self.results is None:\n            raise RuntimeError(\"Cannot get length until a slice.\")\n        return self.results.hits.total\n\n\ndef ElasticsearchPage(*args, **kwargs):  # noqa\n    kwargs.setdefault(\"wrapper_class\", _ElasticsearchWrapper)\n    return Page(*args, **kwargs)\n\n\ndef paginate_url_factory(request, query_arg=\"page\"):\n    def make_url(page):\n        query_seq = [\n            (k, v)\n            for k, vs in request.GET.dict_of_lists().items()\n            for v in vs\n            if k != query_arg\n        ]\n        query_seq += [(query_arg, page)]\n        return request.current_route_path(_query=query_seq)\n    return make_url\n", "path": "warehouse/utils/paginate.py"}, {"content": "# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom pyramid.httpexceptions import (\n    HTTPException, HTTPSeeOther, HTTPMovedPermanently,\n)\nfrom pyramid.view import (\n    notfound_view_config, forbidden_view_config, view_config,\n)\nfrom sqlalchemy import func\nfrom sqlalchemy.orm import aliased, joinedload\n\nfrom warehouse.accounts import REDIRECT_FIELD_NAME\nfrom warehouse.accounts.models import User\nfrom warehouse.cache.origin import origin_cache\nfrom warehouse.cache.http import cache_control\nfrom warehouse.csrf import csrf_exempt\nfrom warehouse.packaging.models import Project, Release, File\nfrom warehouse.sessions import uses_session\nfrom warehouse.utils.row_counter import RowCount\nfrom warehouse.utils.paginate import ElasticsearchPage, paginate_url_factory\n\n\n@view_config(context=HTTPException, decorator=[csrf_exempt])\n@notfound_view_config(\n    append_slash=HTTPMovedPermanently,\n    decorator=[csrf_exempt],\n)\ndef httpexception_view(exc, request):\n    return exc\n\n\n@forbidden_view_config()\ndef forbidden(exc, request):\n    # If the forbidden error is because the user isn't logged in, then we'll\n    # redirect them to the log in page.\n    if request.authenticated_userid is None:\n        url = request.route_url(\n            \"accounts.login\",\n            _query={REDIRECT_FIELD_NAME: request.path_qs},\n        )\n        return HTTPSeeOther(url)\n\n    # If we've reached here, then the user is logged in and they are genuinely\n    # not allowed to access this page.\n    # TODO: Style the forbidden page.\n    return exc\n\n\n@view_config(\n    route_name=\"robots.txt\",\n    renderer=\"robots.txt\",\n    decorator=[\n        cache_control(1 * 24 * 60 * 60),         # 1 day\n        origin_cache(\n            1 * 24 * 60 * 60,                    # 1 day\n            stale_while_revalidate=6 * 60 * 60,  # 6 hours\n            stale_if_error=1 * 24 * 60 * 60,     # 1 day\n        ),\n    ],\n)\ndef robotstxt(request):\n    request.response.content_type = \"text/plain\"\n    return {}\n\n\n@view_config(\n    route_name=\"index\",\n    renderer=\"index.html\",\n    decorator=[\n        origin_cache(\n            1 * 60 * 60,                      # 1 hour\n            stale_while_revalidate=10 * 60,   # 10 minutes\n            stale_if_error=1 * 24 * 60 * 60,  # 1 day\n            keys=[\"all-projects\"],\n        ),\n    ]\n)\ndef index(request):\n    project_names = [\n        r[0] for r in (\n            request.db.query(File.name)\n                   .group_by(File.name)\n                   .order_by(func.sum(File.downloads).desc())\n                   .limit(5)\n                   .all())\n    ]\n    release_a = aliased(\n        Release,\n        request.db.query(Release)\n                  .distinct(Release.name)\n                  .filter(Release.name.in_(project_names))\n                  .order_by(Release.name, Release._pypi_ordering.desc())\n                  .subquery(),\n    )\n    top_projects = (\n        request.db.query(release_a)\n               .options(joinedload(release_a.project),\n                        joinedload(release_a.uploader))\n               .order_by(func.array_idx(project_names, release_a.name))\n               .all()\n    )\n\n    latest_releases = (\n        request.db.query(Release)\n                  .options(joinedload(Release.project),\n                           joinedload(Release.uploader))\n                  .order_by(Release.created.desc())\n                  .limit(5)\n                  .all()\n    )\n\n    counts = dict(\n        request.db.query(RowCount.table_name, RowCount.count)\n                  .filter(\n                      RowCount.table_name.in_([\n                          Project.__tablename__,\n                          Release.__tablename__,\n                          File.__tablename__,\n                          User.__tablename__,\n                      ]))\n                  .all()\n    )\n\n    return {\n        \"latest_releases\": latest_releases,\n        \"top_projects\": top_projects,\n        \"num_projects\": counts.get(Project.__tablename__, 0),\n        \"num_releases\": counts.get(Release.__tablename__, 0),\n        \"num_files\": counts.get(File.__tablename__, 0),\n        \"num_users\": counts.get(User.__tablename__, 0),\n    }\n\n\n@view_config(\n    route_name=\"search\",\n    renderer=\"search/results.html\",\n    decorator=[\n        origin_cache(\n            1 * 60 * 60,                      # 1 hour\n            stale_while_revalidate=10 * 60,   # 10 minutes\n            stale_if_error=1 * 24 * 60 * 60,  # 1 day\n            keys=[\"all-projects\"],\n        )\n    ],\n)\ndef search(request):\n    if request.params.get(\"q\"):\n        query = request.es.query(\n            \"multi_match\",\n            query=request.params[\"q\"],\n            fields=[\n                \"name\", \"version\", \"author\", \"author_email\", \"maintainer\",\n                \"maintainer_email\", \"home_page\", \"license\", \"summary\",\n                \"description\", \"keywords\", \"platform\", \"download_url\",\n            ],\n        )\n    else:\n        query = request.es.query()\n\n    page = ElasticsearchPage(\n        query,\n        page=int(request.params.get(\"page\", 1)),\n        url_maker=paginate_url_factory(request),\n    )\n\n    return {\"page\": page, \"term\": request.params.get(\"q\")}\n\n\n@view_config(\n    route_name=\"includes.current-user-indicator\",\n    renderer=\"includes/current-user-indicator.html\",\n    decorator=[uses_session],\n)\ndef current_user_indicator(request):\n    return {}\n", "path": "warehouse/views.py"}], "after_files": [{"content": "# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom paginate import Page\n\n\nclass _ElasticsearchWrapper:\n\n    def __init__(self, query):\n        self.query = query\n        self.results = None\n        self.best_guess = None\n\n    def __getitem__(self, range):\n        if self.results is not None:\n            raise RuntimeError(\"Cannot reslice after having already sliced.\")\n        self.results = self.query[range].execute()\n\n        if hasattr(self.results, \"suggest\"):\n            suggestion = self.results.suggest.name_suggestion[0]\n            if suggestion.options:\n                self.best_guess = suggestion.options[0]\n\n        return list(self.results)\n\n    def __len__(self):\n        if self.results is None:\n            raise RuntimeError(\"Cannot get length until a slice.\")\n        return self.results.hits.total\n\n\ndef ElasticsearchPage(*args, **kwargs):  # noqa\n    kwargs.setdefault(\"wrapper_class\", _ElasticsearchWrapper)\n    return Page(*args, **kwargs)\n\n\ndef paginate_url_factory(request, query_arg=\"page\"):\n    def make_url(page):\n        query_seq = [\n            (k, v)\n            for k, vs in request.GET.dict_of_lists().items()\n            for v in vs\n            if k != query_arg\n        ]\n        query_seq += [(query_arg, page)]\n        return request.current_route_path(_query=query_seq)\n    return make_url\n", "path": "warehouse/utils/paginate.py"}, {"content": "# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom pyramid.httpexceptions import (\n    HTTPException, HTTPSeeOther, HTTPMovedPermanently,\n)\nfrom pyramid.view import (\n    notfound_view_config, forbidden_view_config, view_config,\n)\nfrom sqlalchemy import func\nfrom sqlalchemy.orm import aliased, joinedload\n\nfrom warehouse.accounts import REDIRECT_FIELD_NAME\nfrom warehouse.accounts.models import User\nfrom warehouse.cache.origin import origin_cache\nfrom warehouse.cache.http import cache_control\nfrom warehouse.csrf import csrf_exempt\nfrom warehouse.packaging.models import Project, Release, File\nfrom warehouse.sessions import uses_session\nfrom warehouse.utils.row_counter import RowCount\nfrom warehouse.utils.paginate import ElasticsearchPage, paginate_url_factory\n\n\n@view_config(context=HTTPException, decorator=[csrf_exempt])\n@notfound_view_config(\n    append_slash=HTTPMovedPermanently,\n    decorator=[csrf_exempt],\n)\ndef httpexception_view(exc, request):\n    return exc\n\n\n@forbidden_view_config()\ndef forbidden(exc, request):\n    # If the forbidden error is because the user isn't logged in, then we'll\n    # redirect them to the log in page.\n    if request.authenticated_userid is None:\n        url = request.route_url(\n            \"accounts.login\",\n            _query={REDIRECT_FIELD_NAME: request.path_qs},\n        )\n        return HTTPSeeOther(url)\n\n    # If we've reached here, then the user is logged in and they are genuinely\n    # not allowed to access this page.\n    # TODO: Style the forbidden page.\n    return exc\n\n\n@view_config(\n    route_name=\"robots.txt\",\n    renderer=\"robots.txt\",\n    decorator=[\n        cache_control(1 * 24 * 60 * 60),         # 1 day\n        origin_cache(\n            1 * 24 * 60 * 60,                    # 1 day\n            stale_while_revalidate=6 * 60 * 60,  # 6 hours\n            stale_if_error=1 * 24 * 60 * 60,     # 1 day\n        ),\n    ],\n)\ndef robotstxt(request):\n    request.response.content_type = \"text/plain\"\n    return {}\n\n\n@view_config(\n    route_name=\"index\",\n    renderer=\"index.html\",\n    decorator=[\n        origin_cache(\n            1 * 60 * 60,                      # 1 hour\n            stale_while_revalidate=10 * 60,   # 10 minutes\n            stale_if_error=1 * 24 * 60 * 60,  # 1 day\n            keys=[\"all-projects\"],\n        ),\n    ]\n)\ndef index(request):\n    project_names = [\n        r[0] for r in (\n            request.db.query(File.name)\n                   .group_by(File.name)\n                   .order_by(func.sum(File.downloads).desc())\n                   .limit(5)\n                   .all())\n    ]\n    release_a = aliased(\n        Release,\n        request.db.query(Release)\n                  .distinct(Release.name)\n                  .filter(Release.name.in_(project_names))\n                  .order_by(Release.name, Release._pypi_ordering.desc())\n                  .subquery(),\n    )\n    top_projects = (\n        request.db.query(release_a)\n               .options(joinedload(release_a.project),\n                        joinedload(release_a.uploader))\n               .order_by(func.array_idx(project_names, release_a.name))\n               .all()\n    )\n\n    latest_releases = (\n        request.db.query(Release)\n                  .options(joinedload(Release.project),\n                           joinedload(Release.uploader))\n                  .order_by(Release.created.desc())\n                  .limit(5)\n                  .all()\n    )\n\n    counts = dict(\n        request.db.query(RowCount.table_name, RowCount.count)\n                  .filter(\n                      RowCount.table_name.in_([\n                          Project.__tablename__,\n                          Release.__tablename__,\n                          File.__tablename__,\n                          User.__tablename__,\n                      ]))\n                  .all()\n    )\n\n    return {\n        \"latest_releases\": latest_releases,\n        \"top_projects\": top_projects,\n        \"num_projects\": counts.get(Project.__tablename__, 0),\n        \"num_releases\": counts.get(Release.__tablename__, 0),\n        \"num_files\": counts.get(File.__tablename__, 0),\n        \"num_users\": counts.get(User.__tablename__, 0),\n    }\n\n\n@view_config(\n    route_name=\"search\",\n    renderer=\"search/results.html\",\n    decorator=[\n        origin_cache(\n            1 * 60 * 60,                      # 1 hour\n            stale_while_revalidate=10 * 60,   # 10 minutes\n            stale_if_error=1 * 24 * 60 * 60,  # 1 day\n            keys=[\"all-projects\"],\n        )\n    ],\n)\ndef search(request):\n    if request.params.get(\"q\"):\n        query = request.es.query(\n            \"multi_match\",\n            query=request.params[\"q\"],\n            fields=[\n                \"name\", \"version\", \"author\", \"author_email\", \"maintainer\",\n                \"maintainer_email\", \"home_page\", \"license\", \"summary\",\n                \"description\", \"keywords\", \"platform\", \"download_url\",\n            ],\n        ).suggest(\n            name=\"name_suggestion\",\n            text=request.params[\"q\"],\n            term={\"field\": \"name\"}\n        )\n    else:\n        query = request.es.query()\n\n    page = ElasticsearchPage(\n        query,\n        page=int(request.params.get(\"page\", 1)),\n        url_maker=paginate_url_factory(request),\n    )\n\n    return {\"page\": page, \"term\": request.params.get(\"q\")}\n\n\n@view_config(\n    route_name=\"includes.current-user-indicator\",\n    renderer=\"includes/current-user-indicator.html\",\n    decorator=[uses_session],\n)\ndef current_user_indicator(request):\n    return {}\n", "path": "warehouse/views.py"}]}