Graham Dumpleton
grahamd at dscpl.com.au
Tue Mar 1 18:05:11 EST 2005
One of the issues in using mod_python.publisher is that the req.path_info data is used in performing traversal to work out which Python method is to be called or which object to be accessed. The contents of req.path_info must match exactly what object structure is available. There is no ability for mod_python.publisher to match as far as it can and then supply what is left as additional path_info for use by the called method. There were however ways of doing it if you constructed your own handler and didn't use mod_python.publisher. Now others may see the following solution to not being able to process additional path_info in mod_python.publisher as obvious, and I admit I have toyed with the idea in my mind for a while but hadn't actually tried it. Now that I have, thought I would post it here along with some more thoughts on what could be done in the future if/when mod_python.publisher is updated to support new style classes. The code I have been playing with is: ### class _extra_path_info: def __init__(self,callback,path=""): self.__callback = callback self.__path = path def __call__(self,req): req.extra_path_info = self.__path return self.__callback(req) def __getattr__(self,name): if name[0] != '_': return _extra_path_info(self.__callback,'/'.join([self.__path,name])) raise AttributeError() class A: def __init__(self): self.method = _extra_path_info(self.method) def method(self,req): return req.path_info,req.extra_path_info a = A() def method(req): return req.path_info,req.extra_path_info method = _extra_path_info(method) ### The intent with the code is that the _extra_path_info class is used to wrap a function or method. By doing this, as a URL is now resolved against the object structure, a transient instance of _extra_path_info is created for each element of the path that extends beyond that which would have matched the function or method in the first place. When the end of the URL is reached and a call is made against the object, the original wrapped method is called, with req.extra_path_info being set to be the part of the URL beyond that which matched the original method. The result of all this for various URLs is as follows: '/method' --> ('/method', '') '/method/a/b/c' --> ('/method/a/b/c', '/a/b/c') '/a/method' --> ('/a/method', '') '/a/method/a/b/c' --> ('/a/method/a/b/c/', '/a/b/c') Now I don't recollect ever seeing anything on the mailing list or in any other documentation talking about such a technique, but it could be quite useful in certain type of circumstances. The only issue with it is that _extra_path_info has to be customised for each method being wrapped if the method also accepts form parameters. In this case, any form parameters that are accepted by the wrapped method have to exist in the __call__() method and it has to forward them to the wrapped method. Now I haven't looked too deeply into new style classes, but from some where I have got it in my head that one should be able to using new style classes create new methods and dynamically setup the parameters they accept. If this is true then _extra_path_info could be replaced with a magic method which would create a wrapper around a function and automatically fill into the __call__() method all the parameters which the wrapped method was expecting. Used in conjunction with decorators in Python 2.4, I am speculating that one could simple write: @extra_path_info def method(req): return req.path_info,req.extra_path_info The only problem with this even if it can be done, is that the object which wraps the function most likely is an instance of a new style class and presently, mod_python.publisher cannot traverse into new style classes. Luckily the vampire::publisher code I have and will release at some point will, so I can try it out and see how it goes. Anyway, thought this all might be of interest to someone so though I would post it here. I wander if there is a place for stuff like this at the Python cookbook site. There are a few examples there which mention mod_python, but they seem to be more general recipes also applicable in other situations. Would be interested to hear any comments on this and whether anyone is already doing something like it. Graham
|