If a tween throws an exception, pyramid.tweens.excview_tween_factory raises KeyError and masks the original exception #700

Closed
jamadden opened this Issue Oct 4, 2012 · 1 comment

Comments

Projects
None yet
2 participants

jamadden commented Oct 4, 2012

In both 1.3.4 and 1.4a2, if a user-installed tween throws an exception, it will be caught by pyramid.tweens.excview_tween_factory in an effort to handle it. However, if the exception was thrown "too soon", excview_tween_factory will raise its own KeyError, masking the original exception. This is because it assumes that the request object has a value in its __dict__ for request_iface:

attrs = request.__dict__
...
request_iface = attrs['request_iface']

But under certain circumstances, that value apparently hasn't been set yet. Which can result in a traceback like this (in 1.3.4):

File '/.../python2.7/site-packages/pyramid-1.3.4-py2.7.egg/pyramid/router.py', line 187 in __call__
    response = self.handle_request(request)
File '/.../python2.7/site-packages/pyramid-1.3.4-py2.7.egg/pyramid/tweens.py', line 31 in excview_tween
    request_iface = attrs['request_iface']
KeyError: 'request_iface'

Our workaround (and I don't know if this is right, but it does let the original exception propagate so it can be diagnosed and fixed) was to make that line:

request_iface = attrs.get('request_iface', IRequest)

FWIW, in the application that I've seen this occur, pyramid_tm is installed, and there there are some custom tweens. The underlying exception that resulted in the KeyError before that change looked like this:

File '/.../python2.7/site-packages/pyramid-1.3.4-py2.7.egg/pyramid/router.py', line 187 in __call__
    response = self.handle_request(request)
File '/.../python2.7/site-packages/pyramid-1.3.4-py2.7.egg/pyramid/tweens.py', line 20 in excview_tween
    response = handler(request)
File '/.../python2.7/site-packages/pyramid_tm/__init__.py', line 107 in tm_tween
    return response
File '/.../python2.7/site-packages/pyramid_tm/__init__.py', line 75 in __exit__
    return self._retry_or_raise(t, v, tb)
File '/.../python2.7/site-packages/pyramid_tm/__init__.py', line 60 in _retry_or_raise
    reraise(t, v, tb) # otherwise reraise the exception
File '/.../python2.7/site-packages/pyramid_tm/__init__.py', line 100 in tm_tween
    response = handler(request)
File '/...src/.../appserver/site_tween.py', line 79 in __call__
    uid = pyramid.security.authenticated_userid( request )
File '/.../python2.7/site-packages/pyramid-1.3.4-py2.7.egg/pyramid/security.py', line 70 in authenticated_userid
    return policy.authenticated_userid(request)
File '/.../python2.7/site-packages/pyramid_who-0.3-py2.7.egg/pyramid_who/whov2.py', line 54 in authenticated_userid
    groups = self._callback(identity, request)
File '/...src/.../appserver/pyramid_auth.py', line 175 in __call__
    if not self.user_exists( username ):
UnboundLocalError: local variable 'username' referenced before assignment

mcdonc closed this in 34d4cd0 Nov 4, 2012

Owner

mcdonc commented Nov 4, 2012

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment