I tested with the tg2.0 and tg2.1 code today.

I used checkouts:
     svn co http://svn.turbogears.org/branches/2.0
     hg clone http://bitbucket.org/mramm/tg-21

The "'function' object has no attribute 'decoration'" error is not  
fixed in the latest 2.0 from SVN.

It is avoided entirely in 2.1, because you can't directly subclass  
DecoratedController, since it's not a WSGIController anymore.

What isn't addressed, however, is that the _perform_call(self, func,  
args) method in TGController (inherited from ObjectDispatchController  
in 2.0 and from Dispatcher in 2.1) still ignores the 'action'  
parameter of routing paths. It still dispatches the request according  
to object dispatch, even if a route has specified the action to  
render. (This happens in 2.0 and 2.1). This is the behaviour that the  
parents in this thread were trying to avoid by subclassing  
DecoratedController.

I continue to work around this problem by using my RoutingController  
(subclassing DecoratedController in 2.0 and TGController in 2.1)  
[code: http://simplestation.com/locomotion/routes-in-tg2]. Which,  
essentially, implements TGController's _perform_call() method, but  
removes all Object Dispatch logic.

I think a superior solution would be to have TGController's  
_perform_call() method detect if a route was active, and if that  
route specified an action side-step object dispatch routing. Perhaps  
by checking the values in args['environ']['pylons.routes_dict'].

Perhaps this change could go into 2.1, and something like the  
RoutingController could go into 2.0, to prevent breaking anybody's  
apps that already rely on the current functionality.

Thoughts? Is anybody else out there using Routes in tg2?

-- Anthony

On 15-May-09, at 11:14 AM, anthonyt wrote:
> I haven't had a chance to check out the latest patch, but since the
> thread of conversation has picked up again, I figured I'd share
> something I wrote a couple days ago: http://simplestation.com/ 
> locomotion/routes-in-tg2/
>
> I'm going to guess my solution is very similar to the solution in the
> patch, but doesn't require updating TG itself.
>
>
> On May 13, 6:43 pm, Mark Ramm <[email protected]> wrote:
>> Oops, I thought this was fixed because of Gustavo's message, but it
>> seems that it wasn't -- so I'm committing a fix to the 2.0 branch
>> tonight.
>>
>> Basically the fix is to do this:
>>
>>         #Special case __before__ and __after__ so don't need to be
>> @exposed
>>         if controller.__name__ in ['__before__', '__after__']:
>>             return controller(*remainder, **dict(params))
>>
>> inside of _perform_call so that __before__ and __after__ don't need
>> decoration attributes since they really are special methods that you
>> want called on every request.
>>
>> I'd very much apriciate it if someone could verify that routes work
>> from the hg.turbogears.org repo.  The whole routing sytem is  
>> different
>> here, but I think we'll need to apply the same fix there.   I think
>> this is a missing test that we ought to add, since using routes is
>> something we want to encourage.
>>
>> --Mark Ramm
>>
>> On Mar 18, 7:29 pm, Carl <[email protected]> wrote:
>>
>>> Correction :-(. It doesn't really work. The Pylons request object
>>> doesn't have a response_type attribute. This line in the controller
>>> method raises AttributeError for 'response_type'
>>
>>> if pylons.request.response_type == 'application/json':
>>>   ...
>>
>>> I'll leave it to the experts to figure it out. Please do.
>>
>>> Hjhj
>>
>>> Danke schein, Carl
>>
>>> On Mar 18, 11:12 am, Carl <[email protected]> wrote:
>>
>>>> I found a workaround, but it's not pretty. The solution is to  
>>>> override
>>>> the _perform_call() method of DecoratedController in your  
>>>> controller:
>>
>>>>     def _perform_call(self, controller, params, remainder=None):
>>>>         # If not a decorated method just call it (needed for
>>>> __before__ and __after__)
>>>>         if not hasattr(controller, 'decoration'):
>>>>             if remainder is None:
>>>>                 remainder = []
>>
>>>>             return controller(*remainder, **dict(params))
>>>>         return DecoratedController._perform_call(self, controller,
>>>> params, remainder)
>>
>>>> Carl
>>
>>>> On Mar 17, 1:59 am, Raphael Slinckx <[email protected]> wrote:
>>
>>>>> See also this post from me from a while ago:http:// 
>>>>> groups.google.com/group/turbogears/browse_thread/thread/ab9c8a...
>>
>>>>> No solution though..
>>
>>>>> On Mar 17, 2:00 am, Carl <[email protected]> wrote:
>>
>>>>>> Ok. This is on a new quickstarted project with my changes for  
>>>>>> custom
>>>>>> routes. Here is the traceback and the changes to app_cfg.py and
>>>>>> root.py are bellow. If it's helpful I can upload the entire  
>>>>>> project.
>>
>>>>>> URL:http://localhost:8080/prefix/1/about
>>>>>> File '/Users/carl/tg2env/lib/python2.5/site-packages/ 
>>>>>> WebError-0.10.1-
>>>>>> py2.5.egg/weberror/evalexception.py', line 431 in respond
>>>>>>   app_iter = self.application(environ, detect_start_response)
>>>>>> File '/Users/carl/tg2env/lib/python2.5/site-packages/ 
>>>>>> TurboGears2-2.0b7-
>>>>>> py2.5.egg/tg/configuration.py', line 631 in wrapper
>>>>>>   return app(environ, start_response)
>>>>>> File '/Users/carl/tg2env/lib/python2.5/site-packages/ 
>>>>>> TurboGears2-2.0b7-
>>>>>> py2.5.egg/tg/configuration.py', line 534 in remover
>>>>>>   return app(environ, start_response)
>>>>>> File '/Users/carl/tg2env/lib/python2.5/site-packages/ 
>>>>>> repoze.tm2-1.0a3-
>>>>>> py2.5.egg/repoze/tm/__init__.py', line 19 in __call__
>>>>>>   result = self.application(environ, save_status_and_headers)
>>>>>> File '/Users/carl/tg2env/lib/python2.5/site-packages/
>>>>>> ToscaWidgets-0.9.5dev_20081026-py2.5.egg/tw/core/ 
>>>>>> middleware.py', line
>>>>>> 36 in __call__
>>>>>>   return self.wsgi_app(environ, start_response)
>>>>>> File '/Users/carl/tg2env/lib/python2.5/site-packages/
>>>>>> ToscaWidgets-0.9.5dev_20081026-py2.5.egg/tw/core/ 
>>>>>> middleware.py', line
>>>>>> 59 in wsgi_app
>>>>>>   resp = req.get_response(self.application)
>>>>>> File 'build/bdist.macosx-10.3-i386/egg/webob/__init__.py',  
>>>>>> line 1325
>>>>>> in get_response
>>>>>> File 'build/bdist.macosx-10.3-i386/egg/webob/__init__.py',  
>>>>>> line 1293
>>>>>> in call_application
>>>>>> File '/Users/carl/tg2env/lib/python2.5/site-packages/
>>>>>> ToscaWidgets-0.9.5dev_20081026-py2.5.egg/tw/core/
>>>>>> resource_injector.py', line 67 in _injector
>>>>>>   resp = req.get_response(app)
>>>>>> File 'build/bdist.macosx-10.3-i386/egg/webob/__init__.py',  
>>>>>> line 1325
>>>>>> in get_response
>>>>>> File 'build/bdist.macosx-10.3-i386/egg/webob/__init__.py',  
>>>>>> line 1293
>>>>>> in call_application
>>>>>> File '/Users/carl/tg2env/lib/python2.5/site-packages/ 
>>>>>> Beaker-1.2.2-
>>>>>> py2.5.egg/beaker/middleware.py', line 81 in __call__
>>>>>>   return self.app(environ, start_response)
>>>>>> File '/Users/carl/tg2env/lib/python2.5/site-packages/ 
>>>>>> Beaker-1.2.2-
>>>>>> py2.5.egg/beaker/middleware.py', line 160 in __call__
>>>>>>   return self.wrap_app(environ, session_start_response)
>>>>>> File '/Users/carl/tg2env/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 '/Users/carl/tg2env/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 '/Users/carl/tg2env/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 '/Users/carl/tg2env/lib/python2.5/site-packages/ 
>>>>>> Pylons-0.9.7-
>>>>>> py2.5.egg/pylons/controllers/core.py', line 217 in __call__
>>>>>>   response = self._inspect_call(self.__before__)
>>>>>> File '/Users/carl/tg2env/lib/python2.5/site-packages/ 
>>>>>> Pylons-0.9.7-
>>>>>> py2.5.egg/pylons/controllers/core.py', line 107 in _inspect_call
>>>>>>   result = self._perform_call(func, args)
>>>>>> File '/Users/carl/tg2env/lib/python2.5/site-packages/ 
>>>>>> TurboGears2-2.0b7-
>>>>>> py2.5.egg/tg/controllers.py', line 125 in _perform_call
>>>>>>   controller.decoration.run_hooks('before_validate', remainder,
>>>>>> AttributeError: 'function' object has no attribute 'decoration'
>>
>>>>>> Here is my app_cfg.py:
>>
>>>>>> # -*- coding: utf-8 -*-
>>>>>> """
>>>>>> Global configuration file for TG2-specific settings in custom- 
>>>>>> routes.
>>
>>>>>> This file complements development/deployment.ini.
>>
>>>>>> """
>>
>>>>>> from tg.configuration import AppConfig, Bunch
>>>>>> # Carl: needed for setup_custom_routes
>>>>>> from tg.configuration import Mapper, config
>>
>>>>>> import custom_routes
>>>>>> from custom_routes import model
>>>>>> from custom_routes.lib import app_globals, helpers
>>
>>>>>> # Carl: added custom routes function to override the default in
>>>>>> AppConfig
>>>>>> def custom_setup_routes(self):
>>>>>>     """Setup the default TG2 routes
>>
>>>>>>     Override this and set up your own routes maps if you want  
>>>>>> to use
>>>>>> routes.
>>>>>>     """
>>>>>>     map = Mapper(directory=config['pylons.paths']['controllers'],
>>>>>>                 always_scan=config['debug'])
>>
>>>>>>     map.connect('prefix', 'prefix/{id}/{action}',  
>>>>>> controller='root')
>>
>>>>>>     # Setup a default route for the root of object dispatch
>>>>>>     map.connect('*url', controller='root',
>>>>>> action='routes_placeholder')
>>
>>>>>>     config['routes.map'] = map
>>
>>>>>> # Carl: assign the custom routes function to AppConfig.
>>>>>> # It's equivalent to subclassing AppConfig in this case
>>>>>> AppConfig.setup_routes = custom_setup_routes
>>
>>>>>> base_config = AppConfig()
>>>>>> base_config.renderers = []
>>
>>>>>> base_config.package = custom_routes
>>
>>>>>> #Set the default renderer
>>>>>> base_config.default_renderer = 'genshi'
>>>>>> base_config.renderers.append('genshi')
>>>>>> # if you want raw speed and have installed chameleon.genshi
>>>>>> # you should try to use this renderer instead.
>>>>>> # warning: for the moment chameleon does not handle i18n  
>>>>>> translations
>>>>>> #base_config.renderers.append('chameleon_genshi')
>>
>>>>>> #Configure the base SQLALchemy Setup
>>>>>> base_config.use_sqlalchemy = True
>>>>>> base_config.model = custom_routes.model
>>
>>>>>> And here are my changes to the RootController:
>>
>>>>>> # -*- coding: utf-8 -*-
>>>>>> """Main Controller"""
>>
>>>>>> from tg import expose, flash, require, url, request, redirect,
>>>>>> validate
>>>>>> from pylons.i18n import ugettext as _, lazy_ugettext as l_
>>
>>>>>> from custom_routes.lib.base import BaseController
>>>>>> # Carl: DecoratedController will be the base class for the root
>>>>>> controller
>>>>>> from tg.controllers import DecoratedController
>>
>>>>>> from custom_routes.model import DBSession, metadata
>>>>>> from custom_routes.controllers.error import ErrorController
>>
>>>>>> __all__ = ['RootController']
>>
>>>>>> class RootController(DecoratedController):
>>>>>> #class RootController(BaseController):
>>>>>> # The rest is the same
>>
>>>>>> On Mar 16, 1:09 pm, Mark Ramm <[email protected]>  
>>>>>> wrote:
>>
>>>>>>> A code sample, and traceback would help us help you better ;)
>>
>>>>>>> On Mon, Mar 16, 2009 at 2:43 PM, Carl <[email protected]>  
>>>>>>> wrote:
>>
>>>>>>>> Hello Gustavo,
>>>>>>>> What didn't work for me is that if my controller I just   
>>>>>>>> subclasses
>>>>>>>> the BaseController, then it looks like the routing in  
>>>>>>>> app_cfg.py is
>>>>>>>> ignored. TGController  calls a _get_routing_info() function  
>>>>>>>> defined in
>>>>>>>> ObjectDispatchController that does just object dispatch.
>>
>>>>>>>> Gigi
>>
>>>>>>>> On Mar 16, 9:46 am, Gustavo Narea <[email protected]>  
>>>>>>>> wrote:
>>>>>>>>> Hello, Carl.
>>
>>>>>>>>> On Saturday March 14, 2009 16:49:17 Carl wrote:
>>
>>>>>>>>>> I tried it but it didn't work for me. Maybe I got the URL  
>>>>>>>>>> syntax
>>
>> ...
>>
>> read more ยป
>
> >


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"TurboGears" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/turbogears?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to