Freeform/formless doesn't work with deferred properties?
Hi, I'm using freeform/formless to handle a form. However, when the property returns a deferred value, it is not handled correctly by freeform. Is this a bug? Attached is an example (based on DP's examples) that shows the behavior: When rendering the page, instead of seeing "50" in the input field, it shows something like '<Deferred at 0xbec7c30c>'. PS: A similar thing happens when returning a deferred as an attribute of context.tag in a render method. -- Gavrie. from twisted.application import service, internet from twisted.internet import defer from nevow import appserver from nevow import renderer from nevow import tags from nevow import formless from nevow import freeform class IMyForm(formless.TypedInterface): foo = formless.Integer() class FormPage(renderer.Renderer): __implements__ = IMyForm, def _getter(self): d = defer.Deferred() d.callback(50) return d foo = property(_getter) document = tags.html[ tags.body[ "Hello! Here is a form:", freeform.configure ] ] application = service.Application("nestedmenus") internet.TCPServer( 8080, appserver.NevowSite( FormPage() ) ).setServiceParent(application)
Gavrie Philipson wrote:
PS: A similar thing happens when returning a deferred as an attribute of context.tag in a render method.
I don't know what to do about your freeform/deferred problem, but this one's easy to handle: don't return tags that have Deferreds inside, do this: def render_foo(self, ctx, data): d = getYourDeferred() d.addCallback(self._cbGenTags, ctx) return d def _cbGenTags(self, result, ctx): return ctx.tag[ str(result) ] -- Twisted | Christopher Armstrong: International Man of Twistery Radix | Release Manager, Twisted Project ---------+ http://radix.twistedmatrix.com/
Christopher Armstrong wrote: ...
I don't know what to do about your freeform/deferred problem, but this one's easy to handle: don't return tags that have Deferreds inside, do this:
def render_foo(self, ctx, data): d = getYourDeferred() d.addCallback(self._cbGenTags, ctx) return d
def _cbGenTags(self, result, ctx): return ctx.tag[ str(result) ]
Christopher, This indeed solved the problem. Thanks, -- Gavrie.
On Dec 22, 2003, at 10:38 AM, Gavrie Philipson wrote:
Hi,
I'm using freeform/formless to handle a form. However, when the property returns a deferred value, it is not handled correctly by freeform. Is this a bug?
Attached is an example (based on DP's examples) that shows the behavior: When rendering the page, instead of seeing "50" in the input field, it shows something like '<Deferred at 0xbec7c30c>'.
PS: A similar thing happens when returning a deferred as an attribute of context.tag in a render method.
Your suspicions about the freeform problem being related to the attribute problem are correct; apparently nevow doesn't deal with deferreds in attribute values properly. Are you sure you are using CVS HEAD? I checked in some changes fairly recently which may affect the situation. Anyway, it's something that should certainly be fixed. In the meantime, it's good that you have a workaround. dp
Donovan Preston wrote:
On Dec 22, 2003, at 10:38 AM, Gavrie Philipson wrote:
Hi,
I'm using freeform/formless to handle a form. However, when the property returns a deferred value, it is not handled correctly by freeform. Is this a bug?
...
Your suspicions about the freeform problem being related to the attribute problem are correct; apparently nevow doesn't deal with deferreds in attribute values properly. Are you sure you are using CVS HEAD? I checked in some changes fairly recently which may affect the situation.
Anyway, it's something that should certainly be fixed. In the meantime, it's good that you have a workaround.
Donovan, Christopher's workaround is fine, but doesn't solve the problem when using freeform.configure to render the form instead of my own form layout. Anyway, I just did a 'cvs update' to get the latest HEAD, and guess what? Now my test script doesn't work at all! When I run twistd -ony /tmp/formpost-defer.tac (the same script that I previously posted to this list), I get a traceback (see below). Is this a bug? I did a clean install of the Quotient package and kept no old files around. -- Gavrie. 2003/12/24 08:31 IST [-] Log opened. 2003/12/24 08:31 IST [-] twistd 1.1.0 (/usr/bin/python 2.3.2) starting up 2003/12/24 08:31 IST [-] reactor class: twisted.internet.default.SelectReactor 2003/12/24 08:31 IST [-] Loading /tmp/formpost-defer.tac... 2003/12/24 08:31 IST [-] /usr/lib/python2.3/site-packages/atop/store.py:36: exceptions.DeprecationWarning: This module is deprecated. 2003/12/24 08:31 IST [-] TODO: add IComponentized to Twisted so that we can do this without relying on getattr magic. 2003/12/24 08:31 IST [-] Loaded. 2003/12/24 08:31 IST [-] nevow.appserver.NevowSite starting on 8080 2003/12/24 08:31 IST [-] Starting factory <nevow.appserver.NevowSite instance at 0xbf0def6c> 2003/12/24 08:31 IST [HTTPChannel,0,127.0.0.1] Traceback (most recent call last): File "/usr/lib/python2.3/site-packages/twisted/internet/default.py", line 501, in doSelect _logrun(selectable, _drdw, selectable, method, dict) File "/usr/lib/python2.3/site-packages/twisted/python/log.py", line 65, in callWithLogger callWithContext({"system": lp}, func, *args, **kw) File "/usr/lib/python2.3/site-packages/twisted/python/log.py", line 52, in callWithContext return context.call({ILogContext: newCtx}, func, *args, **kw) File "/usr/lib/python2.3/site-packages/twisted/python/context.py", line 32, in callWithContext return func(*args,**kw) --- <exception caught here> --- File "/usr/lib/python2.3/site-packages/twisted/internet/default.py", line 510, in _doReadOrWrite why = getattr(selectable, method)() File "/usr/lib/python2.3/site-packages/twisted/internet/tcp.py", line 250, in doRead return self.protocol.dataReceived(data) File "/usr/lib/python2.3/site-packages/twisted/protocols/basic.py", line 223, in dataReceived why = self.lineReceived(line) File "/usr/lib/python2.3/site-packages/twisted/protocols/http.py", line 950, in lineReceived self.allContentReceived() File "/usr/lib/python2.3/site-packages/twisted/protocols/http.py", line 991, in allContentReceived req.requestReceived(command, path, version) File "/usr/lib/python2.3/site-packages/twisted/protocols/http.py", line 549, in requestReceived self.process() File "/usr/lib/python2.3/site-packages/nevow/appserver.py", line 115, in process return self.site.getResourceFor(self).addCallback( File "/usr/lib/python2.3/site-packages/nevow/appserver.py", line 202, in getResourceFor res = INewResource(self.resource) File "/usr/lib/python2.3/site-packages/twisted/python/components.py", line 77, in __call__ raise CannotAdapt("%s cannot be adapted to %s." % twisted.python.components.CannotAdapt: <FormPage object at 0xbf0def4c> cannot be adapted to <class 'nevow.appserver.INewResource'>.
Gavrie Philipson wrote:
Donovan Preston wrote:
On Dec 22, 2003, at 10:38 AM, Gavrie Philipson wrote:
Hi,
I'm using freeform/formless to handle a form. However, when the property returns a deferred value, it is not handled correctly by freeform. Is this a bug?
...
Your suspicions about the freeform problem being related to the attribute problem are correct; apparently nevow doesn't deal with deferreds in attribute values properly. Are you sure you are using CVS HEAD? I checked in some changes fairly recently which may affect the situation.
Anyway, it's something that should certainly be fixed. In the meantime, it's good that you have a workaround.
Never mind my previous message. The attached patch solves the problem with freeform not dealing with deferreds in attribute value. -- Gavrie.
Gavrie Philipson wrote:
The attached patch solves the problem with freeform not dealing with deferreds in attribute value.
...
+ + if isinstance(value, Deferred): + value.addCallback(self._cb_call, context, data) + return value + else: + return self._cb_call(value, context, data) + + def _cb_call(self, value, context, data): + request = context.locate(iwoven.IRequest) try: _, fbn = calculateFullBindingName(context, context.locate(formless.IBinding)) except KeyError:
To whoever commits this patch (i.e., dp ;), two things: 1) if necessary, add an errback (?) 2) there's defer.maybeDeferred for reducing those 5 lines of code in the "isinstance(value, Deferred)" block to 2 (or 1, if you're xtreme):: d = defer.maybeDeferred(defaults.getDefault, context.key, context) d.addCallback(self._cb_call, context, data) -- Twisted | Christopher Armstrong: International Man of Twistery Radix | Release Manager, Twisted Project ---------+ http://radix.twistedmatrix.com/
On Dec 24, 2003, at 1:37 AM, Gavrie Philipson wrote:
Christopher's workaround is fine, but doesn't solve the problem when using freeform.configure to render the form instead of my own form layout.
Yes. Supporting Deferred attribute values needs to happen.
Anyway, I just did a 'cvs update' to get the latest HEAD, and guess what? Now my test script doesn't work at all! When I run twistd -ony /tmp/formpost-defer.tac (the same script that I previously posted to this list), I get a traceback (see below).
Is this a bug? I did a clean install of the Quotient package and kept no old files around.
This is not a bug. However, it arises because of the really, really bad semantics of __implements__. Basically, you subclassed Renderer and didn't declare that your subclass implemented the interfaces which Renderer declares it implements. This didn't matter before, so you didn't notice that there was a problem. Now it matters, and boom. When declaring that a subclass implements some interfaces, don't forget to declare that it implements the super interfaces, too: class Foo(Renderer): __implements__ = IBar, Renderer.__implements__ Someone, can we please please switch to the better semantics for declaring implementation used by either z3 now or PyProtocols? dp
participants (3)
-
Christopher Armstrong
-
Donovan Preston
-
Gavrie Philipson