durusmail: qp: Twisted - Was: Re: Quixote, QP, the future...?
Twisted - Was: Re: Quixote, QP, the future...?
2006-04-09
2006-04-09
2006-04-10
2006-04-10
2006-04-10
2006-04-10
2006-04-10
2006-04-10
2006-04-10
2006-04-10
2006-04-10
2006-04-12
2006-04-12
2006-04-13
2006-04-13
2006-04-13
2006-04-13
2006-04-14
2006-04-14
2006-04-15
2006-04-16
2006-04-16
Twisted - Was: Re: Quixote, QP, the future...?
David K. Hess
2006-04-10
On Apr 10, 2006, at 1:00 PM, David Binger wrote:

> On Apr 10, 2006, at 12:36 PM, David K. Hess wrote:
>
>> On Apr 10, 2006, at 10:39 AM, David Binger wrote:
>>> I was thinking of changing the run_web(self) call in start_web()
>>> to "get_publisher().run_web()".  This lets the Publisher do
>>> whatever it wants to do to get http/scgi or whatever running,
>>> while preserving the basic start-stop/pidfile functionality of
>>> the "qp" command line tool.  I'd rather not move start_web()
>>> itself to the Publisher if we can help it.
>>
>> My concern is that I already handle forking and pidfile management
>> elsewhere so I need that behavior in start_web factored out. In my
>> case QP is not the application, just a feature of another
>> application.
>
> Understood.  If you are not using the qp tool for site management,
> though, then there is no need to for you to call the Site.start_web()
> method.  You can just call your function that configures your
> reactor the way you want it.
>
>>
>>> If you are not using the qp script for controlling the publisher,
>>> then
>>> you have an easy way to direct your site-control to your custom
>>> Site subclass,
>>> with start_web() doing what you need to tell the reactor about your
>>> application.  That seems like a reasonable way to get your job done.
>>>
>>> Note that you can call the start/stop durus methods from your
>>> own script without changing anything.
>>
>> Given my concern above, this might be a better approach. Though,
>> the Site.get_sites interface might need to be touched since it
>> explicitly doles out Site objects.
>
> I don't see any need for your code to call Site.get_sites().
> Don't you just have one site to take care of?
> Just say "x=Site('mysite'); x.start_durus(); prepare_reactor(x)"
> where prepare_reactor() calls methods on x to get the server
> addresses it needs.

That definitely is a very simple and pragmatic approach. One of my
motivations is to find the most integrated and supported way to
accomplish this so that I don't have to worry about patching QP nor
worrying about a new version breaking my code since my usage of a
class isn't quite what its implementation expected.

>>> I think it would be nice to have a function like this:
>>>
>>> def get_reactor(site):
>>>     """
>>>     Return a twisted reactor configured for this site.
>>>     """
>>>
>>> This could be used in a SitePublisher.run_web() implementation that
>>> may or may not call run().  It could also be used directly in
>>> other scripts that start twisted servers for QP sites.
>>>
>>> I don't think a TwistedPublisher subclass is necessary.
>>
>> I guess the beauty of adding run_web to the Publisher is that
>> people have ready access to overriding it. But if I have to
>> subclass Site anyway to change as much behavior as I need to,
>> perhaps I'm better off encapsulating all of the twisted stuff over
>> there?
>
> Yes.  That's what I would do.  The run_web() method would mostly be
> for
> applications that want the qp tool to manage web services in a
> nonstandard
> way.
>
>>
>> Does this make the case for a Site subclass instantiated from
>> slash.py?
>
> That path gets tangled pretty quickly.
> The Site class is what qp depends on to find slash.py.
>
> If anyone wants all of their apps to run with a different Site
> class, I
> think they should change the import in (a copy of) the bin/qp file.
>
> If anyone really wants a particular QP publisher to run with a
> different site class,
> then I'd suggest putting "self.site.__class__ = MySiteClass" in the
> SitePublisher.__init__().

How about a combination of both approaches? I would create
TwistedSite which is a subclass of Site. TwistedSite would have a
standalone() method that defaults to returning True which results in
a reactor.run() call when start_web is invoked and results in overall
"QP is the application" behavior. Combined with the __class__ hook
you suggest above, this makes the general twisted case manageable
from bin/qp and very simple for users to accomplish.

For my embedded case where you are calling from code:

x=MyTwistedSite('mysite'); x.start_durus(); x.start_web()

MyTwistedSite would be a subclass of TwistedSite where standalone()
is overridden to return False so that x.start_web() won't call
reactor.run() and overall "QP is the application" behavior is disabled.

Dave



reply