I get this error
object has no attribute 'im_func'
with this
class Test(object):
def __init__(self, f):
self.func = f
def __call__( self, *args ):
return self.func(*args)
pylons code:
class TestController(BaseController):
@Test
def index(self):
return 'hello world'
full error:
File '/env/lib/python2.5/site-packages/WebError-0.10.2-py2.5.egg/weberror/evalexception.py', line 431 in respond
app_iter = self.application(environ, detect_start_response)
File '/env/lib/python2.5/site-packages/repoze.who-1.0.18-py2.5.egg/repoze/who/middleware.py', line 107 in __call__
app_iter = app(environ, wrapper.wrap_start_response)
File '/env/lib/python2.5/site-packages/Beaker-1.5.3-py2.5.egg/beaker/middleware.py', line 73 in __call__
return self.app(environ, start_response)
File '/env/lib/python2.5/site-packages/Beaker-1.5.3-py2.5.egg/beaker/middleware.py', line 152 in __call__
return self.wrap_app(environ, session_start_response)
File '/env/lib/python2.5/site-packages/Routes-1.10.3-py2.5.egg/routes/middleware.py', line 130 in __call__
response = self.app(environ, start_response)
File '/env/lib/python2.5/site-packages/Pylons-0.9.7-py2.5.egg/pylons/wsgiapp.py', line 125 in __call__
response = self.dispatch(controller, environ, start_response)
File '/env/lib/python2.5/site-packages/Pylons-0.9.7-py2.5.egg/pylons/wsgiapp.py', line 324 in dispatch
return controller(environ, start_response)
File '/project/lib/base.py', line 18 in __call__
return WSGIController.__call__(self, environ, start_response)
File '/env/lib/python2.5/site-packages/Pylons-0.9.7-py2.5.egg/pylons/controllers/core.py', line 221 in __call__
response = self._dispatch_call()
File '/env/lib/python2.5/site-packages/Pylons-0.9.7-py2.5.egg/pylons/controllers/core.py', line 172 in _dispatch_call
response = self._inspect_call(func)
File '/env/lib/python2.5/site-packages/Pylons-0.9.7-py2.5.egg/pylons/controllers/core.py', line 80 in _inspect_call
argspec = cached_argspecs[func.im_func]
AttributeError: 'Test' object has no attribute 'im_func'
TestController.indexends up an instance ofTest, with no access to theTestControllerobject. Also, only user defined methods (which must be functions, not objects) have anim_funcattribute. You’ll need to instantiateTestand have its__call__method return a function so that it can be passed theTestControllerinstance.What’s happening
A decorator:
is equivalent to:
In your original code,
creates an instance of
Testand passesindexto the constructor. The resulting object is assigned to theindexproperty ofTestController.Test.__call__doesn’t get invoked until you try to callTestController.index. Withtcan instance ofTestController,tc.index()is equivalent totc.index.__call__()orTest.__call__(tc.index).The problem is that within the call to
Test.__call__, we’ve lost the reference totc. It didn’t exist whenTest.indexwas defined, so there’s no way of saving it. Moreover, it looks like Pylons performs some magic on the methods and it expectstc.indexto be a user defined method (which has anim_funcproperty), not an object (which doesn`t).The approach I show you changes when
Test.__call__is invoked and the type ofTestController.index.The definition of
TestController.indexis equivalent to:Because
TestController.indexis a function rather than an object,tc.index()is equivalent toTestController.index(tc), and we don’t lose the reference totc.