root/trunk/twisted/internet/defer.py

Revision 29955, 52.2 KB (checked in by exarkun, 16 hours ago)

Merge iterative-deferreds-411-7

Author: exarkun, therve, mithrandi, jml
Reviewers: spiv, glyph, jknight, TimothyFitz
Fixes: #411

Replace the recursive implementation of implicit Deferred chaining
(that is, chaining caused by callbacks which return Deferreds) with
an implementation which is iterative instead. This prevents result
propagation from failing when a long Deferred chain is fired.

Line 
1# -*- test-case-name: twisted.test.test_defer,twisted.test.test_defgen,twisted.internet.test.test_inlinecb -*-
2# Copyright (c) 2001-2010 Twisted Matrix Laboratories.
3# See LICENSE for details.
4
5"""
6Support for results that aren't immediately available.
7
8Maintainer: Glyph Lefkowitz
9
10@var _NO_RESULT: The result used to represent the fact that there is no
11    result. B{Never ever ever use this as an actual result for a Deferred}.  You
12    have been warned.
13
14@var _CONTINUE: A marker left in L{Deferred.callbacks} to indicate a Deferred
15    chain.  Always accompanied by a Deferred instance in the args tuple pointing
16    at the Deferred which is chained to the Deferred which has this marker.
17"""
18
19import traceback
20import warnings
21from sys import exc_info
22
23# Twisted imports
24from twisted.python import log, failure, lockfile
25from twisted.python.util import unsignedID, mergeFunctionMetadata
26
27
28
29class AlreadyCalledError(Exception):
30    pass
31
32
33class CancelledError(Exception):
34    """
35    This error is raised by default when a L{Deferred} is cancelled.
36    """
37
38
39class TimeoutError(Exception):
40    """
41    This exception is deprecated.  It is used only by the deprecated
42    L{Deferred.setTimeout} method.
43    """
44
45
46
47def logError(err):
48    log.err(err)
49    return err
50
51
52
53def succeed(result):
54    """
55    Return a L{Deferred} that has already had C{.callback(result)} called.
56
57    This is useful when you're writing synchronous code to an
58    asynchronous interface: i.e., some code is calling you expecting a
59    L{Deferred} result, but you don't actually need to do anything
60    asynchronous. Just return C{defer.succeed(theResult)}.
61
62    See L{fail} for a version of this function that uses a failing
63    L{Deferred} rather than a successful one.
64
65    @param result: The result to give to the Deferred's 'callback'
66           method.
67
68    @rtype: L{Deferred}
69    """
70    d = Deferred()
71    d.callback(result)
72    return d
73
74
75
76def fail(result=None):
77    """
78    Return a L{Deferred} that has already had C{.errback(result)} called.
79
80    See L{succeed}'s docstring for rationale.
81
82    @param result: The same argument that L{Deferred.errback} takes.
83
84    @raise NoCurrentExceptionError: If C{result} is C{None} but there is no
85        current exception state.
86
87    @rtype: L{Deferred}
88    """
89    d = Deferred()
90    d.errback(result)
91    return d
92
93
94
95def execute(callable, *args, **kw):
96    """
97    Create a L{Deferred} from a callable and arguments.
98
99    Call the given function with the given arguments.  Return a L{Deferred}
100    which has been fired with its callback as the result of that invocation
101    or its C{errback} with a L{Failure} for the exception thrown.
102    """
103    try:
104        result = callable(*args, **kw)
105    except:
106        return fail()
107    else:
108        return succeed(result)
109
110
111
112def maybeDeferred(f, *args, **kw):
113    """
114    Invoke a function that may or may not return a L{Deferred}.
115
116    Call the given function with the given arguments.  If the returned
117    object is a L{Deferred}, return it.  If the returned object is a L{Failure},
118    wrap it with L{fail} and return it.  Otherwise, wrap it in L{succeed} and
119    return it.  If an exception is raised, convert it to a L{Failure}, wrap it
120    in L{fail}, and then return it.
121
122    @type f: Any callable
123    @param f: The callable to invoke
124
125    @param args: The arguments to pass to C{f}
126    @param kw: The keyword arguments to pass to C{f}
127
128    @rtype: L{Deferred}
129    @return: The result of the function call, wrapped in a L{Deferred} if
130    necessary.
131    """
132    try:
133        result = f(*args, **kw)
134    except:
135        return fail(failure.Failure())
136
137    if isinstance(result, Deferred):
138        return result
139    elif isinstance(result, failure.Failure):
140        return fail(result)
141    else:
142        return succeed(result)
143
144
145
146def timeout(deferred):
147    deferred.errback(failure.Failure(TimeoutError("Callback timed out")))
148
149
150
151def passthru(arg):
152    return arg
153
154
155
156def setDebugging(on):
157    """
158    Enable or disable L{Deferred} debugging.
159
160    When debugging is on, the call stacks from creation and invocation are
161    recorded, and added to any L{AlreadyCalledErrors} we raise.
162    """
163    Deferred.debug=bool(on)
164
165
166
167def getDebugging():
168    """
169    Determine whether L{Deferred} debugging is enabled.
170    """
171    return Deferred.debug
172
173
174# See module docstring.
175_NO_RESULT = object()
176_CONTINUE = object()
177
178
179
180class Deferred:
181    """
182    This is a callback which will be put off until later.
183
184    Why do we want this? Well, in cases where a function in a threaded
185    program would block until it gets a result, for Twisted it should
186    not block. Instead, it should return a L{Deferred}.
187
188    This can be implemented for protocols that run over the network by
189    writing an asynchronous protocol for L{twisted.internet}. For methods
190    that come from outside packages that are not under our control, we use
191    threads (see for example L{twisted.enterprise.adbapi}).
192
193    For more information about Deferreds, see doc/howto/core/defer.html or
194    U{http://twistedmatrix.com/documents/current/core/howto/defer.html}
195
196    When creating a Deferred, you may provide a canceller function, which
197    will be called by d.cancel() to let you do any clean-up necessary if the
198    user decides not to wait for the deferred to complete.
199
200    @ivar called: A flag which is C{False} until either C{callback} or
201        C{errback} is called and afterwards always C{True}.
202    @type called: C{bool}
203
204    @ivar paused: A counter of how many unmatched C{pause} calls have been made
205        on this instance.
206    @type paused: C{int}
207
208    @ivar _suppressAlreadyCalled: A flag used by the cancellation mechanism
209        which is C{True} if the Deferred has no canceller and has been
210        cancelled, C{False} otherwise.  If C{True}, it can be expected that
211        C{callback} or C{errback} will eventually be called and the result
212        should be silently discarded.
213    @type _suppressAlreadyCalled: C{bool}
214
215    @ivar _runningCallbacks: A flag which is C{True} while this instance is
216        executing its callback chain, used to stop recursive execution of
217        L{_runCallbacks}
218    @type _runningCallbacks: C{bool}
219
220    @ivar _chainedTo: If this Deferred is waiting for the result of another
221        Deferred, this is a reference to the other Deferred.  Otherwise, C{None}.
222    """
223
224    called = False
225    paused = 0
226    _debugInfo = None
227    _suppressAlreadyCalled = False
228
229    # Are we currently running a user-installed callback?  Meant to prevent
230    # recursive running of callbacks when a reentrant call to add a callback is
231    # used.
232    _runningCallbacks = False
233
234    # Keep this class attribute for now, for compatibility with code that
235    # sets it directly.
236    debug = False
237
238    _chainedTo = None
239
240    def __init__(self, canceller=None):
241        """
242        Initialize a L{Deferred}.
243
244        @param canceller: a callable used to stop the pending operation
245            scheduled by this L{Deferred} when L{Deferred.cancel} is
246            invoked. The canceller will be passed the deferred whose
247            cancelation is requested (i.e., self).
248
249            If a canceller is not given, or does not invoke its argument's
250            C{callback} or C{errback} method, L{Deferred.cancel} will
251            invoke L{Deferred.errback} with a L{CancelledError}.
252
253            Note that if a canceller is not given, C{callback} or
254            C{errback} may still be invoked exactly once, even though
255            defer.py will have already invoked C{errback}, as described
256            above.  This allows clients of code which returns a L{Deferred}
257            to cancel it without requiring the L{Deferred} instantiator to
258            provide any specific implementation support for cancellation.
259            New in 10.1.
260
261        @type canceller: a 1-argument callable which takes a L{Deferred}. The
262            return result is ignored.
263        """
264        self.callbacks = []
265        self._canceller = canceller
266        if self.debug:
267            self._debugInfo = DebugInfo()
268            self._debugInfo.creator = traceback.format_stack()[:-1]
269
270
271    def addCallbacks(self, callback, errback=None,
272                     callbackArgs=None, callbackKeywords=None,
273                     errbackArgs=None, errbackKeywords=None):
274        """
275        Add a pair of callbacks (success and error) to this L{Deferred}.
276
277        These will be executed when the 'master' callback is run.
278        """
279        assert callable(callback)
280        assert errback == None or callable(errback)
281        cbs = ((callback, callbackArgs, callbackKeywords),
282               (errback or (passthru), errbackArgs, errbackKeywords))
283        self.callbacks.append(cbs)
284
285        if self.called:
286            self._runCallbacks()
287        return self
288
289
290    def addCallback(self, callback, *args, **kw):
291        """
292        Convenience method for adding just a callback.
293
294        See L{addCallbacks}.
295        """
296        return self.addCallbacks(callback, callbackArgs=args,
297                                 callbackKeywords=kw)
298
299
300    def addErrback(self, errback, *args, **kw):
301        """
302        Convenience method for adding just an errback.
303
304        See L{addCallbacks}.
305        """
306        return self.addCallbacks(passthru, errback,
307                                 errbackArgs=args,
308                                 errbackKeywords=kw)
309
310
311    def addBoth(self, callback, *args, **kw):
312        """
313        Convenience method for adding a single callable as both a callback
314        and an errback.
315
316        See L{addCallbacks}.
317        """
318        return self.addCallbacks(callback, callback,
319                                 callbackArgs=args, errbackArgs=args,
320                                 callbackKeywords=kw, errbackKeywords=kw)
321
322
323    def chainDeferred(self, d):
324        """
325        Chain another L{Deferred} to this L{Deferred}.
326
327        This method adds callbacks to this L{Deferred} to call C{d}'s callback
328        or errback, as appropriate. It is merely a shorthand way of performing
329        the following::
330
331            self.addCallbacks(d.callback, d.errback)
332
333        When you chain a deferred d2 to another deferred d1 with
334        d1.chainDeferred(d2), you are making d2 participate in the callback
335        chain of d1. Thus any event that fires d1 will also fire d2.
336        However, the converse is B{not} true; if d2 is fired d1 will not be
337        affected.
338
339        Note that unlike the case where chaining is caused by a L{Deferred}
340        being returned from a callback, it is possible to cause the call
341        stack size limit to be exceeded by chaining many L{Deferred}s
342        together with C{chainDeferred}.
343        """
344        d._chainedTo = self
345        return self.addCallbacks(d.callback, d.errback)
346
347
348    def callback(self, result):
349        """
350        Run all success callbacks that have been added to this L{Deferred}.
351
352        Each callback will have its result passed as the first argument to
353        the next; this way, the callbacks act as a 'processing chain'.  If
354        the success-callback returns a L{Failure} or raises an L{Exception},
355        processing will continue on the *error* callback chain.  If a
356        callback (or errback) returns another L{Deferred}, this L{Deferred}
357        will be chained to it (and further callbacks will not run until that
358        L{Deferred} has a result).
359        """
360        assert not isinstance(result, Deferred)
361        self._startRunCallbacks(result)
362
363
364    def errback(self, fail=None):
365        """
366        Run all error callbacks that have been added to this L{Deferred}.
367
368        Each callback will have its result passed as the first
369        argument to the next; this way, the callbacks act as a
370        'processing chain'. Also, if the error-callback returns a non-Failure
371        or doesn't raise an L{Exception}, processing will continue on the
372        *success*-callback chain.
373
374        If the argument that's passed to me is not a L{failure.Failure} instance,
375        it will be embedded in one. If no argument is passed, a
376        L{failure.Failure} instance will be created based on the current
377        traceback stack.
378
379        Passing a string as `fail' is deprecated, and will be punished with
380        a warning message.
381
382        @raise NoCurrentExceptionError: If C{fail} is C{None} but there is
383            no current exception state.
384        """
385        if not isinstance(fail, failure.Failure):
386            fail = failure.Failure(fail)
387
388        self._startRunCallbacks(fail)
389
390
391    def pause(self):
392        """
393        Stop processing on a L{Deferred} until L{unpause}() is called.
394        """
395        self.paused = self.paused + 1
396
397
398    def unpause(self):
399        """
400        Process all callbacks made since L{pause}() was called.
401        """
402        self.paused = self.paused - 1
403        if self.paused:
404            return
405        if self.called:
406            self._runCallbacks()
407
408
409    def cancel(self):
410        """
411        Cancel this L{Deferred}.
412
413        If the L{Deferred} has not yet had its C{errback} or C{callback} method
414        invoked, call the canceller function provided to the constructor. If
415        that function does not invoke C{callback} or C{errback}, or if no
416        canceller function was provided, errback with L{CancelledError}.
417
418        If this L{Deferred} is waiting on another L{Deferred}, forward the
419        cancellation to the other L{Deferred}.
420        """
421        if not self.called:
422            canceller = self._canceller
423            if canceller:
424                canceller(self)
425            else:
426                # Arrange to eat the callback that will eventually be fired
427                # since there was no real canceller.
428                self._suppressAlreadyCalled = True
429            if not self.called:
430                # There was no canceller, or the canceller didn't call
431                # callback or errback.
432                self.errback(failure.Failure(CancelledError()))
433        elif isinstance(self.result, Deferred):
434            # Waiting for another deferred -- cancel it instead.
435            self.result.cancel()
436
437
438    def _startRunCallbacks(self, result):
439        if self.called:
440            if self._suppressAlreadyCalled:
441                self._suppressAlreadyCalled = False
442                return
443            if self.debug:
444                if self._debugInfo is None:
445                    self._debugInfo = DebugInfo()
446                extra = "\n" + self._debugInfo._getDebugTracebacks()
447                raise AlreadyCalledError(extra)
448            raise AlreadyCalledError
449        if self.debug:
450            if self._debugInfo is None:
451                self._debugInfo = DebugInfo()
452            self._debugInfo.invoker = traceback.format_stack()[:-2]
453        self.called = True
454        self.result = result
455        self._runCallbacks()
456
457
458    def _continuation(self):
459        """
460        Build a tuple of callback and errback with L{_continue} to be used by
461        L{_addContinue} and L{_removeContinue} on another Deferred.
462        """
463        return ((_CONTINUE, (self,), None),
464                (_CONTINUE, (self,), None))
465
466
467    def _runCallbacks(self):
468        """
469        Run the chain of callbacks once a result is available.
470
471        This consists of a simple loop over all of the callbacks, calling each
472        with the current result and making the current result equal to the
473        return value (or raised exception) of that call.
474
475        If C{self._runningCallbacks} is true, this loop won't run at all, since
476        it is already running above us on the call stack.  If C{self.paused} is
477        true, the loop also won't run, because that's what it means to be
478        paused.
479
480        The loop will terminate before processing all of the callbacks if a
481        C{Deferred} without a result is encountered.
482
483        If a C{Deferred} I{with} a result is encountered, that result is taken
484        and the loop proceeds.
485
486        @note: The implementation is complicated slightly by the fact that
487            chaining (associating two Deferreds with each other such that one
488            will wait for the result of the other, as happens when a Deferred is
489            returned from a callback on another Deferred) is supported
490            iteratively rather than recursively, to avoid running out of stack
491            frames when processing long chains.
492        """
493        if self._runningCallbacks:
494            # Don't recursively run callbacks
495            return
496
497        # Keep track of all the Deferreds encountered while propagating results
498        # up a chain.  The way a Deferred gets onto this stack is by having
499        # added its _continuation() to the callbacks list of a second Deferred
500        # and then that second Deferred being fired.  ie, if ever had _chainedTo
501        # set to something other than None, you might end up on this stack.
502        chain = [self]
503
504        while chain:
505            current = chain[-1]
506
507            if current.paused:
508                # This Deferred isn't going to produce a result at all.  All the
509                # Deferreds up the chain waiting on it will just have to...
510                # wait.
511                return
512
513            finished = True
514            current._chainedTo = None
515            while current.callbacks:
516                item = current.callbacks.pop(0)
517                callback, args, kw = item[
518                    isinstance(current.result, failure.Failure)]
519                args = args or ()
520                kw = kw or {}
521
522                # Avoid recursion if we can.
523                if callback is _CONTINUE:
524                    # Give the waiting Deferred our current result and then
525                    # forget about that result ourselves.
526                    chainee = args[0]
527                    chainee.result = current.result
528                    current.result = None
529                    # Making sure to update _debugInfo
530                    if current._debugInfo is not None:
531                        current._debugInfo.failResult = None
532                    chainee.paused -= 1
533                    chain.append(chainee)
534                    # Delay cleaning this Deferred and popping it from the chain
535                    # until after we've dealt with chainee.
536                    finished = False
537                    break
538
539                try:
540                    current._runningCallbacks = True
541                    try:
542                        current.result = callback(current.result, *args, **kw)
543                    finally:
544                        current._runningCallbacks = False
545                except:
546                    current.result = failure.Failure()
547                else:
548                    if isinstance(current.result, Deferred):
549                        # The result is another Deferred.  If it has a result,
550                        # we can take it and keep going.
551                        resultResult = getattr(current.result, 'result', _NO_RESULT)
552                        if resultResult is _NO_RESULT or isinstance(resultResult, Deferred) or current.result.paused:
553                            # Nope, it didn't.  Pause and chain.
554                            current.pause()
555                            current._chainedTo = current.result
556                            # Note: current.result has no result, so it's not
557                            # running its callbacks right now.  Therefore we can
558                            # append to the callbacks list directly instead of
559                            # using addCallbacks.
560                            current.result.callbacks.append(current._continuation())
561                            break
562                        else:
563                            # Yep, it did.  Steal it.
564                            current.result.result = None
565                            # Make sure _debugInfo's failure state is updated.
566                            if current.result._debugInfo is not None:
567                                current.result._debugInfo.failResult = None
568                            current.result = resultResult
569
570            if finished:
571                # As much of the callback chain - perhaps all of it - as can be
572                # processed right now has been.  The current Deferred is waiting on
573                # another Deferred or for more callbacks.  Before finishing with it,
574                # make sure its _debugInfo is in the proper state.
575                if isinstance(current.result, failure.Failure):
576                    # Stash the Failure in the _debugInfo for unhandled error
577                    # reporting.
578                    current.result.cleanFailure()
579                    if current._debugInfo is None:
580                        current._debugInfo = DebugInfo()
581                    current._debugInfo.failResult = current.result
582                else:
583                    # Clear out any Failure in the _debugInfo, since the result
584                    # is no longer a Failure.
585                    if current._debugInfo is not None:
586                        current._debugInfo.failResult = None
587
588                # This Deferred is done, pop it from the chain and move back up
589                # to the Deferred which supplied us with our result.
590                chain.pop()
591
592
593    def __str__(self):
594        """
595        Return a string representation of this C{Deferred}.
596        """
597        cname = self.__class__.__name__
598        result = getattr(self, 'result', _NO_RESULT)
599        myID = hex(unsignedID(self))
600        if self._chainedTo is not None:
601            result = ' waiting on Deferred at %s' % (hex(unsignedID(self._chainedTo)),)
602        elif result is _NO_RESULT:
603            result = ''
604        else:
605            result = ' current result: %r' % (result,)
606        return "<%s at %s%s>" % (cname, myID, result)
607    __repr__ = __str__
608
609
610
611class DebugInfo:
612    """
613    Deferred debug helper.
614    """
615
616    failResult = None
617
618    def _getDebugTracebacks(self):
619        info = ''
620        if hasattr(self, "creator"):
621            info += " C: Deferred was created:\n C:"
622            info += "".join(self.creator).rstrip().replace("\n","\n C:")
623            info += "\n"
624        if hasattr(self, "invoker"):
625            info += " I: First Invoker was:\n I:"
626            info += "".join(self.invoker).rstrip().replace("\n","\n I:")
627            info += "\n"
628        return info
629
630
631    def __del__(self):
632        """
633        Print tracebacks and die.
634
635        If the *last* (and I do mean *last*) callback leaves me in an error
636        state, print a traceback (if said errback is a L{Failure}).
637        """
638        if self.failResult is not None:
639            log.msg("Unhandled error in Deferred:", isError=True)
640            debugInfo = self._getDebugTracebacks()
641            if debugInfo != '':
642                log.msg("(debug: " + debugInfo + ")", isError=True)
643            log.err(self.failResult)
644
645
646
647class FirstError(Exception):
648    """
649    First error to occur in a L{DeferredList} if C{fireOnOneErrback} is set.
650
651    @ivar subFailure: The L{Failure} that occurred.
652    @type subFailure: L{Failure}
653
654    @ivar index: The index of the L{Deferred} in the L{DeferredList} where
655        it happened.
656    @type index: C{int}
657    """
658    def __init__(self, failure, index):
659        Exception.__init__(self, failure, index)
660        self.subFailure = failure
661        self.index = index
662
663
664    def __repr__(self):
665        """
666        The I{repr} of L{FirstError} instances includes the repr of the
667        wrapped failure's exception and the index of the L{FirstError}.
668        """
669        return 'FirstError[#%d, %r]' % (self.index, self.subFailure.value)
670
671
672    def __str__(self):
673        """
674        The I{str} of L{FirstError} instances includes the I{str} of the
675        entire wrapped failure (including its traceback and exception) and
676        the index of the L{FirstError}.
677        """
678        return 'FirstError[#%d, %s]' % (self.index, self.subFailure)
679
680
681    def __cmp__(self, other):
682        """
683        Comparison between L{FirstError} and other L{FirstError} instances
684        is defined as the comparison of the index and sub-failure of each
685        instance.  L{FirstError} instances don't compare equal to anything
686        that isn't a L{FirstError} instance.
687
688        @since: 8.2
689        """
690        if isinstance(other, FirstError):
691            return cmp(
692                (self.index, self.subFailure),
693                (other.index, other.subFailure))
694        return -1
695
696
697
698class DeferredList(Deferred):
699    """
700    L{DeferredList} is a tool for collecting the results of several Deferreds.
701
702    This tracks a list of L{Deferred}s for their results, and makes a single
703    callback when they have all completed.  By default, the ultimate result is a
704    list of (success, result) tuples, 'success' being a boolean.
705    L{DeferredList} exposes the same API that L{Deferred} does, so callbacks and
706    errbacks can be added to it in the same way.
707
708    L{DeferredList} is implemented by adding callbacks and errbacks to each
709    L{Deferred} in the list passed to it.  This means callbacks and errbacks
710    added to the Deferreds before they are passed to L{DeferredList} will change
711    the result that L{DeferredList} sees (ie, L{DeferredList} is not special).
712    Callbacks and errbacks can also be added to the Deferreds after they are
713    passed to L{DeferredList} and L{DeferredList} may change the result that
714    they see.
715
716    See the documentation for the C{__init__} arguments for more information.
717    """
718
719    fireOnOneCallback = False
720    fireOnOneErrback = False
721
722    def __init__(self, deferredList, fireOnOneCallback=False,
723                 fireOnOneErrback=False, consumeErrors=False):
724        """
725        Initialize a DeferredList.
726
727        @param deferredList: The list of deferreds to track.
728        @type deferredList:  C{list} of L{Deferred}s
729
730        @param fireOnOneCallback: (keyword param) a flag indicating that this
731            L{DeferredList} will fire when the first L{Deferred} in
732            C{deferredList} fires with a non-failure result without waiting for
733            any of the other Deferreds.  When this flag is set, the DeferredList
734            will fire with a two-tuple: the first element is the index in
735            C{deferredList} of the Deferred which fired; the second element is
736            the result of that Deferred.
737        @type fireOnOneCallback: C{bool}
738
739        @param fireOnOneErrback: (keyword param) a flag indicating that this
740            L{DeferredList} will fire when the first L{Deferred} in
741            C{deferredList} fires with a failure result without waiting for any
742            of the other Deferreds.  When this flag is set, if a Deferred in the
743            list errbacks, the DeferredList will errback with a L{FirstError}
744            failure wrapping the failure of that Deferred.
745        @type fireOnOneErrback: C{bool}
746
747        @param consumeErrors: (keyword param) a flag indicating that failures in
748            any of the included L{Deferreds} should not be propagated to
749            errbacks added to the individual L{Deferreds} after this
750            L{DeferredList} is constructed.  After constructing the
751            L{DeferredList}, any errors in the individual L{Deferred}s will be
752            converted to a callback result of C{None}.  This is useful to
753            prevent spurious 'Unhandled error in Deferred' messages from being
754            logged.  This does not prevent C{fireOnOneErrback} from working.
755        @type consumeErrors: C{bool}
756        """
757        self.resultList = [None] * len(deferredList)
758        Deferred.__init__(self)
759        if len(deferredList) == 0 and not fireOnOneCallback:
760            self.callback(self.resultList)
761
762        # These flags need to be set *before* attaching callbacks to the
763        # deferreds, because the callbacks use these flags, and will run
764        # synchronously if any of the deferreds are already fired.
765        self.fireOnOneCallback = fireOnOneCallback
766        self.fireOnOneErrback = fireOnOneErrback
767        self.consumeErrors = consumeErrors
768        self.finishedCount = 0
769
770        index = 0
771        for deferred in deferredList:
772            deferred.addCallbacks(self._cbDeferred, self._cbDeferred,
773                                  callbackArgs=(index,SUCCESS),
774                                  errbackArgs=(index,FAILURE))
775            index = index + 1
776
777
778    def _cbDeferred(self, result, index, succeeded):
779        """
780        (internal) Callback for when one of my deferreds fires.
781        """
782        self.resultList[index] = (succeeded, result)
783
784        self.finishedCount += 1
785        if not self.called:
786            if succeeded == SUCCESS and self.fireOnOneCallback:
787                self.callback((result, index))
788            elif succeeded == FAILURE and self.fireOnOneErrback:
789                self.errback(failure.Failure(FirstError(result, index)))
790            elif self.finishedCount == len(self.resultList):
791                self.callback(self.resultList)
792
793        if succeeded == FAILURE and self.consumeErrors:
794            result = None
795
796        return result
797
798
799
800def _parseDListResult(l, fireOnOneErrback=False):
801    if __debug__:
802        for success, value in l:
803            assert success
804    return [x[1] for x in l]
805
806
807
808def gatherResults(deferredList):
809    """
810    Returns list with result of given L{Deferred}s.
811
812    This builds on L{DeferredList} but is useful since you don't
813    need to parse the result for success/failure.
814
815    @type deferredList:  C{list} of L{Deferred}s
816    """
817    d = DeferredList(deferredList, fireOnOneErrback=True)
818    d.addCallback(_parseDListResult)
819    return d
820
821
822
823# Constants for use with DeferredList
824
825SUCCESS = True
826FAILURE = False
827
828
829
830## deferredGenerator
831
832class waitForDeferred:
833    """
834    See L{deferredGenerator}.
835    """
836
837    def __init__(self, d):
838        if not isinstance(d, Deferred):
839            raise TypeError("You must give waitForDeferred a Deferred. You gave it %r." % (d,))
840        self.d = d
841
842
843    def getResult(self):
844        if isinstance(self.result, failure.Failure):
845            self.result.raiseException()
846        return self.result
847
848
849
850def _deferGenerator(g, deferred):
851    """
852    See L{deferredGenerator}.
853    """
854    result = None
855
856    # This function is complicated by the need to prevent unbounded recursion
857    # arising from repeatedly yielding immediately ready deferreds.  This while
858    # loop and the waiting variable solve that by manually unfolding the
859    # recursion.
860
861    waiting = [True, # defgen is waiting for result?
862               None] # result
863
864    while 1:
865        try:
866            result = g.next()
867        except StopIteration:
868            deferred.callback(result)
869            return deferred
870        except:
871            deferred.errback()
872            return deferred
873
874        # Deferred.callback(Deferred) raises an error; we catch this case
875        # early here and give a nicer error message to the user in case
876        # they yield a Deferred.
877        if isinstance(result, Deferred):
878            return fail(TypeError("Yield waitForDeferred(d), not d!"))
879
880        if isinstance(result, waitForDeferred):
881            # a waitForDeferred was yielded, get the result.
882            # Pass result in so it don't get changed going around the loop
883            # This isn't a problem for waiting, as it's only reused if
884            # gotResult has already been executed.
885            def gotResult(r, result=result):
886                result.result = r
887                if waiting[0]:
888                    waiting[0] = False
889                    waiting[1] = r
890                else:
891                    _deferGenerator(g, deferred)
892            result.d.addBoth(gotResult)
893            if waiting[0]:
894                # Haven't called back yet, set flag so that we get reinvoked
895                # and return from the loop
896                waiting[0] = False
897                return deferred
898            # Reset waiting to initial values for next loop
899            waiting[0] = True
900            waiting[1] = None
901
902            result = None
903
904
905
906def deferredGenerator(f):
907    """
908    deferredGenerator and waitForDeferred help you write L{Deferred}-using code
909    that looks like a regular sequential function. If your code has a minimum
910    requirement of Python 2.5, consider the use of L{inlineCallbacks} instead,
911    which can accomplish the same thing in a more concise manner.
912
913    There are two important functions involved: L{waitForDeferred}, and
914    L{deferredGenerator}.  They are used together, like this::
915
916        def thingummy():
917            thing = waitForDeferred(makeSomeRequestResultingInDeferred())
918            yield thing
919            thing = thing.getResult()
920            print thing #the result! hoorj!
921        thingummy = deferredGenerator(thingummy)
922
923    L{waitForDeferred} returns something that you should immediately yield; when
924    your generator is resumed, calling C{thing.getResult()} will either give you
925    the result of the L{Deferred} if it was a success, or raise an exception if it
926    was a failure.  Calling C{getResult} is B{absolutely mandatory}.  If you do
927    not call it, I{your program will not work}.
928
929    L{deferredGenerator} takes one of these waitForDeferred-using generator
930    functions and converts it into a function that returns a L{Deferred}. The
931    result of the L{Deferred} will be the last value that your generator yielded
932    unless the last value is a L{waitForDeferred} instance, in which case the
933    result will be C{None}.  If the function raises an unhandled exception, the
934    L{Deferred} will errback instead.  Remember that C{return result} won't work;
935    use C{yield result; return} in place of that.
936
937    Note that not yielding anything from your generator will make the L{Deferred}
938    result in C{None}. Yielding a L{Deferred} from your generator is also an error
939    condition; always yield C{waitForDeferred(d)} instead.
940
941    The L{Deferred} returned from your deferred generator may also errback if your
942    generator raised an exception.  For example::
943
944        def thingummy():
945            thing = waitForDeferred(makeSomeRequestResultingInDeferred())
946            yield thing
947            thing = thing.getResult()
948            if thing == 'I love Twisted':
949                # will become the result of the Deferred
950                yield 'TWISTED IS GREAT!'
951                return
952            else:
953                # will trigger an errback
954                raise Exception('DESTROY ALL LIFE')
955        thingummy = deferredGenerator(thingummy)
956
957    Put succinctly, these functions connect deferred-using code with this 'fake
958    blocking' style in both directions: L{waitForDeferred} converts from a
959    L{Deferred} to the 'blocking' style, and L{deferredGenerator} converts from the
960    'blocking' style to a L{Deferred}.
961    """
962
963    def unwindGenerator(*args, **kwargs):
964        return _deferGenerator(f(*args, **kwargs), Deferred())
965    return mergeFunctionMetadata(f, unwindGenerator)
966
967
968## inlineCallbacks
969
970# BaseException is only in Py 2.5.
971try:
972    BaseException
973except NameError:
974    BaseException=Exception
975
976
977
978class _DefGen_Return(BaseException):
979    def __init__(self, value):
980        self.value = value
981
982
983
984def returnValue(val):
985    """
986    Return val from a L{inlineCallbacks} generator.
987
988    Note: this is currently implemented by raising an exception
989    derived from L{BaseException}.  You might want to change any
990    'except:' clauses to an 'except Exception:' clause so as not to
991    catch this exception.
992
993    Also: while this function currently will work when called from
994    within arbitrary functions called from within the generator, do
995    not rely upon this behavior.
996    """
997    raise _DefGen_Return(val)
998
999
1000
1001def _inlineCallbacks(result, g, deferred):
1002    """
1003    See L{inlineCallbacks}.
1004    """
1005    # This function is complicated by the need to prevent unbounded recursion
1006    # arising from repeatedly yielding immediately ready deferreds.  This while
1007    # loop and the waiting variable solve that by manually unfolding the
1008    # recursion.
1009
1010    waiting = [True, # waiting for result?
1011               None] # result
1012
1013    while 1:
1014        try:
1015            # Send the last result back as the result of the yield expression.
1016            isFailure = isinstance(result, failure.Failure)
1017            if isFailure:
1018                result = result.throwExceptionIntoGenerator(g)
1019            else:
1020                result = g.send(result)
1021        except StopIteration:
1022            # fell off the end, or "return" statement
1023            deferred.callback(None)
1024            return deferred
1025        except _DefGen_Return, e:
1026            # returnValue() was called; time to give a result to the original
1027            # Deferred.  First though, let's try to identify the potentially
1028            # confusing situation which results when returnValue() is
1029            # accidentally invoked from a different function, one that wasn't
1030            # decorated with @inlineCallbacks.
1031
1032            # The traceback starts in this frame (the one for
1033            # _inlineCallbacks); the next one down should be the application
1034            # code.
1035            appCodeTrace = exc_info()[2].tb_next
1036            if isFailure:
1037                # If we invoked this generator frame by throwing an exception
1038                # into it, then throwExceptionIntoGenerator will consume an
1039                # additional stack frame itself, so we need to skip that too.
1040                appCodeTrace = appCodeTrace.tb_next
1041            # Now that we've identified the frame being exited by the
1042            # exception, let's figure out if returnValue was called from it
1043            # directly.  returnValue itself consumes a stack frame, so the
1044            # application code will have a tb_next, but it will *not* have a
1045            # second tb_next.
1046            if appCodeTrace.tb_next.tb_next:
1047                # If returnValue was invoked non-local to the frame which it is
1048                # exiting, identify the frame that ultimately invoked
1049                # returnValue so that we can warn the user, as this behavior is
1050                # confusing.
1051                ultimateTrace = appCodeTrace
1052                while ultimateTrace.tb_next.tb_next:
1053                    ultimateTrace = ultimateTrace.tb_next
1054                filename = ultimateTrace.tb_frame.f_code.co_filename
1055                lineno = ultimateTrace.tb_lineno
1056                warnings.warn_explicit(
1057                    "returnValue() in %r causing %r to exit: "
1058                    "returnValue should only be invoked by functions decorated "
1059                    "with inlineCallbacks" % (
1060                        ultimateTrace.tb_frame.f_code.co_name,
1061                        appCodeTrace.tb_frame.f_code.co_name),
1062                    DeprecationWarning, filename, lineno)
1063            deferred.callback(e.value)
1064            return deferred
1065        except:
1066            deferred.errback()
1067            return deferred
1068
1069        if isinstance(result, Deferred):
1070            # a deferred was yielded, get the result.
1071            def gotResult(r):
1072                if waiting[0]:
1073                    waiting[0] = False
1074                    waiting[1] = r
1075                else:
1076                    _inlineCallbacks(r, g, deferred)
1077
1078            result.addBoth(gotResult)
1079            if waiting[0]:
1080                # Haven't called back yet, set flag so that we get reinvoked
1081                # and return from the loop
1082                waiting[0] = False
1083                return deferred
1084
1085            result = waiting[1]
1086            # Reset waiting to initial values for next loop.  gotResult uses
1087            # waiting, but this isn't a problem because gotResult is only
1088            # executed once, and if it hasn't been executed yet, the return
1089            # branch above would have been taken.
1090
1091
1092            waiting[0] = True
1093            waiting[1] = None
1094
1095
1096    return deferred
1097
1098
1099
1100def inlineCallbacks(f):
1101    """
1102    WARNING: this function will not work in Python 2.4 and earlier!
1103
1104    inlineCallbacks helps you write Deferred-using code that looks like a
1105    regular sequential function. This function uses features of Python 2.5
1106    generators.  If you need to be compatible with Python 2.4 or before, use
1107    the L{deferredGenerator} function instead, which accomplishes the same
1108    thing, but with somewhat more boilerplate.  For example::
1109
1110        def thingummy():
1111            thing = yield makeSomeRequestResultingInDeferred()
1112            print thing #the result! hoorj!
1113        thingummy = inlineCallbacks(thingummy)
1114
1115    When you call anything that results in a L{Deferred}, you can simply yield it;
1116    your generator will automatically be resumed when the Deferred's result is
1117    available. The generator will be sent the result of the L{Deferred} with the
1118    'send' method on generators, or if the result was a failure, 'throw'.
1119
1120    Your inlineCallbacks-enabled generator will return a L{Deferred} object, which
1121    will result in the return value of the generator (or will fail with a
1122    failure object if your generator raises an unhandled exception). Note that
1123    you can't use C{return result} to return a value; use C{returnValue(result)}
1124    instead. Falling off the end of the generator, or simply using C{return}
1125    will cause the L{Deferred} to have a result of C{None}.
1126
1127    The L{Deferred} returned from your deferred generator may errback if your
1128    generator raised an exception::
1129
1130        def thingummy():
1131            thing = yield makeSomeRequestResultingInDeferred()
1132            if thing == 'I love Twisted':
1133                # will become the result of the Deferred
1134                returnValue('TWISTED IS GREAT!')
1135            else:
1136                # will trigger an errback
1137                raise Exception('DESTROY ALL LIFE')
1138        thingummy = inlineCallbacks(thingummy)
1139    """
1140    def unwindGenerator(*args, **kwargs):
1141        return _inlineCallbacks(None, f(*args, **kwargs), Deferred())
1142    return mergeFunctionMetadata(f, unwindGenerator)
1143
1144
1145## DeferredLock/DeferredQueue
1146
1147class _ConcurrencyPrimitive(object):
1148    def __init__(self):
1149        self.waiting = []
1150
1151
1152    def _releaseAndReturn(self, r):
1153        self.release()
1154        return r
1155
1156
1157    def run(*args, **kwargs):
1158        """
1159        Acquire, run, release.
1160
1161        This function takes a callable as its first argument and any
1162        number of other positional and keyword arguments.  When the
1163        lock or semaphore is acquired, the callable will be invoked
1164        with those arguments.
1165
1166        The callable may return a L{Deferred}; if it does, the lock or
1167        semaphore won't be released until that L{Deferred} fires.
1168
1169        @return: L{Deferred} of function result.
1170        """
1171        if len(args) < 2:
1172            if not args:
1173                raise TypeError("run() takes at least 2 arguments, none given.")
1174            raise TypeError("%s.run() takes at least 2 arguments, 1 given" % (
1175                args[0].__class__.__name__,))
1176        self, f = args[:2]
1177        args = args[2:]
1178
1179        def execute(ignoredResult):
1180            d = maybeDeferred(f, *args, **kwargs)
1181            d.addBoth(self._releaseAndReturn)
1182            return d
1183
1184        d = self.acquire()
1185        d.addCallback(execute)
1186        return d
1187
1188
1189
1190class DeferredLock(_ConcurrencyPrimitive):
1191    """
1192    A lock for event driven systems.
1193
1194    @ivar locked: C{True} when this Lock has been acquired, false at all other
1195        times.  Do not change this value, but it is useful to examine for the
1196        equivalent of a "non-blocking" acquisition.
1197    """
1198
1199    locked = False
1200
1201
1202    def _cancelAcquire(self, d):
1203        """
1204        Remove a deferred d from our waiting list, as the deferred has been
1205        canceled.
1206
1207        Note: We do not need to wrap this in a try/except to catch d not
1208        being in self.waiting because this canceller will not be called if
1209        d has fired. release() pops a deferred out of self.waiting and
1210        calls it, so the canceller will no longer be called.
1211
1212        @param d: The deferred that has been canceled.
1213        """
1214        self.waiting.remove(d)
1215
1216
1217    def acquire(self):
1218        """
1219        Attempt to acquire the lock.  Returns a L{Deferred} that fires on
1220        lock acquisition with the L{DeferredLock} as the value.  If the lock
1221        is locked, then the Deferred is placed at the end of a waiting list.
1222
1223        @return: a L{Deferred} which fires on lock acquisition.
1224        @rtype: a L{Deferred}
1225        """
1226        d = Deferred(canceller=self._cancelAcquire)
1227        if self.locked:
1228            self.waiting.append(d)
1229        else:
1230            self.locked = True
1231            d.callback(self)
1232        return d
1233
1234
1235    def release(self):
1236        """
1237        Release the lock.  If there is a waiting list, then the first
1238        L{Deferred} in that waiting list will be called back.
1239
1240        Should be called by whomever did the L{acquire}() when the shared
1241        resource is free.
1242        """
1243        assert self.locked, "Tried to release an unlocked lock"
1244        self.locked = False
1245        if self.waiting:
1246            # someone is waiting to acquire lock
1247            self.locked = True
1248            d = self.waiting.pop(0)
1249            d.callback(self)
1250
1251
1252
1253class DeferredSemaphore(_ConcurrencyPrimitive):
1254    """
1255    A semaphore for event driven systems.
1256
1257    @ivar tokens: At most this many users may acquire this semaphore at
1258        once.
1259    @type tokens: C{int}
1260
1261    @ivar limit: The difference between C{tokens} and the number of users
1262        which have currently acquired this semaphore.
1263    @type limit: C{int}
1264    """
1265
1266    def __init__(self, tokens):
1267        _ConcurrencyPrimitive.__init__(self)
1268        if tokens < 1:
1269            raise ValueError("DeferredSemaphore requires tokens >= 1")
1270        self.tokens = tokens
1271        self.limit = tokens
1272
1273
1274    def _cancelAcquire(self, d):
1275        """
1276        Remove a deferred d from our waiting list, as the deferred has been
1277        canceled.
1278
1279        Note: We do not need to wrap this in a try/except to catch d not
1280        being in self.waiting because this canceller will not be called if
1281        d has fired. release() pops a deferred out of self.waiting and
1282        calls it, so the canceller will no longer be called.
1283
1284        @param d: The deferred that has been canceled.
1285        """
1286        self.waiting.remove(d)
1287
1288
1289    def acquire(self):
1290        """
1291        Attempt to acquire the token.
1292
1293        @return: a L{Deferred} which fires on token acquisition.
1294        """
1295        assert self.tokens >= 0, "Internal inconsistency??  tokens should never be negative"
1296        d = Deferred(canceller=self._cancelAcquire)
1297        if not self.tokens:
1298            self.waiting.append(d)
1299        else:
1300            self.tokens = self.tokens - 1
1301            d.callback(self)
1302        return d
1303
1304
1305    def release(self):
1306        """
1307        Release the token.
1308
1309        Should be called by whoever did the L{acquire}() when the shared
1310        resource is free.
1311        """
1312        assert self.tokens < self.limit, "Someone released me too many times: too many tokens!"
1313        self.tokens = self.tokens + 1
1314        if self.waiting:
1315            # someone is waiting to acquire token
1316            self.tokens = self.tokens - 1
1317            d = self.waiting.pop(0)
1318            d.callback(self)
1319
1320
1321
1322class QueueOverflow(Exception):
1323    pass
1324
1325
1326
1327class QueueUnderflow(Exception):
1328    pass
1329
1330
1331
1332class DeferredQueue(object):
1333    """
1334    An event driven queue.
1335
1336    Objects may be added as usual to this queue.  When an attempt is
1337    made to retrieve an object when the queue is empty, a L{Deferred} is
1338    returned which will fire when an object becomes available.
1339
1340    @ivar size: The maximum number of objects to allow into the queue
1341    at a time.  When an attempt to add a new object would exceed this
1342    limit, L{QueueOverflow} is raised synchronously.  C{None} for no limit.
1343
1344    @ivar backlog: The maximum number of L{Deferred} gets to allow at
1345    one time.  When an attempt is made to get an object which would
1346    exceed this limit, L{QueueUnderflow} is raised synchronously.  C{None}
1347    for no limit.
1348    """
1349
1350    def __init__(self, size=None, backlog=None):
1351        self.waiting = []
1352        self.pending = []
1353        self.size = size
1354        self.backlog = backlog
1355
1356
1357    def _cancelGet(self, d):
1358        """
1359        Remove a deferred d from our waiting list, as the deferred has been
1360        canceled.
1361
1362        Note: We do not need to wrap this in a try/except to catch d not
1363        being in self.waiting because this canceller will not be called if
1364        d has fired. put() pops a deferred out of self.waiting and calls
1365        it, so the canceller will no longer be called.
1366
1367        @param d: The deferred that has been canceled.
1368        """
1369        self.waiting.remove(d)
1370
1371
1372    def put(self, obj):
1373        """
1374        Add an object to this queue.
1375
1376        @raise QueueOverflow: Too many objects are in this queue.
1377        """
1378        if self.waiting:
1379            self.waiting.pop(0).callback(obj)
1380        elif self.size is None or len(self.pending) < self.size:
1381            self.pending.append(obj)
1382        else:
1383            raise QueueOverflow()
1384
1385
1386    def get(self):
1387        """
1388        Attempt to retrieve and remove an object from the queue.
1389
1390        @return: a L{Deferred} which fires with the next object available in
1391        the queue.
1392
1393        @raise QueueUnderflow: Too many (more than C{backlog})
1394        L{Deferred}s are already waiting for an object from this queue.
1395        """
1396        if self.pending:
1397            return succeed(self.pending.pop(0))
1398        elif self.backlog is None or len(self.waiting) < self.backlog:
1399            d = Deferred(canceller=self._cancelGet)
1400            self.waiting.append(d)
1401            return d
1402        else:
1403            raise QueueUnderflow()
1404
1405
1406
1407class AlreadyTryingToLockError(Exception):
1408    """
1409    Raised when L{DeferredFilesystemLock.deferUntilLocked} is called twice on a
1410    single L{DeferredFilesystemLock}.
1411    """
1412
1413
1414
1415class DeferredFilesystemLock(lockfile.FilesystemLock):
1416    """
1417    A L{FilesystemLock} that allows for a L{Deferred} to be fired when the lock is
1418    acquired.
1419
1420    @ivar _scheduler: The object in charge of scheduling retries. In this
1421        implementation this is parameterized for testing.
1422
1423    @ivar _interval: The retry interval for an L{IReactorTime} based scheduler.
1424
1425    @ivar _tryLockCall: A L{DelayedCall} based on C{_interval} that will manage
1426        the next retry for aquiring the lock.
1427
1428    @ivar _timeoutCall: A L{DelayedCall} based on C{deferUntilLocked}'s timeout
1429        argument.  This is in charge of timing out our attempt to acquire the
1430        lock.
1431    """
1432    _interval = 1
1433    _tryLockCall = None
1434    _timeoutCall = None
1435
1436
1437    def __init__(self, name, scheduler=None):
1438        """
1439        @param name: The name of the lock to acquire
1440        @param scheduler: An object which provides L{IReactorTime}
1441        """
1442        lockfile.FilesystemLock.__init__(self, name)
1443
1444        if scheduler is None:
1445            from twisted.internet import reactor
1446            scheduler = reactor
1447
1448        self._scheduler = scheduler
1449
1450
1451    def deferUntilLocked(self, timeout=None):
1452        """
1453        Wait until we acquire this lock.  This method is not safe for
1454        concurrent use.
1455
1456        @type timeout: C{float} or C{int}
1457        @param timeout: the number of seconds after which to time out if the
1458            lock has not been acquired.
1459
1460        @return: a L{Deferred} which will callback when the lock is acquired, or
1461            errback with a L{TimeoutError} after timing out or an
1462            L{AlreadyTryingToLockError} if the L{deferUntilLocked} has already
1463            been called and not successfully locked the file.
1464        """
1465        if self._tryLockCall is not None:
1466            return fail(
1467                AlreadyTryingToLockError(
1468                    "deferUntilLocked isn't safe for concurrent use."))
1469
1470        d = Deferred()
1471
1472        def _cancelLock():
1473            self._tryLockCall.cancel()
1474            self._tryLockCall = None
1475            self._timeoutCall = None
1476
1477            if self.lock():
1478                d.callback(None)
1479            else:
1480                d.errback(failure.Failure(
1481                        TimeoutError("Timed out aquiring lock: %s after %fs" % (
1482                                self.name,
1483                                timeout))))
1484
1485        def _tryLock():
1486            if self.lock():
1487                if self._timeoutCall is not None:
1488                    self._timeoutCall.cancel()
1489                    self._timeoutCall = None
1490
1491                self._tryLockCall = None
1492
1493                d.callback(None)
1494            else:
1495                if timeout is not None and self._timeoutCall is None:
1496                    self._timeoutCall = self._scheduler.callLater(
1497                        timeout, _cancelLock)
1498
1499                self._tryLockCall = self._scheduler.callLater(
1500                    self._interval, _tryLock)
1501
1502        _tryLock()
1503
1504        return d
1505
1506
1507
1508__all__ = ["Deferred", "DeferredList", "succeed", "fail", "FAILURE", "SUCCESS",
1509           "AlreadyCalledError", "TimeoutError", "gatherResults",
1510           "maybeDeferred",
1511           "waitForDeferred", "deferredGenerator", "inlineCallbacks",
1512           "returnValue",
1513           "DeferredLock", "DeferredSemaphore", "DeferredQueue",
1514           "DeferredFilesystemLock", "AlreadyTryingToLockError",
1515          ]
Note: See TracBrowser for help on using the browser.