We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[RFE] Add override button when an update for a build is created
Hi,

when I update a golang package in Fedora it is always followed by override of its build. Would it be possible to add a button to open a page (bodhi.fedoraproject.org/overrides/new) with override form filled with package name, build and bug id?

Jan


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `bodhi/views/generic.py`
Content:
```
1 # This program is free software; you can redistribute it and/or
2 # modify it under the terms of the GNU General Public License
3 # as published by the Free Software Foundation; either version 2
4 # of the License, or (at your option) any later version.
5 #
6 # This program is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9 # GNU General Public License for more details.
10 #
11 # You should have received a copy of the GNU General Public License
12 # along with this program; if not, write to the Free Software
13 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
14 
15 import datetime
16 import sqlalchemy as sa
17 
18 import cornice.errors
19 
20 from pyramid.security import authenticated_userid
21 from pyramid.settings import asbool
22 from pyramid.view import view_config, notfound_view_config
23 from pyramid.exceptions import HTTPForbidden
24 
25 from bodhi import log
26 import bodhi.models
27 import bodhi.util
28 
29 
30 def get_top_testers(request):
31     db = request.db
32     blacklist = request.registry.settings.get('stats_blacklist').split()
33     days = int(request.registry.settings.get('top_testers_timeframe', 7))
34     start_time = datetime.datetime.utcnow() - datetime.timedelta(days=days)
35 
36     query = db.query(
37         bodhi.models.User,
38         sa.func.count(bodhi.models.User.comments).label('count_1')
39     ).join(bodhi.models.Comment)
40     query = query\
41         .order_by('count_1 desc')\
42         .filter(bodhi.models.Comment.timestamp > start_time)
43 
44     for user in blacklist:
45         query = query.filter(bodhi.models.User.name != user)
46 
47     return query\
48         .group_by(bodhi.models.User)\
49         .limit(5)\
50         .all()
51 
52 
53 def get_latest_updates(request, critpath, security):
54     db = request.db
55     query = db.query(bodhi.models.Update)
56 
57     if critpath:
58         query = query.filter(
59             bodhi.models.Update.critpath==True)
60     if security:
61         query = query.filter(
62             bodhi.models.Update.type==bodhi.models.UpdateType.security)
63 
64     query = query.filter(
65         bodhi.models.Update.status==bodhi.models.UpdateStatus.testing)
66 
67     query = query.order_by(bodhi.models.Update.date_submitted.desc())
68     return query.limit(5).all()
69 
70 
71 @view_config(route_name='home', renderer='home.html')
72 def home(request):
73     """ Returns data for the frontpage """
74     r = request
75 
76     @request.cache.cache_on_arguments()
77     def work():
78         top_testers = get_top_testers(request)
79         critpath_updates = get_latest_updates(request, True, False)
80         security_updates = get_latest_updates(request, False, True)
81 
82         return {
83             "top_testers": [(obj.__json__(r), n) for obj, n in top_testers],
84             "critpath_updates": [obj.__json__(r) for obj in critpath_updates],
85             "security_updates": [obj.__json__(r) for obj in security_updates],
86         }
87 
88     return work()
89 
90 
91 @view_config(route_name='new_update', renderer='new_update.html')
92 def new_update(request):
93     """ Returns the new update form """
94     user = authenticated_userid(request)
95     if not user:
96         raise HTTPForbidden("You must be logged in.")
97     return dict(
98         update=None,
99         types=reversed(bodhi.models.UpdateType.values()),
100         severities=reversed(bodhi.models.UpdateSeverity.values()),
101         suggestions=reversed(bodhi.models.UpdateSuggestion.values()),
102     )
103 
104 
105 @view_config(route_name='latest_candidates', renderer='json')
106 def latest_candidates(request):
107     """
108     For a given `package`, this method returns the most recent builds tagged
109     into the Release.candidate_tag for all Releases.
110     """
111     koji = request.koji
112     db = request.db
113 
114     @request.cache.cache_on_arguments()
115     def work(pkg, testing):
116         result = []
117         koji.multicall = True
118 
119         releases = db.query(bodhi.models.Release) \
120                      .filter(
121                          bodhi.models.Release.state.in_(
122                              (bodhi.models.ReleaseState.pending,
123                               bodhi.models.ReleaseState.current)))
124 
125         kwargs = dict(package=pkg, latest=True)
126         for release in releases:
127             koji.listTagged(release.candidate_tag, **kwargs)
128             if testing:
129                 koji.listTagged(release.testing_tag, **kwargs)
130                 koji.listTagged(release.pending_testing_tag, **kwargs)
131 
132         builds = koji.multiCall() or []  # Protect against None
133 
134         for build in builds:
135             if isinstance(build, dict):
136                 continue
137             if build and build[0] and build[0][0]:
138                 item = {
139                     'nvr': build[0][0]['nvr'],
140                     'id': build[0][0]['id'],
141                 }
142                 # Prune duplicates
143                 # https://github.com/fedora-infra/bodhi/issues/450
144                 if item not in result:
145                     result.append(item)
146         return result
147 
148 
149     pkg = request.params.get('package')
150     testing = asbool(request.params.get('testing'))
151     log.debug('latest_candidate(%r, %r)' % (pkg, testing))
152 
153     if not pkg:
154         return []
155 
156     result = work(pkg, testing)
157 
158     log.debug(result)
159     return result
160 
161 
162 @view_config(route_name='latest_builds', renderer='json')
163 def latest_builds(request):
164     """ Get a list of the latest builds for a given package.
165 
166     Returns a dictionary of the release dist tag to the latest build.
167     """
168     builds = {}
169     koji = request.koji
170     package = request.params.get('package')
171     for tag_type, tags in bodhi.models.Release.get_tags(request.db)[0].iteritems():
172         for tag in tags:
173             try:
174                 for build in koji.getLatestBuilds(tag, package=package):
175                     builds[tag] = build['nvr']
176             except:  # Things like EPEL don't have pending tags
177                 pass
178     return builds
179 
180 
181 @view_config(route_name='masher_status', renderer='masher.html')
182 def masher_status(request):
183     return dict()
184 
185 
186 @view_config(route_name='new_override', renderer='override.html')
187 def new_override(request):
188     """ Returns the new buildroot override form """
189     user = authenticated_userid(request)
190     if not user:
191         raise HTTPForbidden("You must be logged in.")
192     return dict()
193 
194 
195 @view_config(route_name='api_version', renderer='json')
196 def api_version(request):
197     """ Returns the Bodhi API version """
198     return dict(version=bodhi.util.version())
199 
200 
201 @notfound_view_config(append_slash=True)
202 def notfound_view(context, request):
203     """ Automatically redirects to slash-appended routes.
204 
205     http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/urldispatch.html#redirecting-to-slash-appended-rou
206     """
207     return exception_view(context, request)
208 
209 
210 @view_config(context=HTTPForbidden)
211 @view_config(context=Exception)
212 def exception_view(exc, request):
213     """ A generic error page handler (404s, 403s, 500s, etc..)
214 
215     This is here to catch everything that isn't caught by our cornice error
216     handlers.  When we do catch something, we transform it intpu a cornice
217     Errors object and pass it to our nice cornice error handler.  That way, all
218     the exception presentation and rendering we can keep in one place.
219     """
220 
221     errors = getattr(request, 'errors', [])
222     status = getattr(exc, 'status_code', 500)
223 
224     if status not in (404, 403):
225         log.exception("Error caught.  Handling HTML response.")
226     else:
227         log.warn(str(exc))
228 
229     if not len(errors):
230         description = getattr(exc, 'explanation', None) or str(exc)
231 
232         errors = cornice.errors.Errors(request, status=status)
233         errors.add('unknown', description=description)
234 
235     return bodhi.services.errors.html_handler(errors)
236
```
--- 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/bodhi/views/generic.py b/bodhi/views/generic.py
--- a/bodhi/views/generic.py
+++ b/bodhi/views/generic.py
@@ -186,10 +186,11 @@
 @view_config(route_name='new_override', renderer='override.html')
 def new_override(request):
     """ Returns the new buildroot override form """
