Graham Dumpleton
grahamd at dscpl.com.au
Wed Dec 7 06:29:14 EST 2005
On 07/12/2005, at 7:21 PM, Radek Bartoň wrote: > Hello, thanks for your reply. > > >> If what it is that you want is that an instance of MyClass be created >> specific for each request, before any URL mapping against methods is >> being done, then using mod_python.publisher alone the answer is >> that no >> it cannot be done easily. Unless my brain is overlooking something >> obvious, you have to do something convoluted like: >> >> from mod_python import util, apache >> >> import types >> >> class Wrapper: >> >> def __init__(self,function): >> self.__class = function.im_class >> self.__name = function.im_func.__name__ >> >> def __call__(self,req): >> instance = self.__class(req) >> function = getattr(instance,self.__name) >> return util.apply_fs_data(function,req.form) >> >> class MyClass: >> >> def __init__(self,req): >> self.__req = req >> >> def method1(self): >> return "method1" >> >> def method2(self): >> return "method2" >> >> class Object: pass >> >> index = Object() >> index.method1 = Wrapper(MyClass.method1) >> index.method2 = Wrapper(MyClass.method2) >> > > I tried this wrapper. When I typed URL http://localhost/test.py/ > index page > returned string representation of object so I could write __str__ > function of > Object class to make it working. You are better off defining __call__() for the instance and not __str__() as __call__() still allows you access to form parameters and the request object. Thus you might have: class MyClass: ... def __call__(self): return "__call__" ... index.__call__ = Wrapper(MyClass.__call__) > But URLs > http://localhost/test.py/index/method1 and > http://localhost/test.py/index/method2 returned errors "Not Found". You might need to be running mod_python 3.2.5b for it to work, but I would not have expected that to be the case. This code was actual code I tried and tested before I sent it, albeit on mod_python 3.2.5b. > Nevertheless I think that functionality of this wrapper was > mentioned same > as functionality of my first example: > > class MyClass: > def __init__(self): > ... > def __str__(self): > ... > def method1(self, req): > ... > def method2(self, req): > ... > > index = MyClass(): The code I posted is not the same. In your code, there is one and only one instance of MyClass created and all requested are handled within the context of the one instance. This instance of MyClass is created at the time the module is imported and is why it is not possible for the request object to be available to the constructor of the class. In the code I posted, the Wrapper instance __call__() method is called for each request and an instance of MyClass is created for each request which is received. The distinct request object for each request is passed to the constructor for the instance of MyClass created specifically for each request. > I don't know much about mod_python and its publisher internal > function but > this one works because I think that publisher when parse request > URL looks > first for matching file in web root and then it looks into this > file for > index function or for index object. If index object has defined > __str__ > function publisher returns string representation of this object as > reply for > request. If index object has methods and URL is containing > identifier of some > method publisher call it. Repair me if this is bad idea. More or less. If MyClass provides __call__() it will call that in preference to converting the instance to a string, thus triggering execution of __str__(). >> Apart from that, if you were using Vampire, you could simply use >> basic >> handlers are write: >> >> import vampire >> >> class MyClass: >> >> def __init__(self,req): >> self.__req = req >> >> def __call__(self): >> return "__call__" >> >> def method1(self): >> return "method1",self.__req.filename >> >> def method2(self, req): >> return "method2",req.filename >> >> handler = vampire.Publisher(MyClass) >> >> The vampire.Publisher() wrapper class handlers both creating an >> instance >> of the class and mapping URLs onto methods of the instance. It only >> supports callable methods in classes though. Ie., it will not map >> URLs >> to __str__() or to basic data types which are a member of the class. >> >> > > This looks that it cold have functionality I want. But mayby it > will be > sufficent to look how vampire gets request object and write this to > MyClass's > constructor. It is not that simple. The vampire.Publisher class and the code it relies on to do what it does is not trivial. It in effect implements a complete mechanism for mapping URLs onto objects, much like mod_python.publisher. It isn't just a few lines that you could emulate. >> Note that creating an instance of a class per request could be quite >> inefficient. What is the original reason that you wanted to access >> the >> request object in the constructor in the first place? >> > > I didn' know that when I use > > def index(req): > instance = MyClass(req) > > mod_python creates only one instance of MyClass for every request > and when I > use It doesn't, it is creating an instance of MyClass per request. > index = MyClass > > it creates instance for each. You are starting to mix techniques here. If you are actually talking about basic handlers and not mod_python.publisher, you can do this but for your MyClass it will fail. If using basic handlers, you can say: class MyClass: def __call__(self,req): .... handler = MyClass and mod_python will create an instance of MyClass for each request and then call the instance, thus why it must define __call__(). With basic handlers as you seem to realise though, there is no further URL mapping done by mod_python. If using mod_python.publisher, as: index = MyClass you should I believe get NotFound as it will not automatically create instances of classes for you if a class type is referenced. I know Nicolas hand it in mind to perhaps support this, but personally I don't think it is a good idea as it could introduce other problems where people think methods are not accessible but may actually. The authorisation schemes as written also would not work for the instance created. Ie., authorisation could only be done at file scope. > But creating instance isn't the purpose. Purpose > is to have page witch is class. Its string representation or its > callable > function returns main content with forms i. e. and its methost handles > request connected with forms on main page. > > Hope that I make my self clear and thanks for response. Not entirely, you still haven't explicitly said for what reason you want to access the "req" object in the constructor of MyClass, which is basically what your original question was about. If you can specify what information you are wanting to get from the request object in the constructor, can perhaps say why you would not want to do that or how you might do it. Graham
|