[Twisted-Python] twisted.wed.widgets and defer.Deferred() giving a list.

Tommi Virtanen tv at twistedmatrix.com
Mon Sep 10 11:22:01 MDT 2001


	Hi. I didn't commit this, as it's a bit of a conceptual change.
        Please give feedback. Patch is at the end.

        This change allows web.widgets to call defer.Deferred's
        callback() with a list instead of a string, making it possible
        to stream a web page to the browser by returning a string and
        then a Deferred object.

        Here's a snippet of a web UI I'm doing that streams LDAP
        search results to the browser as soon as the server sends
        them -- see handle_entry():

class LDAPSearchAndPrint(ldap.LDAPSearch):
    def __init__(self, ldapclient, callback, filter=pureldap.LDAPFilterMatchAll):
        ldap.LDAPSearch.__init__(self, ldapclient,
                                 baseObject='dc=example, dc=com',
                                 filter=filter,
                                 )
        self.result=""
        self.callback=callback
        self.count=0

    def handle_success(self):
        self.callback(["<p>%d entries matched."%self.count])

    def handle_entry(self, objectName, attributes):
        result="<p>%s\n<ul>\n"%objectName

        for a,l in attributes:
            assert len(l)>0
            if len(l)==1:
                result=result+"  <li>%s: %s\n"%(a, l[0])
            else:
                result=result+"  <li>%s:\n    <ul>\n"%a
                for i in l:
                    result=result+"      <li>%s\n"%i
                result=result+"    </ul>\n"

        result=result+"</ul>\n"

        c=self.callback
        d=defer.Deferred()
        self.callback=d.callback
        c([result, d])
        self.count=self.count+1

    def handle_fail(self, resultCode, errorMessage):
        self.callback("fail: %d: %s"%(resultCode, errorMessage or "Unknown error"))


--- twisted/web/widgets.py	2001/09/10 17:13:24	1.8
+++ twisted/web/widgets.py	2001/09/10 17:18:37
@@ -283,12 +283,17 @@
     def callback(self, result, position, decNeedsHeaders):
         if result != FORGET_IT:
             self.needsHeaders = self.needsHeaders - decNeedsHeaders
-        if isinstance(result, defer.Deferred):
-            self._addDeferred(result, position)
-        self.lst[position] = result
+        if not isinstance(result, types.ListType):
+            result=[result]
+        for i in xrange(len(result)):
+            if isinstance(result[i], defer.Deferred):
+                self._addDeferred(result[i], position+i)
+        self.lst[position:position+1] = result
+        assert self.position <= position
         self.keepRendering()
-        if isinstance(result, defer.Deferred):
-            result.arm()
+        for r in result:
+            if isinstance(r, defer.Deferred):
+                r.arm()
 
 
     def keepRendering(self):

-- 
tv@{{hq.yok.utu,havoc,gaeshido}.fi,{debian,wanderer}.org,stonesoft.com}
double a,b=4,c;main(){for(;++a<2e6;c-=(b=-b)/a++);printf("%f\n",c);}





More information about the Twisted-Python mailing list