+    nvr = request.params.get('nvr')
     user = authenticated_userid(request)
     if not user:
         raise HTTPForbidden("You must be logged in.")
-    return dict()
+    return dict(nvr=nvr)
 
 
 @view_config(route_name='api_version', renderer='json')

{"golden_diff": "diff --git a/bodhi/views/generic.py b/bodhi/views/generic.py\n--- a/bodhi/views/generic.py\n+++ b/bodhi/views/generic.py\n@@ -186,10 +186,11 @@\n @view_config(route_name='new_override', renderer='override.html')\n def new_override(request):\n     \"\"\" Returns the new buildroot override form \"\"\"\n+    nvr = request.params.get('nvr')\n     user = authenticated_userid(request)\n     if not user:\n         raise HTTPForbidden(\"You must be logged in.\")\n-    return dict()\n+    return dict(nvr=nvr)\n \n \n @view_config(route_name='api_version', renderer='json')\n", "issue": "[RFE] Add override button when an update for a build is created\nHi,\n\nwhen I update a golang package in Fedora it is always followed by override of its build. Would it be possible to add a button to open a page (bodhi.fedoraproject.org/overrides/new) with override form filled with package name, build and bug id?\n\nJan\n\n", "before_files": [{"content": "# This program is free software; you can redistribute it and/or\n# modify it under the terms of the GNU General Public License\n# as published by the Free Software Foundation; either version 2\n# of the License, or (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, write to the Free Software\n# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\n\nimport datetime\nimport sqlalchemy as sa\n\nimport cornice.errors\n\nfrom pyramid.security import authenticated_userid\nfrom pyramid.settings import asbool\nfrom pyramid.view import view_config, notfound_view_config\nfrom pyramid.exceptions import HTTPForbidden\n\nfrom bodhi import log\nimport bodhi.models\nimport bodhi.util\n\n\ndef get_top_testers(request):\n    db = request.db\n    blacklist = request.registry.settings.get('stats_blacklist').split()\n    days = int(request.registry.settings.get('top_testers_timeframe', 7))\n    start_time = datetime.datetime.utcnow() - datetime.timedelta(days=days)\n\n    query = db.query(\n        bodhi.models.User,\n        sa.func.count(bodhi.models.User.comments).label('count_1')\n    ).join(bodhi.models.Comment)\n    query = query\\\n        .order_by('count_1 desc')\\\n        .filter(bodhi.models.Comment.timestamp > start_time)\n\n    for user in blacklist:\n        query = query.filter(bodhi.models.User.name != user)\n\n    return query\\\n        .group_by(bodhi.models.User)\\\n        .limit(5)\\\n        .all()\n\n\ndef get_latest_updates(request, critpath, security):\n    db = request.db\n    query = db.query(bodhi.models.Update)\n\n    if critpath:\n        query = query.filter(\n            bodhi.models.Update.critpath==True)\n    if security:\n        query = query.filter(\n            bodhi.models.Update.type==bodhi.models.UpdateType.security)\n\n    query = query.filter(\n        bodhi.models.Update.status==bodhi.models.UpdateStatus.testing)\n\n    query = query.order_by(bodhi.models.Update.date_submitted.desc())\n    return query.limit(5).all()\n\n\n@view_config(route_name='home', renderer='home.html')\ndef home(request):\n    \"\"\" Returns data for the frontpage \"\"\"\n    r = request\n\n    @request.cache.cache_on_arguments()\n    def work():\n        top_testers = get_top_testers(request)\n        critpath_updates = get_latest_updates(request, True, False)\n        security_updates = get_latest_updates(request, False, True)\n\n        return {\n            \"top_testers\": [(obj.__json__(r), n) for obj, n in top_testers],\n            \"critpath_updates\": [obj.__json__(r) for obj in critpath_updates],\n            \"security_updates\": [obj.__json__(r) for obj in security_updates],\n        }\n\n    return work()\n\n\n@view_config(route_name='new_update', renderer='new_update.html')\ndef new_update(request):\n    \"\"\" Returns the new update form \"\"\"\n    user = authenticated_userid(request)\n    if not user:\n        raise HTTPForbidden(\"You must be logged in.\")\n    return dict(\n        update=None,\n        types=reversed(bodhi.models.UpdateType.values()),\n        severities=reversed(bodhi.models.UpdateSeverity.values()),\n        suggestions=reversed(bodhi.models.UpdateSuggestion.values()),\n    )\n\n\n@view_config(route_name='latest_candidates', renderer='json')\ndef latest_candidates(request):\n    \"\"\"\n    For a given `package`, this method returns the most recent builds tagged\n    into the Release.candidate_tag for all Releases.\n    \"\"\"\n    koji = request.koji\n    db = request.db\n\n    @request.cache.cache_on_arguments()\n    def work(pkg, testing):\n        result = []\n        koji.multicall = True\n\n        releases = db.query(bodhi.models.Release) \\\n                     .filter(\n                         bodhi.models.Release.state.in_(\n                             (bodhi.models.ReleaseState.pending,\n                              bodhi.models.ReleaseState.current)))\n\n        kwargs = dict(package=pkg, latest=True)\n        for release in releases:\n            koji.listTagged(release.candidate_tag, **kwargs)\n            if testing:\n                koji.listTagged(release.testing_tag, **kwargs)\n                koji.listTagged(release.pending_testing_tag, **kwargs)\n\n        builds = koji.multiCall() or []  # Protect against None\n\n        for build in builds:\n            if isinstance(build, dict):\n                continue\n            if build and build[0] and build[0][0]:\n                item = {\n                    'nvr': build[0][0]['nvr'],\n                    'id': build[0][0]['id'],\n                }\n                # Prune duplicates\n                # https://github.com/fedora-infra/bodhi/issues/450\n                if item not in result:\n                    result.append(item)\n        return result\n\n\n    pkg = request.params.get('package')\n    testing = asbool(request.params.get('testing'))\n    log.debug('latest_candidate(%r, %r)' % (pkg, testing))\n\n    if not pkg:\n        return []\n\n    result = work(pkg, testing)\n\n    log.debug(result)\n    return result\n\n\n@view_config(route_name='latest_builds', renderer='json')\ndef latest_builds(request):\n    \"\"\" Get a list of the latest builds for a given package.\n\n    Returns a dictionary of the release dist tag to the latest build.\n    \"\"\"\n    builds = {}\n    koji = request.koji\n    package = request.params.get('package')\n    for tag_type, tags in bodhi.models.Release.get_tags(request.db)[0].iteritems():\n        for tag in tags:\n            try:\n                for build in koji.getLatestBuilds(tag, package=package):\n                    builds[tag] = build['nvr']\n            except:  # Things like EPEL don't have pending tags\n                pass\n    return builds\n\n\n@view_config(route_name='masher_status', renderer='masher.html')\ndef masher_status(request):\n    return dict()\n\n\n@view_config(route_name='new_override', renderer='override.html')\ndef new_override(request):\n    \"\"\" Returns the new buildroot override form \"\"\"\n    user = authenticated_userid(request)\n    if not user:\n        raise HTTPForbidden(\"You must be logged in.\")\n    return dict()\n\n\n@view_config(route_name='api_version', renderer='json')\ndef api_version(request):\n    \"\"\" Returns the Bodhi API version \"\"\"\n    return dict(version=bodhi.util.version())\n\n\n@notfound_view_config(append_slash=True)\ndef notfound_view(context, request):\n    \"\"\" Automatically redirects to slash-appended routes.\n\n    http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/urldispatch.html#redirecting-to-slash-appended-rou\n    \"\"\"\n    return exception_view(context, request)\n\n\n@view_config(context=HTTPForbidden)\n@view_config(context=Exception)\ndef exception_view(exc, request):\n    \"\"\" A generic error page handler (404s, 403s, 500s, etc..)\n\n    This is here to catch everything that isn't caught by our cornice error\n    handlers.  When we do catch something, we transform it intpu a cornice\n    Errors object and pass it to our nice cornice error handler.  That way, all\n    the exception presentation and rendering we can keep in one place.\n    \"\"\"\n\n    errors = getattr(request, 'errors', [])\n    status = getattr(exc, 'status_code', 500)\n\n    if status not in (404, 403):\n        log.exception(\"Error caught.  Handling HTML response.\")\n    else:\n        log.warn(str(exc))\n\n    if not len(errors):\n        description = getattr(exc, 'explanation', None) or str(exc)\n\n        errors = cornice.errors.Errors(request, status=status)\n        errors.add('unknown', description=description)\n\n    return bodhi.services.errors.html_handler(errors)\n", "path": "bodhi/views/generic.py"}], "after_files": [{"content": "# This program is free software; you can redistribute it and/or\n# modify it under the terms of the GNU General Public License\n# as published by the Free Software Foundation; either version 2\n# of the License, or (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, write to the Free Software\n# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\n\nimport datetime\nimport sqlalchemy as sa\n\nimport cornice.errors\n\nfrom pyramid.security import authenticated_userid\nfrom pyramid.settings import asbool\nfrom pyramid.view import view_config, notfound_view_config\nfrom pyramid.exceptions import HTTPForbidden\n\nfrom bodhi import log\nimport bodhi.models\nimport bodhi.util\n\n\ndef get_top_testers(request):\n    db = request.db\n    blacklist = request.registry.settings.get('stats_blacklist').split()\n    days = int(request.registry.settings.get('top_testers_timeframe', 7))\n    start_time = datetime.datetime.utcnow() - datetime.timedelta(days=days)\n\n    query = db.query(\n        bodhi.models.User,\n        sa.func.count(bodhi.models.User.comments).label('count_1')\n    ).join(bodhi.models.Comment)\n    query = query\\\n        .order_by('count_1 desc')\\\n        .filter(bodhi.models.Comment.timestamp > start_time)\n\n    for user in blacklist:\n        query = query.filter(bodhi.models.User.name != user)\n\n    return query\\\n        .group_by(bodhi.models.User)\\\n        .limit(5)\\\n        .all()\n\n\ndef get_latest_updates(request, critpath, security):\n    db = request.db\n    query = db.query(bodhi.models.Update)\n\n    if critpath:\n        query = query.filter(\n            bodhi.models.Update.critpath==True)\n    if security:\n        query = query.filter(\n            bodhi.models.Update.type==bodhi.models.UpdateType.security)\n\n    query = query.filter(\n        bodhi.models.Update.status==bodhi.models.UpdateStatus.testing)\n\n    query = query.order_by(bodhi.models.Update.date_submitted.desc())\n    return query.limit(5).all()\n\n\n@view_config(route_name='home', renderer='home.html')\ndef home(request):\n    \"\"\" Returns data for the frontpage \"\"\"\n    r = request\n\n    @request.cache.cache_on_arguments()\n    def work():\n        top_testers = get_top_testers(request)\n        critpath_updates = get_latest_updates(request, True, False)\n        security_updates = get_latest_updates(request, False, True)\n\n        return {\n            \"top_testers\": [(obj.__json__(r), n) for obj, n in top_testers],\n            \"critpath_updates\": [obj.__json__(r) for obj in critpath_updates],\n            \"security_updates\": [obj.__json__(r) for obj in security_updates],\n        }\n\n    return work()\n\n\n@view_config(route_name='new_update', renderer='new_update.html')\ndef new_update(request):\n    \"\"\" Returns the new update form \"\"\"\n    user = authenticated_userid(request)\n    if not user:\n        raise HTTPForbidden(\"You must be logged in.\")\n    return dict(\n        update=None,\n        types=reversed(bodhi.models.UpdateType.values()),\n        severities=reversed(bodhi.models.UpdateSeverity.values()),\n        suggestions=reversed(bodhi.models.UpdateSuggestion.values()),\n    )\n\n\n@view_config(route_name='latest_candidates', renderer='json')\ndef latest_candidates(request):\n    \"\"\"\n    For a given `package`, this method returns the most recent builds tagged\n    into the Release.candidate_tag for all Releases.\n    \"\"\"\n    koji = request.koji\n    db = request.db\n\n    @request.cache.cache_on_arguments()\n    def work(pkg, testing):\n        result = []\n        koji.multicall = True\n\n        releases = db.query(bodhi.models.Release) \\\n                     .filter(\n                         bodhi.models.Release.state.in_(\n                             (bodhi.models.ReleaseState.pending,\n                              bodhi.models.ReleaseState.current)))\n\n        kwargs = dict(package=pkg, latest=True)\n        for release in releases:\n            koji.listTagged(release.candidate_tag, **kwargs)\n            if testing:\n                koji.listTagged(release.testing_tag, **kwargs)\n                koji.listTagged(release.pending_testing_tag, **kwargs)\n\n        builds = koji.multiCall() or []  # Protect against None\n\n        for build in builds:\n            if isinstance(build, dict):\n                continue\n            if build and build[0] and build[0][0]:\n                item = {\n                    'nvr': build[0][0]['nvr'],\n                    'id': build[0][0]['id'],\n                }\n                # Prune duplicates\n                # https://github.com/fedora-infra/bodhi/issues/450\n                if item not in result:\n                    result.append(item)\n        return result\n\n\n    pkg = request.params.get('package')\n    testing = asbool(request.params.get('testing'))\n    log.debug('latest_candidate(%r, %r)' % (pkg, testing))\n\n    if not pkg:\n        return []\n\n    result = work(pkg, testing)\n\n    log.debug(result)\n    return result\n\n\n@view_config(route_name='latest_builds', renderer='json')\ndef latest_builds(request):\n    \"\"\" Get a list of the latest builds for a given package.\n\n    Returns a dictionary of the release dist tag to the latest build.\n    \"\"\"\n    builds = {}\n    koji = request.koji\n    package = request.params.get('package')\n    for tag_type, tags in bodhi.models.Release.get_tags(request.db)[0].iteritems():\n        for tag in tags:\n            try:\n                for build in koji.getLatestBuilds(tag, package=package):\n                    builds[tag] = build['nvr']\n            except:  # Things like EPEL don't have pending tags\n                pass\n    return builds\n\n\n@view_config(route_name='masher_status', renderer='masher.html')\ndef masher_status(request):\n    return dict()\n\n\n@view_config(route_name='new_override', renderer='override.html')\ndef new_override(request):\n    \"\"\" Returns the new buildroot override form \"\"\"\n    nvr = request.params.get('nvr')\n    user = authenticated_userid(request)\n    if not user:\n        raise HTTPForbidden(\"You must be logged in.\")\n    return dict(nvr=nvr)\n\n\n@view_config(route_name='api_version', renderer='json')\ndef api_version(request):\n    \"\"\" Returns the Bodhi API version \"\"\"\n    return dict(version=bodhi.util.version())\n\n\n@notfound_view_config(append_slash=True)\ndef notfound_view(context, request):\n    \"\"\" Automatically redirects to slash-appended routes.\n\n    http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/urldispatch.html#redirecting-to-slash-appended-rou\n    \"\"\"\n    return exception_view(context, request)\n\n\n@view_config(context=HTTPForbidden)\n@view_config(context=Exception)\ndef exception_view(exc, request):\n    \"\"\" A generic error page handler (404s, 403s, 500s, etc..)\n\n    This is here to catch everything that isn't caught by our cornice error\n    handlers.  When we do catch something, we transform it intpu a cornice\n    Errors object and pass it to our nice cornice error handler.  That way, all\n    the exception presentation and rendering we can keep in one place.\n    \"\"\"\n\n    errors = getattr(request, 'errors', [])\n    status = getattr(exc, 'status_code', 500)\n\n    if status not in (404, 403):\n        log.exception(\"Error caught.  Handling HTML response.\")\n    else:\n        log.warn(str(exc))\n\n    if not len(errors):\n        description = getattr(exc, 'explanation', None) or str(exc)\n\n        errors = cornice.errors.Errors(request, status=status)\n        errors.add('unknown', description=description)\n\n    return bodhi.services.errors.html_handler(errors)\n", "path": "bodhi/views/generic.py"}]}