[Twisted-Python] Updated defer patch

Christopher Armstrong carmstro at twistedmatrix.com
Wed Jul 31 21:41:40 EDT 2002


Ok, so I've added some code that wraps plain strings passed to .errback
with a "DefaultException" and then issues a DeprecationWarning.
Unfortunately, this patch causes tests to fail, since they pass a string
to .errback and try to ensure that what gets passed to their
error-callback is the same thing.  So, following itamar's lead, this is
backwards-compatibility-code-that's-only-half-backwards-compatible ;-)

I've also updated the docstrings for callback and errback, they were
out-of-date.

(Note, this is an updated version of my last patch, so those
modifications are duplicated here)

Index: twisted/internet/defer.py
===================================================================
RCS file: /cvs/Twisted/twisted/internet/defer.py,v
retrieving revision 1.12
diff -u -r1.12 defer.py
--- twisted/internet/defer.py	24 Jul 2002 19:04:56 -0000	1.12
+++ twisted/internet/defer.py	1 Aug 2002 01:36:17 -0000
@@ -32,6 +32,9 @@
 class TimeoutError(Exception):
     pass
 
+class DefaultException(Exception):
+    pass
+
 def logError(err):
     log.err(err)
     return err
@@ -103,7 +106,7 @@
         These will be executed when the 'master' callback is run.
         """
         cbs = ((callback, callbackArgs, callbackKeywords),
-               (errback or logError, errbackArgs, errbackKeywords))
+               (errback or (lambda x: x), errbackArgs, errbackKeywords))
         if self.default:
             self.callbacks[-1] = cbs
         else:
@@ -152,10 +155,9 @@
 
         Each callback will have its result passed as the first
         argument to the next; this way, the callbacks act as a
-        'processing chain'.
-
-        If this deferred has not been armed yet, nothing will happen until it
-        is armed.
+        'processing chain'. Also, if the success-callback returns a Failure
+        or raises an Exception, processing will continue on the *error*-
+        callback chain.
         """
         self._startRunCallbacks(result, 0)
 
@@ -165,13 +167,24 @@
 
         Each callback will have its result passed as the first
         argument to the next; this way, the callbacks act as a
-        'processing chain'.
-
-        If this deferred has not been armed yet, nothing will happen until it
-        is armed.
-        """
-        if not fail:
+        'processing chain'. Also, if the error-callback returns a non-Failure
+        or doesn't raise an Exception, processing will continue on the
+        *success*-callback chain.
+
+        The argument must be a Failure instance or None, and strings are
+        accepted for backward-compatibility, but are deprecated.
+        """
+        if isinstance(fail, types.StringType) or isinstance(fail, types.UnicodeType):
+            import warnings
+            warnings.warn(
+                "Don't pass strings (like %r) to Deferred.errback (replacing with a DefaultException)." %
+                          fail, DeprecationWarning, stacklevel=2)
+            fail = failure.Failure(DefaultException(fail))
+        elif fail is None:
             fail = failure.Failure()
+        elif not isinstance(fail, failure.Failure):
+            raise TypeError("Deferred.errback accepts failure.Failure instances, strings, or None. %r is none of these." % fail)
+            
         self._startRunCallbacks(fail, 1)
 

@@ -228,14 +241,8 @@
                                              callbackArgs=(0,),
                                              errbackArgs=(1,))
                     break
-                if type(self.result) != types.StringType:
-                    # TODO: make this hack go away; it has something to do
-                    # with PB returning strings from errbacks that are
-                    # actually tracebacks that we still want to handle as
-                    # errors sometimes... can't find exactly where right
-                    # now
-                    if not isinstance(self.result, failure.Failure):
-                        self.isError = 0
+                if not isinstance(self.result, failure.Failure):
+                    self.isError = 0
             except:
                 self.result = failure.Failure()
                 self.isError = 1



-- 
                                Chris Armstrong
                         << radix at twistedmatrix.com >>
                http://twistedmatrix.com/users/carmstro.twistd/





More information about the Twisted-Python mailing list