Opened 10 years ago

Closed 10 years ago

Last modified 10 years ago

#21348 closed Bug (wontfix)

RuntimeError: maximum recursion depth exceeded while calling a Python object

Reported by: Val Neekman Owned by: nobody
Component: Database layer (models, ORM) Version: dev
Severity: Normal Keywords: recursion depth
Cc: dcramer@… Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Sample project to take Django 1.6 for a spin.

Project works well with 1.6b4 and runs into the following problem as soon as I upgrade to 1.6c1.

Env:

  1. Linux Ubuntu 12.04
  2. Python 2.7.3
  3. Sqlite3
  4. Django 1.6c1

Done:

  1. Did a diff of tags: 1.6b4 and 1.6c1 and nothing jump out at me.
  2. Searched Google and djangoproject.com for a duplicate ticket or a possible fix. No result!

Creating the ticket to share my finding for speedier clouser.

Note: There is no 1.6-rc-1 yet, hence setting version to Master.

Please review and share you thoughts on this.

Thanks

---- LOG ----

RuntimeError
RuntimeError: maximum recursion depth exceeded while calling a Python object

Traceback (most recent call last)
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/dozer/leak.py", line 111, in call
return self.app(environ, start_response)
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/contrib/staticfiles/handlers.py", line 67, in call
return self.application(environ, start_response)
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/core/handlers/wsgi.py", line 206, in call
response = self.get_response(request)
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/core/handlers/base.py", line 196, in get_response
response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/core/handlers/base.py", line 231, in handle_uncaught_exception
return debug.technical_500_response(request, *exc_info)
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/core/handlers/base.py", line 90, in get_response
response = middleware_method(request)
File "/mnt/hgfs/Projects/workon/web/djangoware/djangoware/apps/userware/middleware/logout.py", line 14, in process_request
if request.user.is_authenticated():
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/utils/functional.py", line 213, in inner
self._setup()
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/utils/functional.py", line 298, in _setup
self._wrapped = self._setupfunc()
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/contrib/auth/middleware.py", line 18, in <lambda>
request.user = SimpleLazyObject(lambda: get_user(request))
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/contrib/auth/middleware.py", line 10, in get_user
request._cached_user = auth.get_user(request)
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/contrib/auth/init.py", line 137, in get_user
user = backend.get_user(user_id) or AnonymousUser()
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/contrib/auth/backends.py", line 69, in get_user
return UserModel._default_manager.get(pk=user_id)
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/db/models/manager.py", line 151, in get
return self.get_queryset().get(*args, kwargs)
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/db/models/query.py", line 301, in get
num = len(clone)
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/db/models/query.py", line 77, in len
self._fetch_all()
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/db/models/query.py", line 854, in _fetch_all
self._result_cache = list(self.iterator())
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/db/models/query.py", line 220, in iterator
for row in compiler.results_iter():
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 710, in results_iter
for rows in self.execute_sql(MULTI):
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 781, in execute_sql
cursor.execute(sql, params)
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/devserver/modules/sql.py", line 77, in execute
return super(DatabaseStatTracker, self).execute(sql, params)
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/db/backends/util.py", line 69, in execute
return super(CursorDebugWrapper, self).execute(sql, params)

............. hundreds of recursion on line 69 as above ...................

File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/db/backends/util.py", line 69, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/db/backends/util.py", line 73, in execute
sql = self.db.ops.last_executed_query(self.cursor, sql, params)
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/db/backends/init.py", line 854, in last_executed_query
u_params = tuple(to_unicode(val) for val in params)
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/db/backends/init.py", line 854, in <genexpr>
u_params = tuple(to_unicode(val) for val in params)
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/db/backends/init.py", line 852, in <lambda>
to_unicode = lambda s: force_text(s, strings_only=True, errors='replace')
File "/mnt/hgfs/Projects/.web-virenv/djangoware/lib/python2.7/site-packages/django/utils/encoding.py", line 93, in force_text
if isinstance(s, six.text_type):
RuntimeError: maximum recursion depth exceeded while calling a Python object
The debugger caught an exception in your WSGI application. You can now look at the traceback which led to the error.
To switch between the interactive traceback and the plaintext one, you can click on the "Traceback" headline. From the text traceback you can also create a paste of it. For code execution mouse-over the frame you want to debug and click on the console icon on the right side.

You can execute arbitrary Python code in the stack frames and there are some extra helpers available for introspection:

dump() shows all variables in the frame
dump(obj) dumps all that's known about the object

Change History (9)

comment:1 by Anssi Kääriäinen, 10 years ago

It seems you are using django-devserver (https://github.com/dcramer/django-devserver/). My guess is that django-devserver's DatabaseStatTracker (a DebugCursorWrapper subclass) and changes in 0d74bdaf0c39feb8ec303dbbdbcadba70e46eecb do not interact well.

With the information available it seems very likely that this is an error in django-devserver, not in Django itself. Having a call "return super(CursorDebugWrapper, self).execute(sql, params)" recurse indefinitely should not happen unless there is monkey-patching going on...

comment:2 by Val Neekman, 10 years ago

I have tested and now can confirm that the cause of the error is indeed django-devserver (0.7.0).

I cannot confirm any monkey-patching, so perhaps we leave the ticket "open" for the time being?

comment:3 by Anssi Kääriäinen, 10 years ago

Severity: Release blockerNormal

OK for me. But I'll remove the release blocker.

comment:4 by David Cramer, 10 years ago

Cc: dcramer@… added

This likely breaks a ton of injection stuff thats out there (probably all written by me, so I take blame). I didn't really dig into it too much yet, but nothing was obvious in my 5 seconds spent looking at the code.

comment:5 by Anssi Kääriäinen, 10 years ago

Resolution: wontfix
Status: newclosed

It isn't good that django-devserver is broken. But Django must be able to assume that super(CursorDebugWrapper, self).execute(...) really calls the super method, not the calling method again.

comment:6 by kosz85@…, 10 years ago

It happen in devserver when you don't have debug_toolbar, then in throw ImportError and your DatabaseStatTracker will iherit from CursorDebugWrapper. It's not django error.

I checked and it is monkeypatching. They inherit from CursorDebugWrapper, and store as old class, but thay change util.CursorDebugWrapper to point DatabaseStatTracker, so when it go to CursorDebugWrapper and call super, this name point to DatabaseStatTracker so its like:
super(CursorDebugWrapper, slef) == super(DatabaseStatTracker, self) so it loops. There would help some kind of settings to overwrite default CursorWrapper without monkeypatching which like you see is risky.

If you need it badly just rename at line 26 CursorDebugWrapper to CursorWrapper, then it won't crash when using CursorDebugWrapper.

comment:7 by anonymous, 10 years ago

sorry line 52 ;)

comment:8 by beau@…, 10 years ago

There's now an open pull request in django-devserver that fixes this issue.

comment:9 by Cal Leeming, 10 years ago

This has now been fixed in devserver 0.8.0.

Note: See TracTickets for help on using tickets.
Back to Top