{{{#!python
def render(self, context):
try:
template = self.template.resolve(context)
# Does this quack like a Template?
if not callable(getattr(template, 'render', None)):
# If not, we'll try get_template
template = get_template(template)
values = {
name: var.resolve(context)
for name, var in six.iteritems(self.extra_context)
}
if self.isolated_context:
return template.render(context.new(values))
with context.push(**values):
return template.render(context)
except:
if settings.TEMPLATE_DEBUG:
raise
return ''
}}}
See from GitHub:
https://github.com/django/django/blob/master/django/template/loader_tags.py#L146
I change the bare except in line 146 to:
{{{#!python
except (TemplateDoesNotExist, TemplateSyntaxError):
}}}
and ran the test suite:
{{{#!sh
./runtests.py --settings=test_sqlite template_tests
}}}
Here is the output:
https://gist.github.com/berkerpeksag/ab84b067a552951abd9c
So, is the usage of bare except correct?
Thanks!
--
Ticket URL: <https://code.djangoproject.com/ticket/21189>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* cc: bmispelon@… (added)
* needs_better_patch: => 0
* component: Template system => Core (Other)
* needs_tests: => 0
* needs_docs: => 0
* stage: Unreviewed => Accepted
Comment:
Hi,
The idea behind the bare `except` is that rendering should catch all
exceptions and, depending on the value of `settings.TEMPLATE_DEBUG`,
either output an empty string or re-raise it (it will be caught later down
the chain to display the familiar error page).
This is by design and it explains the test failures you get when you
restrict the types of exceptions being caught.
With that said, the usage of a bare `except` clause is usually a code
smell (and pep8 advises against it [1]). In this case for example, `except
Exception` might be better suited (`except Exception` catches all
exceptions except those like `SystemExit` which you generally don't want
to catch).
I did an audit of django's code to find the other instances of using bare
except clauses and I think there's room for improvement so I'll mark this
ticket as `accepted` but broaden its scope to cover other bare except
clauses.
The difficulty here lies in finding out which exception type(s) is
appropriate to catch (in general, while using `except Exception` is an
improvement over `except`, it's still too broad in most cases). This has
to be done on a case-by-case basis and usually require a good
understanding of the surrounding code.
So here's the list of places where I think `except` clauses should be
qualified.
Note that the line numbers are likely to get out of sync as time passes
(as I'm typing this, the current HEAD on master is at
c4fdd859ecba0b8e6dac6eca06429e66925722bd).
You can use `grep -rn except: django/` to find the occurences in your own
checkout.
*
[https://github.com/django/django/blob/master/django/template/loader_tags.py#L146
django/template/loader_tags.py:146]
*
[https://github.com/django/django/blob/master/django/core/management/sql.py#L66
django/core/management/sql.py:66]
*
[https://github.com/django/django/blob/master/django/core/management/__init__.py#L212
django/core/management/__init__.py:212]
*
[https://github.com/django/django/blob/master/django/core/management/__init__.py#L363
django/core/management/__init__.py:363]
*
[https://github.com/django/django/blob/master/django/core/mail/backends/smtp.py#L59
django/core/mail/backends/smtp.py:59]
*
[https://github.com/django/django/blob/master/django/core/mail/backends/smtp.py#L75
django/core/mail/backends/smtp.py:75]
*
[https://github.com/django/django/blob/master/django/core/mail/backends/smtp.py#L116
django/core/mail/backends/smtp.py:116]
*
[https://github.com/django/django/blob/master/django/core/mail/backends/console.py#L31
django/core/mail/backends/console.py:31]
*
[https://github.com/django/django/blob/master/django/http/request.py#L225
django/http/request.py:225]
*
[https://github.com/django/django/blob/master/django/http/multipartparser.py#L165
django/http/multipartparser.py:165]
*
[https://github.com/django/django/blob/master/django/http/multipartparser.py#L549
django/http/multipartparser.py:549]
*
[https://github.com/django/django/blob/master/django/http/multipartparser.py#L574
django/http/multipartparser.py:574]
*
[https://github.com/django/django/blob/master/django/db/backends/oracle/base.py#L620
django/db/backends/oracle/base.py:620]
*
[https://github.com/django/django/blob/master/django/contrib/gis/geoip/__init__.py#L17
django/contrib/gis/geoip/__init__.py:17]
*
[https://github.com/django/django/blob/master/django/contrib/gis/sitemaps/views.py#L83
django/contrib/gis/sitemaps/views.py:83]
*
[https://github.com/django/django/blob/master/django/contrib/gis/geos/libgeos.py#L68
django/contrib/gis/geos/libgeos.py:68]
*
[https://github.com/django/django/blob/master/django/contrib/gis/geos/libgeos.py#L78
django/contrib/gis/geos/libgeos.py:78]
*
[https://github.com/django/django/blob/master/django/contrib/gis/db/backends/base.py#L348
django/contrib/gis/db/backends/base.py:348]
*
[https://github.com/django/django/blob/master/django/contrib/gis/db/backends/spatialite/operations.py#L247
django/contrib/gis/db/backends/spatialite/operations.py:247]
*
[https://github.com/django/django/blob/master/django/contrib/gis/forms/fields.py#L76
django/contrib/gis/forms/fields.py:76]
*
[https://github.com/django/django/blob/master/django/contrib/gis/tests/inspectapp/tests.py#L142
django/contrib/gis/tests/inspectapp/tests.py:142]
*
[https://github.com/django/django/blob/master/django/contrib/gis/tests/layermap/tests.py#L153
django/contrib/gis/tests/layermap/tests.py:153]
*
[https://github.com/django/django/blob/master/django/contrib/gis/utils/layermapping.py#L340
django/contrib/gis/utils/layermapping.py:340]
*
[https://github.com/django/django/blob/master/django/contrib/gis/utils/layermapping.py#L368
django/contrib/gis/utils/layermapping.py:368]
*
[https://github.com/django/django/blob/master/django/contrib/gis/utils/__init__.py#L14
django/contrib/gis/utils/__init__.py:14]
There's also two instances where I'm not sure whether a bare `except` is
appropriate or not:
*
[https://github.com/django/django/blob/master/django/utils/module_loading.py#L60
django/utils/module_loading.py:60]
*
[https://github.com/django/django/blob/master/django/contrib/flatpages/middleware.py#L15
django/contrib/flatpages/middleware.py:15]
Finally, for completeness's sake, here are the instances of bare `except`
clauses which I believe are correct:
*
[https://github.com/django/django/blob/master/django/test/_doctest.py#L1321
django/test/_doctest.py:1321]
*
[https://github.com/django/django/blob/master/django/test/_doctest.py#L2631
django/test/_doctest.py:2631]
*
[https://github.com/django/django/blob/master/django/core/handlers/base.py#L153
django/core/handlers/base.py:153]
*
[https://github.com/django/django/blob/master/django/core/handlers/base.py#L167
django/core/handlers/base.py:167]
*
[https://github.com/django/django/blob/master/django/core/handlers/base.py#L183
django/core/handlers/base.py:183]
*
[https://github.com/django/django/blob/master/django/core/handlers/base.py#L193
django/core/handlers/base.py:193]
*
[https://github.com/django/django/blob/master/django/core/handlers/base.py#L203
django/core/handlers/base.py:203]
*
[https://github.com/django/django/blob/master/django/core/handlers/wsgi.py#L188
django/core/handlers/wsgi.py:188]
*
[https://github.com/django/django/blob/master/django/db/transaction.py#L485
django/db/transaction.py:485]
*
[https://github.com/django/django/blob/master/django/contrib/gis/utils/layermapping.py#L591
django/contrib/gis/utils/layermapping.py:591]
Of course, this doesn't have to be tackled all at once, so if anyone wants
to offer a patch for only one or two items in the list, I'd be happy to
review it (you also get bonus point if you can provided a testcase that
illustrates incorrect silencing of a particular type of exception).
Thanks for the report (and sorry for the big wall of text :) ).
[1] http://www.python.org/dev/peps/pep-0008/#programming-recommendations
--
Ticket URL: <https://code.djangoproject.com/ticket/21189#comment:1>
* status: new => closed
* resolution: => fixed
Comment:
In [changeset:"20472aa827669d2b83b74e521504e88e18d086a1"]:
{{{
#!CommitTicketReference repository=""
revision="20472aa827669d2b83b74e521504e88e18d086a1"
Fixed #21189: Cleaned up usage of bare except clauses.
Thanks to berkerpeksag for the report and to claudep
for the review.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/21189#comment:2>