scrapy/scrapy — pull request #582 by kmike (2014-02-04 20:34:28+00:00)
Title: Handle cases when inspect.stack() fails

Ricardo @Panaggio reported an error: creating BaseSpider class fails if the first import is inside jinja2 template. Stacktrace:

```
Traceback:
File "/usr/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
111. response = callback(request, *callback_args, **callback_kwargs)
File "/home/ricardo/demos/tmp/shub/web/utils/apikeys.py" in wrapped
38. return view_func(request, *args, **kwargs)
File "/home/ricardo/demos/tmp/shub/web/utils/httpauth.py" in wrapped
22. return view_func(request, *a, **kw)
File "/usr/lib/python2.7/dist-packages/django/contrib/auth/decorators.py" in _wrapped_view
20. return view_func(request, *args, **kwargs)
File "/home/ricardo/demos/tmp/shub/web/utils/hs.py" in wrapper
26. return func(request, *args, **kwargs)
File "/home/ricardo/demos/tmp/shub/web/utils/projects.py" in wrapper
62. return view(request, *args, **kwargs)
File "/home/ricardo/demos/tmp/shub/web/utils/decorators.py" in wrapper
156. mimetype=mimetype)
File "/usr/lib/python2.7/dist-packages/django/shortcuts/__init__.py" in render_to_response
20. return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
File "/usr/lib/python2.7/dist-packages/django/template/loader.py" in render_to_string
176. return t.render(context_instance)
File "/usr/lib/python2.7/dist-packages/django_jinja/base.py" in render
132. return super(Template, self).render(new_context)
File "/usr/lib/python2.7/dist-packages/jinja2/environment.py" in render
894. return self.environment.handle_exception(exc_info, True)
File "/home/ricardo/demos/tmp/shub/web/templates/projects/project_spiders.jinja" in top-level template code
3. {% import "macros/csrf.jinja" as csrf with context %}
File "/home/ricardo/demos/tmp/shub/web/templates/base_projects.jinja" in top-level template code
1. {% extends "base.jinja" %}
File "/home/ricardo/demos/tmp/shub/web/templates/base.jinja" in top-level template code
2. {% import "macros/js.jinja" as js with context %}
File "/home/ricardo/demos/tmp/shub/web/templates/base_site.jinja" in top-level template code
27. {% block body %}{% endblock %}
File "/home/ricardo/demos/tmp/shub/web/templates/base.jinja" in block "body"
118. {% block content %}
File "/home/ricardo/demos/tmp/shub/web/templates/base.jinja" in block "content"
122.

{% block tabs_content %}{% endblock %}

File "/home/ricardo/demos/tmp/shub/web/templates/projects/project_spiders.jinja" in block "tabs_content"
61.
File "/home/ricardo/demos/tmp/shub/web/utils/jinja2compat/functions.py" in job_url
15. return reverse('job:details', args=(projectid, spider, jobid))
File "/usr/lib/python2.7/dist-packages/django/core/urlresolvers.py" in reverse
476. return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs))
File "/usr/lib/python2.7/dist-packages/django/core/urlresolvers.py" in _reverse_with_prefix
363. possibilities = self.reverse_dict.getlist(lookup_view)
File "/usr/lib/python2.7/dist-packages/django/core/urlresolvers.py" in reverse_dict
276. self._populate()
File "/usr/lib/python2.7/dist-packages/django/core/urlresolvers.py" in _populate
253. for name in pattern.reverse_dict:
File "/usr/lib/python2.7/dist-packages/django/core/urlresolvers.py" in reverse_dict
276. self._populate()
File "/usr/lib/python2.7/dist-packages/django/core/urlresolvers.py" in _populate
265. lookups.appendlist(pattern.callback, (bits, p_pattern, pattern.default_args))
File "/usr/lib/python2.7/dist-packages/django/core/urlresolvers.py" in callback
216. self._callback = get_callable(self._callback_str)
File "/usr/lib/python2.7/dist-packages/django/utils/functional.py" in wrapper
27. result = func(*args)
File "/usr/lib/python2.7/dist-packages/django/core/urlresolvers.py" in get_callable
92. lookup_view = getattr(import_module(mod_name), func_name)
File "/usr/lib/python2.7/dist-packages/django/utils/importlib.py" in import_module
35. __import__(name)
File "/home/ricardo/demos/tmp/shub/web/apps/job/views.py" in
15. from shub.web.utils.items import maybe_extract_items, get_schemas, \
File "/home/ricardo/demos/tmp/shub/web/utils/items.py" in
2. from slybot.spider import IblSpider
File "/usr/lib/pymodules/python2.7/slybot/spider.py" in
9. from scrapy.spider import Spider
File "/usr/lib/pymodules/python2.7/scrapy/spider.py" in
68. BaseSpider = create_deprecated_class('BaseSpider', Spider)
File "/usr/lib/pymodules/python2.7/scrapy/utils/deprecate.py" in create_deprecated_class
98. frm = inspect.stack()[1]
File "/usr/lib/python2.7/inspect.py" in stack
1054. return getouterframes(sys._getframe(1), context)
File "/usr/lib/python2.7/inspect.py" in getouterframes
1032. framelist.append((frame,) + getframeinfo(frame, context))
File "/usr/lib/python2.7/inspect.py" in getframeinfo
1007. lines, lnum = findsource(frame)
File "/usr/lib/python2.7/inspect.py" in findsource
580. if pat.match(lines[lnum]): break

Exception Type: IndexError at /p/1844/spiders/
Exception Value: list index out of range
```

`lines` list contain lines of jinja2 template, not the python source code in this case, and it looks like inspect.stack() gets confused. In this PR such errors are catched and converted to warnings.