mirror of
https://github.com/evennia/evennia.git
synced 2026-03-23 00:06:30 +01:00
2919 lines
No EOL
301 KiB
HTML
2919 lines
No EOL
301 KiB
HTML
<!DOCTYPE html>
|
|
|
|
<html lang="en" data-content_root="../../../">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>twisted.internet.defer — Evennia latest documentation</title>
|
|
<link rel="stylesheet" type="text/css" href="../../../_static/pygments.css?v=d75fae25" />
|
|
<link rel="stylesheet" type="text/css" href="../../../_static/nature.css?v=279e0f84" />
|
|
<link rel="stylesheet" type="text/css" href="../../../_static/custom.css?v=e4a91a55" />
|
|
<script src="../../../_static/documentation_options.js?v=c6e86fd7"></script>
|
|
<script src="../../../_static/doctools.js?v=9bcbadda"></script>
|
|
<script src="../../../_static/sphinx_highlight.js?v=dc90522c"></script>
|
|
<link rel="icon" href="../../../_static/favicon.ico"/>
|
|
<link rel="index" title="Index" href="../../../genindex.html" />
|
|
<link rel="search" title="Search" href="../../../search.html" />
|
|
</head><body>
|
|
<div class="related" role="navigation" aria-label="Related">
|
|
<h3>Navigation</h3>
|
|
<ul>
|
|
<li class="right" style="margin-right: 10px">
|
|
<a href="../../../genindex.html" title="General Index"
|
|
accesskey="I">index</a></li>
|
|
<li class="right" >
|
|
<a href="../../../py-modindex.html" title="Python Module Index"
|
|
>modules</a> |</li>
|
|
<li class="nav-item nav-item-0"><a href="../../../index.html">Evennia</a> »</li>
|
|
<li class="nav-item nav-item-1"><a href="../../index.html" accesskey="U">Module code</a> »</li>
|
|
<li class="nav-item nav-item-this"><a href="">twisted.internet.defer</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="document">
|
|
<div class="documentwrapper">
|
|
<div class="bodywrapper">
|
|
<div class="body" role="main">
|
|
|
|
<h1>Source code for twisted.internet.defer</h1><div class="highlight"><pre>
|
|
<span></span><span class="c1"># -*- test-case-name: twisted.test.test_defer -*-</span>
|
|
<span class="c1"># Copyright (c) Twisted Matrix Laboratories.</span>
|
|
<span class="c1"># See LICENSE for details.</span>
|
|
|
|
<span class="sd">"""</span>
|
|
<span class="sd">Support for results that aren't immediately available.</span>
|
|
|
|
<span class="sd">Maintainer: Glyph Lefkowitz</span>
|
|
<span class="sd">"""</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">__future__</span><span class="w"> </span><span class="kn">import</span> <span class="n">annotations</span>
|
|
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">inspect</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">traceback</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">warnings</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">abc</span><span class="w"> </span><span class="kn">import</span> <span class="n">ABC</span><span class="p">,</span> <span class="n">abstractmethod</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">asyncio</span><span class="w"> </span><span class="kn">import</span> <span class="n">AbstractEventLoop</span><span class="p">,</span> <span class="n">Future</span><span class="p">,</span> <span class="n">iscoroutine</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">contextvars</span><span class="w"> </span><span class="kn">import</span> <span class="n">Context</span> <span class="k">as</span> <span class="n">_Context</span><span class="p">,</span> <span class="n">copy_context</span> <span class="k">as</span> <span class="n">_copy_context</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">enum</span><span class="w"> </span><span class="kn">import</span> <span class="n">Enum</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">functools</span><span class="w"> </span><span class="kn">import</span> <span class="n">wraps</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">sys</span><span class="w"> </span><span class="kn">import</span> <span class="n">exc_info</span><span class="p">,</span> <span class="n">implementation</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">types</span><span class="w"> </span><span class="kn">import</span> <span class="n">CoroutineType</span><span class="p">,</span> <span class="n">GeneratorType</span><span class="p">,</span> <span class="n">MappingProxyType</span><span class="p">,</span> <span class="n">TracebackType</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="p">(</span>
|
|
<span class="n">TYPE_CHECKING</span><span class="p">,</span>
|
|
<span class="n">Any</span><span class="p">,</span>
|
|
<span class="n">Awaitable</span><span class="p">,</span>
|
|
<span class="n">Callable</span><span class="p">,</span>
|
|
<span class="n">Coroutine</span><span class="p">,</span>
|
|
<span class="n">Generator</span><span class="p">,</span>
|
|
<span class="n">Generic</span><span class="p">,</span>
|
|
<span class="n">Iterable</span><span class="p">,</span>
|
|
<span class="n">List</span><span class="p">,</span>
|
|
<span class="n">Mapping</span><span class="p">,</span>
|
|
<span class="n">NoReturn</span><span class="p">,</span>
|
|
<span class="n">Optional</span><span class="p">,</span>
|
|
<span class="n">Sequence</span><span class="p">,</span>
|
|
<span class="n">Tuple</span><span class="p">,</span>
|
|
<span class="n">Type</span><span class="p">,</span>
|
|
<span class="n">TypeVar</span><span class="p">,</span>
|
|
<span class="n">Union</span><span class="p">,</span>
|
|
<span class="n">cast</span><span class="p">,</span>
|
|
<span class="n">overload</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">attr</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">incremental</span><span class="w"> </span><span class="kn">import</span> <span class="n">Version</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">typing_extensions</span><span class="w"> </span><span class="kn">import</span> <span class="n">Concatenate</span><span class="p">,</span> <span class="n">Literal</span><span class="p">,</span> <span class="n">ParamSpec</span><span class="p">,</span> <span class="n">Self</span>
|
|
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">twisted.internet.interfaces</span><span class="w"> </span><span class="kn">import</span> <span class="n">IDelayedCall</span><span class="p">,</span> <span class="n">IReactorTime</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">twisted.logger</span><span class="w"> </span><span class="kn">import</span> <span class="n">Logger</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">twisted.python</span><span class="w"> </span><span class="kn">import</span> <span class="n">lockfile</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">twisted.python.compat</span><span class="w"> </span><span class="kn">import</span> <span class="n">_PYPY</span><span class="p">,</span> <span class="n">cmp</span><span class="p">,</span> <span class="n">comparable</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">twisted.python.deprecate</span><span class="w"> </span><span class="kn">import</span> <span class="n">deprecated</span><span class="p">,</span> <span class="n">warnAboutFunction</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">twisted.python.failure</span><span class="w"> </span><span class="kn">import</span> <span class="n">Failure</span><span class="p">,</span> <span class="n">_extraneous</span>
|
|
|
|
<span class="n">log</span> <span class="o">=</span> <span class="n">Logger</span><span class="p">()</span>
|
|
|
|
|
|
<span class="n">_T</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s2">"_T"</span><span class="p">)</span>
|
|
<span class="n">_P</span> <span class="o">=</span> <span class="n">ParamSpec</span><span class="p">(</span><span class="s2">"_P"</span><span class="p">)</span>
|
|
|
|
<span class="c1"># See use in _inlineCallbacks for explanation and removal timeline.</span>
|
|
<span class="n">_oldPypyStack</span> <span class="o">=</span> <span class="n">_PYPY</span> <span class="ow">and</span> <span class="n">implementation</span><span class="o">.</span><span class="n">version</span> <span class="o"><</span> <span class="p">(</span><span class="mi">7</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">14</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">AlreadyCalledError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> This error is raised when one of L{Deferred.callback} or L{Deferred.errback}</span>
|
|
<span class="sd"> is called after one of the two had already been called.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">CancelledError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> This error is raised by default when a L{Deferred} is cancelled.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">TimeoutError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> This error is raised by default when a L{Deferred} times out.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">NotACoroutineError</span><span class="p">(</span><span class="ne">TypeError</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> This error is raised when a coroutine is expected and something else is</span>
|
|
<span class="sd"> encountered.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">logError</span><span class="p">(</span><span class="n">err</span><span class="p">:</span> <span class="n">Failure</span><span class="p">)</span> <span class="o">-></span> <span class="n">Failure</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Log and return failure.</span>
|
|
|
|
<span class="sd"> This method can be used as an errback that passes the failure on to the</span>
|
|
<span class="sd"> next errback unmodified. Note that if this is the last errback, and the</span>
|
|
<span class="sd"> deferred gets garbage collected after being this errback has been called,</span>
|
|
<span class="sd"> the clean up code logs it again.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">log</span><span class="o">.</span><span class="n">failure</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span> <span class="n">err</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">err</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">succeed</span><span class="p">(</span><span class="n">result</span><span class="p">:</span> <span class="n">_T</span><span class="p">)</span> <span class="o">-></span> <span class="s2">"Deferred[_T]"</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Return a L{Deferred} that has already had C{.callback(result)} called.</span>
|
|
|
|
<span class="sd"> This is useful when you're writing synchronous code to an</span>
|
|
<span class="sd"> asynchronous interface: i.e., some code is calling you expecting a</span>
|
|
<span class="sd"> L{Deferred} result, but you don't actually need to do anything</span>
|
|
<span class="sd"> asynchronous. Just return C{defer.succeed(theResult)}.</span>
|
|
|
|
<span class="sd"> See L{fail} for a version of this function that uses a failing</span>
|
|
<span class="sd"> L{Deferred} rather than a successful one.</span>
|
|
|
|
<span class="sd"> @param result: The result to give to the Deferred's 'callback'</span>
|
|
<span class="sd"> method.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">d</span><span class="p">:</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">]</span> <span class="o">=</span> <span class="n">Deferred</span><span class="p">()</span>
|
|
<span class="c1"># This violate abstraction boundaries, so code that is not internal to</span>
|
|
<span class="c1"># Twisted shouldn't do it, but it's a significant performance optimization:</span>
|
|
<span class="n">d</span><span class="o">.</span><span class="n">result</span> <span class="o">=</span> <span class="n">result</span>
|
|
<span class="n">d</span><span class="o">.</span><span class="n">called</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">d</span><span class="o">.</span><span class="n">_chainedTo</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="k">return</span> <span class="n">d</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">fail</span><span class="p">(</span><span class="n">result</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Union</span><span class="p">[</span><span class="n">Failure</span><span class="p">,</span> <span class="ne">BaseException</span><span class="p">]]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">)</span> <span class="o">-></span> <span class="s2">"Deferred[Any]"</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Return a L{Deferred} that has already had C{.errback(result)} called.</span>
|
|
|
|
<span class="sd"> See L{succeed}'s docstring for rationale.</span>
|
|
|
|
<span class="sd"> @param result: The same argument that L{Deferred.errback} takes.</span>
|
|
|
|
<span class="sd"> @raise NoCurrentExceptionError: If C{result} is L{None} but there is no</span>
|
|
<span class="sd"> current exception state.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">d</span><span class="p">:</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">Any</span><span class="p">]</span> <span class="o">=</span> <span class="n">Deferred</span><span class="p">()</span>
|
|
<span class="n">d</span><span class="o">.</span><span class="n">errback</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">d</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">execute</span><span class="p">(</span>
|
|
<span class="nb">callable</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">_P</span><span class="p">,</span> <span class="n">_T</span><span class="p">],</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="s2">"Deferred[_T]"</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Create a L{Deferred} from a callable and arguments.</span>
|
|
|
|
<span class="sd"> Call the given function with the given arguments. Return a L{Deferred}</span>
|
|
<span class="sd"> which has been fired with its callback as the result of that invocation</span>
|
|
<span class="sd"> or its C{errback} with a L{Failure} for the exception thrown.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">result</span> <span class="o">=</span> <span class="nb">callable</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">BaseException</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">fail</span><span class="p">()</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">succeed</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
|
|
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">maybeDeferred</span><span class="p">(</span>
|
|
<span class="n">f</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">_P</span><span class="p">,</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">]],</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="s2">"Deferred[_T]"</span><span class="p">:</span>
|
|
<span class="o">...</span>
|
|
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">maybeDeferred</span><span class="p">(</span>
|
|
<span class="n">f</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">_P</span><span class="p">,</span> <span class="n">Coroutine</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">Any</span><span class="p">],</span> <span class="n">Any</span><span class="p">,</span> <span class="n">_T</span><span class="p">]],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="s2">"Deferred[_T]"</span><span class="p">:</span>
|
|
<span class="o">...</span>
|
|
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">maybeDeferred</span><span class="p">(</span>
|
|
<span class="n">f</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">_P</span><span class="p">,</span> <span class="n">_T</span><span class="p">],</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="s2">"Deferred[_T]"</span><span class="p">:</span>
|
|
<span class="o">...</span>
|
|
|
|
|
|
<div class="viewcode-block" id="maybeDeferred">
|
|
<a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.commands.cmdhandler.maybeDeferred">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">maybeDeferred</span><span class="p">(</span>
|
|
<span class="n">f</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">_P</span><span class="p">,</span> <span class="n">Union</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">],</span> <span class="n">Coroutine</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">Any</span><span class="p">],</span> <span class="n">Any</span><span class="p">,</span> <span class="n">_T</span><span class="p">],</span> <span class="n">_T</span><span class="p">]],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="s2">"Deferred[_T]"</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Invoke a function that may or may not return a L{Deferred} or coroutine.</span>
|
|
|
|
<span class="sd"> Call the given function with the given arguments. Then:</span>
|
|
|
|
<span class="sd"> - If the returned object is a L{Deferred}, return it.</span>
|
|
|
|
<span class="sd"> - If the returned object is a L{Failure}, wrap it with L{fail} and</span>
|
|
<span class="sd"> return it.</span>
|
|
|
|
<span class="sd"> - If the returned object is a L{types.CoroutineType}, wrap it with</span>
|
|
<span class="sd"> L{Deferred.fromCoroutine} and return it.</span>
|
|
|
|
<span class="sd"> - Otherwise, wrap it in L{succeed} and return it.</span>
|
|
|
|
<span class="sd"> - If an exception is raised, convert it to a L{Failure}, wrap it in</span>
|
|
<span class="sd"> L{fail}, and then return it.</span>
|
|
|
|
<span class="sd"> @param f: The callable to invoke</span>
|
|
<span class="sd"> @param args: The arguments to pass to C{f}</span>
|
|
<span class="sd"> @param kwargs: The keyword arguments to pass to C{f}</span>
|
|
|
|
<span class="sd"> @return: The result of the function call, wrapped in a L{Deferred} if</span>
|
|
<span class="sd"> necessary.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">result</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">BaseException</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">fail</span><span class="p">(</span><span class="n">Failure</span><span class="p">(</span><span class="n">captureVars</span><span class="o">=</span><span class="n">Deferred</span><span class="o">.</span><span class="n">debug</span><span class="p">))</span>
|
|
|
|
<span class="k">if</span> <span class="nb">type</span><span class="p">(</span><span class="n">result</span><span class="p">)</span> <span class="ow">in</span> <span class="n">_DEFERRED_SUBCLASSES</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">result</span> <span class="c1"># type: ignore[return-value]</span>
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">Failure</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="n">fail</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="nb">type</span><span class="p">(</span><span class="n">result</span><span class="p">)</span> <span class="ow">is</span> <span class="n">CoroutineType</span><span class="p">:</span>
|
|
<span class="c1"># A note on how we identify this case ...</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># inspect.iscoroutinefunction(f) should be the simplest and easiest</span>
|
|
<span class="c1"># way to determine if we want to apply coroutine handling. However,</span>
|
|
<span class="c1"># the value may be returned by a regular function that calls a</span>
|
|
<span class="c1"># coroutine function and returns its result. It would be confusing if</span>
|
|
<span class="c1"># cases like this led to different handling of the coroutine (even</span>
|
|
<span class="c1"># though it is a mistake to have a regular function call a coroutine</span>
|
|
<span class="c1"># function to return its result - doing so immediately destroys a</span>
|
|
<span class="c1"># large part of the value of coroutine functions: that they can only</span>
|
|
<span class="c1"># have a coroutine result).</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># There are many ways we could inspect ``result`` to determine if it</span>
|
|
<span class="c1"># is a "coroutine" but most of these are mistakes. The goal is only</span>
|
|
<span class="c1"># to determine whether the value came from ``async def`` or not</span>
|
|
<span class="c1"># because these are the only values we're trying to handle with this</span>
|
|
<span class="c1"># case. Such values always have exactly one type: CoroutineType.</span>
|
|
<span class="k">return</span> <span class="n">Deferred</span><span class="o">.</span><span class="n">fromCoroutine</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">returned</span><span class="p">:</span> <span class="n">_T</span> <span class="o">=</span> <span class="n">result</span> <span class="c1"># type: ignore</span>
|
|
<span class="k">return</span> <span class="n">succeed</span><span class="p">(</span><span class="n">returned</span><span class="p">)</span></div>
|
|
|
|
|
|
|
|
<span class="nd">@deprecated</span><span class="p">(</span>
|
|
<span class="n">Version</span><span class="p">(</span><span class="s2">"Twisted"</span><span class="p">,</span> <span class="mi">17</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span>
|
|
<span class="n">replacement</span><span class="o">=</span><span class="s2">"twisted.internet.defer.Deferred.addTimeout"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">timeout</span><span class="p">(</span><span class="n">deferred</span><span class="p">:</span> <span class="s2">"Deferred[object]"</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">deferred</span><span class="o">.</span><span class="n">errback</span><span class="p">(</span><span class="n">Failure</span><span class="p">(</span><span class="ne">TimeoutError</span><span class="p">(</span><span class="s2">"Callback timed out"</span><span class="p">)))</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">passthru</span><span class="p">(</span><span class="n">arg</span><span class="p">:</span> <span class="n">_T</span><span class="p">)</span> <span class="o">-></span> <span class="n">_T</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">arg</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_failthru</span><span class="p">(</span><span class="n">arg</span><span class="p">:</span> <span class="n">Failure</span><span class="p">)</span> <span class="o">-></span> <span class="n">Failure</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">arg</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">setDebugging</span><span class="p">(</span><span class="n">on</span><span class="p">:</span> <span class="nb">bool</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Enable or disable L{Deferred} debugging.</span>
|
|
|
|
<span class="sd"> When debugging is on, the call stacks from creation and invocation are</span>
|
|
<span class="sd"> recorded, and added to any L{AlreadyCalledError}s we raise.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">Deferred</span><span class="o">.</span><span class="n">debug</span> <span class="o">=</span> <span class="nb">bool</span><span class="p">(</span><span class="n">on</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">getDebugging</span><span class="p">()</span> <span class="o">-></span> <span class="nb">bool</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Determine whether L{Deferred} debugging is enabled.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">return</span> <span class="n">Deferred</span><span class="o">.</span><span class="n">debug</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_cancelledToTimedOutError</span><span class="p">(</span><span class="n">value</span><span class="p">:</span> <span class="n">_T</span><span class="p">,</span> <span class="n">timeout</span><span class="p">:</span> <span class="nb">float</span><span class="p">)</span> <span class="o">-></span> <span class="n">_T</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> A default translation function that translates L{Failure}s that are</span>
|
|
<span class="sd"> L{CancelledError}s to L{TimeoutError}s.</span>
|
|
|
|
<span class="sd"> @param value: Anything</span>
|
|
<span class="sd"> @param timeout: The timeout</span>
|
|
|
|
<span class="sd"> @raise TimeoutError: If C{value} is a L{Failure} that is a L{CancelledError}.</span>
|
|
<span class="sd"> @raise Exception: If C{value} is a L{Failure} that is not a L{CancelledError},</span>
|
|
<span class="sd"> it is re-raised.</span>
|
|
|
|
<span class="sd"> @since: 16.5</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">Failure</span><span class="p">):</span>
|
|
<span class="n">value</span><span class="o">.</span><span class="n">trap</span><span class="p">(</span><span class="n">CancelledError</span><span class="p">)</span>
|
|
<span class="k">raise</span> <span class="ne">TimeoutError</span><span class="p">(</span><span class="n">timeout</span><span class="p">,</span> <span class="s2">"Deferred"</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">value</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">_Sentinel</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> @cvar _NO_RESULT:</span>
|
|
<span class="sd"> The result used to represent the fact that there is no result.</span>
|
|
<span class="sd"> B{Never ever ever use this as an actual result for a Deferred}.</span>
|
|
<span class="sd"> You have been warned.</span>
|
|
<span class="sd"> @cvar _CONTINUE:</span>
|
|
<span class="sd"> A marker left in L{Deferred.callback}s to indicate a Deferred chain.</span>
|
|
<span class="sd"> Always accompanied by a Deferred instance in the args tuple pointing at</span>
|
|
<span class="sd"> the Deferred which is chained to the Deferred which has this marker.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">_NO_RESULT</span> <span class="o">=</span> <span class="nb">object</span><span class="p">()</span>
|
|
<span class="n">_CONTINUE</span> <span class="o">=</span> <span class="nb">object</span><span class="p">()</span>
|
|
|
|
|
|
<span class="c1"># Cache these values for use without the extra lookup in deferred hot code paths</span>
|
|
<span class="n">_NO_RESULT</span> <span class="o">=</span> <span class="n">_Sentinel</span><span class="o">.</span><span class="n">_NO_RESULT</span>
|
|
<span class="n">_CONTINUE</span> <span class="o">=</span> <span class="n">_Sentinel</span><span class="o">.</span><span class="n">_CONTINUE</span>
|
|
|
|
|
|
<span class="c1"># type note: this should be Callable[[object, ...], object] but mypy doesn't allow.</span>
|
|
<span class="c1"># Callable[[object], object] is next best, but disallows valid callback signatures</span>
|
|
<span class="n">DeferredCallback</span> <span class="o">=</span> <span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="nb">object</span><span class="p">]</span>
|
|
<span class="c1"># type note: this should be Callable[[Failure, ...], object] but mypy doesn't allow.</span>
|
|
<span class="c1"># Callable[[Failure], object] is next best, but disallows valid callback signatures</span>
|
|
<span class="n">DeferredErrback</span> <span class="o">=</span> <span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="nb">object</span><span class="p">]</span>
|
|
|
|
<span class="n">_CallbackOrderedArguments</span> <span class="o">=</span> <span class="n">Tuple</span><span class="p">[</span><span class="nb">object</span><span class="p">,</span> <span class="o">...</span><span class="p">]</span>
|
|
<span class="n">_CallbackKeywordArguments</span> <span class="o">=</span> <span class="n">Mapping</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">object</span><span class="p">]</span>
|
|
<span class="n">_CallbackChain</span> <span class="o">=</span> <span class="n">Tuple</span><span class="p">[</span>
|
|
<span class="n">Tuple</span><span class="p">[</span>
|
|
<span class="n">Union</span><span class="p">[</span><span class="n">DeferredCallback</span><span class="p">,</span> <span class="n">Literal</span><span class="p">[</span><span class="n">_Sentinel</span><span class="o">.</span><span class="n">_CONTINUE</span><span class="p">]],</span>
|
|
<span class="n">_CallbackOrderedArguments</span><span class="p">,</span>
|
|
<span class="n">_CallbackKeywordArguments</span><span class="p">,</span>
|
|
<span class="p">],</span>
|
|
<span class="n">Tuple</span><span class="p">[</span>
|
|
<span class="n">Union</span><span class="p">[</span><span class="n">DeferredErrback</span><span class="p">,</span> <span class="n">DeferredCallback</span><span class="p">,</span> <span class="n">Literal</span><span class="p">[</span><span class="n">_Sentinel</span><span class="o">.</span><span class="n">_CONTINUE</span><span class="p">]],</span>
|
|
<span class="n">_CallbackOrderedArguments</span><span class="p">,</span>
|
|
<span class="n">_CallbackKeywordArguments</span><span class="p">,</span>
|
|
<span class="p">],</span>
|
|
<span class="p">]</span>
|
|
|
|
<span class="n">_NONE_KWARGS</span><span class="p">:</span> <span class="n">_CallbackKeywordArguments</span> <span class="o">=</span> <span class="n">MappingProxyType</span><span class="p">({})</span>
|
|
|
|
|
|
<span class="n">_SelfResultT</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s2">"_SelfResultT"</span><span class="p">)</span>
|
|
<span class="n">_NextResultT</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s2">"_NextResultT"</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">DebugInfo</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Deferred debug helper.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">failResult</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Failure</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">creator</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]]</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">invoker</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]]</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_getDebugTracebacks</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
|
|
<span class="n">info</span> <span class="o">=</span> <span class="s2">""</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">creator</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">info</span> <span class="o">+=</span> <span class="s2">" C: Deferred was created:</span><span class="se">\n</span><span class="s2"> C:"</span>
|
|
<span class="n">info</span> <span class="o">+=</span> <span class="s2">""</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">creator</span><span class="p">)</span><span class="o">.</span><span class="n">rstrip</span><span class="p">()</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="s2">"</span><span class="se">\n</span><span class="s2"> C:"</span><span class="p">)</span>
|
|
<span class="n">info</span> <span class="o">+=</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">invoker</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">info</span> <span class="o">+=</span> <span class="s2">" I: First Invoker was:</span><span class="se">\n</span><span class="s2"> I:"</span>
|
|
<span class="n">info</span> <span class="o">+=</span> <span class="s2">""</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">invoker</span><span class="p">)</span><span class="o">.</span><span class="n">rstrip</span><span class="p">()</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="s2">"</span><span class="se">\n</span><span class="s2"> I:"</span><span class="p">)</span>
|
|
<span class="n">info</span> <span class="o">+=</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span>
|
|
<span class="k">return</span> <span class="n">info</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__del__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Print tracebacks and die.</span>
|
|
|
|
<span class="sd"> If the *last* (and I do mean *last*) callback leaves me in an error</span>
|
|
<span class="sd"> state, print a traceback (if said errback is a L{Failure}).</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">failResult</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="c1"># Note: this is two separate messages for compatibility with</span>
|
|
<span class="c1"># earlier tests; arguably it should be a single error message.</span>
|
|
<span class="n">log</span><span class="o">.</span><span class="n">critical</span><span class="p">(</span><span class="s2">"Unhandled error in Deferred:"</span><span class="p">,</span> <span class="n">isError</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
|
|
|
<span class="n">debugInfo</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_getDebugTracebacks</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="n">debugInfo</span><span class="p">:</span>
|
|
<span class="nb">format</span> <span class="o">=</span> <span class="s2">"(debug: </span><span class="si">{debugInfo}</span><span class="s2">)"</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="nb">format</span> <span class="o">=</span> <span class="s2">""</span>
|
|
|
|
<span class="n">log</span><span class="o">.</span><span class="n">failure</span><span class="p">(</span><span class="nb">format</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">failResult</span><span class="p">,</span> <span class="n">debugInfo</span><span class="o">=</span><span class="n">debugInfo</span><span class="p">)</span>
|
|
|
|
|
|
<div class="viewcode-block" id="Deferred">
|
|
<a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.commands.cmdhandler.Deferred">[docs]</a>
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">Deferred</span><span class="p">(</span><span class="n">Awaitable</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">]):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> This is a callback which will be put off until later.</span>
|
|
|
|
<span class="sd"> Why do we want this? Well, in cases where a function in a threaded</span>
|
|
<span class="sd"> program would block until it gets a result, for Twisted it should</span>
|
|
<span class="sd"> not block. Instead, it should return a L{Deferred}.</span>
|
|
|
|
<span class="sd"> This can be implemented for protocols that run over the network by</span>
|
|
<span class="sd"> writing an asynchronous protocol for L{twisted.internet}. For methods</span>
|
|
<span class="sd"> that come from outside packages that are not under our control, we use</span>
|
|
<span class="sd"> threads (see for example L{twisted.enterprise.adbapi}).</span>
|
|
|
|
<span class="sd"> For more information about Deferreds, see doc/core/howto/defer.html or</span>
|
|
<span class="sd"> U{http://twistedmatrix.com/documents/current/core/howto/defer.html}</span>
|
|
|
|
<span class="sd"> When creating a Deferred, you may provide a canceller function, which</span>
|
|
<span class="sd"> will be called by d.cancel() to let you do any clean-up necessary if the</span>
|
|
<span class="sd"> user decides not to wait for the deferred to complete.</span>
|
|
|
|
<span class="sd"> @ivar called: A flag which is C{False} until either C{callback} or</span>
|
|
<span class="sd"> C{errback} is called and afterwards always C{True}.</span>
|
|
<span class="sd"> @ivar paused: A counter of how many unmatched C{pause} calls have been made</span>
|
|
<span class="sd"> on this instance.</span>
|
|
<span class="sd"> @ivar _suppressAlreadyCalled: A flag used by the cancellation mechanism</span>
|
|
<span class="sd"> which is C{True} if the Deferred has no canceller and has been</span>
|
|
<span class="sd"> cancelled, C{False} otherwise. If C{True}, it can be expected that</span>
|
|
<span class="sd"> C{callback} or C{errback} will eventually be called and the result</span>
|
|
<span class="sd"> should be silently discarded.</span>
|
|
<span class="sd"> @ivar _runningCallbacks: A flag which is C{True} while this instance is</span>
|
|
<span class="sd"> executing its callback chain, used to stop recursive execution of</span>
|
|
<span class="sd"> L{_runCallbacks}</span>
|
|
<span class="sd"> @ivar _chainedTo: If this L{Deferred} is waiting for the result of another</span>
|
|
<span class="sd"> L{Deferred}, this is a reference to the other Deferred. Otherwise,</span>
|
|
<span class="sd"> L{None}.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">called</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="n">paused</span> <span class="o">=</span> <span class="mi">0</span>
|
|
<span class="n">_debugInfo</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">DebugInfo</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">_suppressAlreadyCalled</span> <span class="o">=</span> <span class="kc">False</span>
|
|
|
|
<span class="c1"># Are we currently running a user-installed callback? Meant to prevent</span>
|
|
<span class="c1"># recursive running of callbacks when a reentrant call to add a callback is</span>
|
|
<span class="c1"># used.</span>
|
|
<span class="n">_runningCallbacks</span> <span class="o">=</span> <span class="kc">False</span>
|
|
|
|
<span class="c1"># Keep this class attribute for now, for compatibility with code that</span>
|
|
<span class="c1"># sets it directly.</span>
|
|
<span class="n">debug</span> <span class="o">=</span> <span class="kc">False</span>
|
|
|
|
<span class="n">_chainedTo</span><span class="p">:</span> <span class="s2">"Optional[Deferred[Any]]"</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<div class="viewcode-block" id="Deferred.__init__">
|
|
<a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.commands.cmdhandler.Deferred.__init__">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span> <span class="n">canceller</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Callable</span><span class="p">[[</span><span class="s2">"Deferred[Any]"</span><span class="p">],</span> <span class="kc">None</span><span class="p">]]</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Initialize a L{Deferred}.</span>
|
|
|
|
<span class="sd"> @param canceller: a callable used to stop the pending operation</span>
|
|
<span class="sd"> scheduled by this L{Deferred} when L{Deferred.cancel} is invoked.</span>
|
|
<span class="sd"> The canceller will be passed the deferred whose cancellation is</span>
|
|
<span class="sd"> requested (i.e., C{self}).</span>
|
|
|
|
<span class="sd"> If a canceller is not given, or does not invoke its argument's</span>
|
|
<span class="sd"> C{callback} or C{errback} method, L{Deferred.cancel} will</span>
|
|
<span class="sd"> invoke L{Deferred.errback} with a L{CancelledError}.</span>
|
|
|
|
<span class="sd"> Note that if a canceller is not given, C{callback} or</span>
|
|
<span class="sd"> C{errback} may still be invoked exactly once, even though</span>
|
|
<span class="sd"> defer.py will have already invoked C{errback}, as described</span>
|
|
<span class="sd"> above. This allows clients of code which returns a L{Deferred}</span>
|
|
<span class="sd"> to cancel it without requiring the L{Deferred} instantiator to</span>
|
|
<span class="sd"> provide any specific implementation support for cancellation.</span>
|
|
<span class="sd"> New in 10.1.</span>
|
|
|
|
<span class="sd"> @type canceller: a 1-argument callable which takes a L{Deferred}. The</span>
|
|
<span class="sd"> return result is ignored.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">callbacks</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">_CallbackChain</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_canceller</span> <span class="o">=</span> <span class="n">canceller</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">debug</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_debugInfo</span> <span class="o">=</span> <span class="n">DebugInfo</span><span class="p">()</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_debugInfo</span><span class="o">.</span><span class="n">creator</span> <span class="o">=</span> <span class="n">traceback</span><span class="o">.</span><span class="n">format_stack</span><span class="p">()[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span></div>
|
|
|
|
|
|
<div class="viewcode-block" id="Deferred.addCallbacks">
|
|
<a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.commands.cmdhandler.Deferred.addCallbacks">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addCallbacks</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">callback</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span>
|
|
<span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">_NextResultT</span><span class="p">],</span>
|
|
<span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">]],</span>
|
|
<span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">Failure</span><span class="p">],</span>
|
|
<span class="n">Callable</span><span class="p">[</span>
|
|
<span class="o">...</span><span class="p">,</span>
|
|
<span class="n">Union</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">,</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">],</span> <span class="n">Failure</span><span class="p">],</span>
|
|
<span class="p">],</span>
|
|
<span class="p">],</span>
|
|
<span class="n">errback</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span>
|
|
<span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">_NextResultT</span><span class="p">],</span>
|
|
<span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">]],</span>
|
|
<span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">Failure</span><span class="p">],</span>
|
|
<span class="n">Callable</span><span class="p">[</span>
|
|
<span class="o">...</span><span class="p">,</span>
|
|
<span class="n">Union</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">,</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">],</span> <span class="n">Failure</span><span class="p">],</span>
|
|
<span class="p">],</span>
|
|
<span class="kc">None</span><span class="p">,</span>
|
|
<span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
|
<span class="n">callbackArgs</span><span class="p">:</span> <span class="n">Tuple</span><span class="p">[</span><span class="n">Any</span><span class="p">,</span> <span class="o">...</span><span class="p">]</span> <span class="o">=</span> <span class="p">(),</span>
|
|
<span class="n">callbackKeywords</span><span class="p">:</span> <span class="n">Mapping</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Any</span><span class="p">]</span> <span class="o">=</span> <span class="n">_NONE_KWARGS</span><span class="p">,</span>
|
|
<span class="n">errbackArgs</span><span class="p">:</span> <span class="n">_CallbackOrderedArguments</span> <span class="o">=</span> <span class="p">(),</span>
|
|
<span class="n">errbackKeywords</span><span class="p">:</span> <span class="n">_CallbackKeywordArguments</span> <span class="o">=</span> <span class="n">_NONE_KWARGS</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="s2">"Deferred[_NextResultT]"</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Add a pair of callbacks (success and error) to this L{Deferred}.</span>
|
|
|
|
<span class="sd"> These will be executed when the 'master' callback is run.</span>
|
|
|
|
<span class="sd"> @note: The signature of this function was designed many years before</span>
|
|
<span class="sd"> PEP 612; ParamSpec provides no mechanism to annotate parameters</span>
|
|
<span class="sd"> like C{callbackArgs}; this is therefore inherently less type-safe</span>
|
|
<span class="sd"> than calling C{addCallback} and C{addErrback} separately.</span>
|
|
|
|
<span class="sd"> @return: C{self}.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="n">errback</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">errback</span> <span class="o">=</span> <span class="n">_failthru</span>
|
|
|
|
<span class="c1"># Default value used to be None and callers may be using None</span>
|
|
<span class="k">if</span> <span class="n">callbackArgs</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">callbackArgs</span> <span class="o">=</span> <span class="p">()</span> <span class="c1"># type: ignore[unreachable]</span>
|
|
<span class="k">if</span> <span class="n">callbackKeywords</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">callbackKeywords</span> <span class="o">=</span> <span class="p">{}</span> <span class="c1"># type: ignore[unreachable]</span>
|
|
<span class="k">if</span> <span class="n">errbackArgs</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">errbackArgs</span> <span class="o">=</span> <span class="p">()</span> <span class="c1"># type: ignore[unreachable]</span>
|
|
<span class="k">if</span> <span class="n">errbackKeywords</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">errbackKeywords</span> <span class="o">=</span> <span class="p">{}</span> <span class="c1"># type: ignore[unreachable]</span>
|
|
|
|
<span class="c1"># Note that this logic is duplicated in addCallbac/addErrback/addBoth</span>
|
|
<span class="c1"># for performance reasons.</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">callbacks</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="p">(</span>
|
|
<span class="p">(</span><span class="n">callback</span><span class="p">,</span> <span class="n">callbackArgs</span><span class="p">,</span> <span class="n">callbackKeywords</span><span class="p">),</span>
|
|
<span class="p">(</span><span class="n">errback</span><span class="p">,</span> <span class="n">errbackArgs</span><span class="p">,</span> <span class="n">errbackKeywords</span><span class="p">),</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">called</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_runCallbacks</span><span class="p">()</span>
|
|
|
|
<span class="c1"># type note: The Deferred's type has changed here, but *idiomatically*</span>
|
|
<span class="c1"># the caller should treat the result as the new type, consistently.</span>
|
|
<span class="k">return</span> <span class="bp">self</span> <span class="c1"># type:ignore[return-value]</span></div>
|
|
|
|
|
|
<span class="c1"># BEGIN way too many @overload-s for addCallback, addErrback, and addBoth:</span>
|
|
<span class="c1"># these must be accomplished with @overloads, rather than a big Union on</span>
|
|
<span class="c1"># the result type as you might expect, because the fact that</span>
|
|
<span class="c1"># _NextResultT has no bound makes mypy get confused and require the</span>
|
|
<span class="c1"># return types of functions to be combinations of Deferred and Failure</span>
|
|
<span class="c1"># rather than the actual return type. I'm not entirely sure what about the</span>
|
|
<span class="c1"># semantics of <nothing> create this overzealousness on the part of trying</span>
|
|
<span class="c1"># to assign a type; there *might* be a mypy bug in there somewhere.</span>
|
|
<span class="c1"># Possibly https://github.com/python/typing/issues/548 is implicated here</span>
|
|
<span class="c1"># because TypeVar for the *callable* with a variadic bound might express to</span>
|
|
<span class="c1"># Mypy the actual constraint that we want on its type.</span>
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addCallback</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">callback</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">Concatenate</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">,</span> <span class="n">_P</span><span class="p">],</span> <span class="n">Failure</span><span class="p">],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">]:</span>
|
|
<span class="o">...</span>
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addCallback</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">callback</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span>
|
|
<span class="n">Concatenate</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">,</span> <span class="n">_P</span><span class="p">],</span>
|
|
<span class="n">Union</span><span class="p">[</span><span class="n">Failure</span><span class="p">,</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">]],</span>
|
|
<span class="p">],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">]:</span>
|
|
<span class="o">...</span>
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addCallback</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">callback</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">Concatenate</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">,</span> <span class="n">_P</span><span class="p">],</span> <span class="n">Union</span><span class="p">[</span><span class="n">Failure</span><span class="p">,</span> <span class="n">_NextResultT</span><span class="p">]],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">]:</span>
|
|
<span class="o">...</span>
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addCallback</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">callback</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">Concatenate</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">,</span> <span class="n">_P</span><span class="p">],</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">]],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">]:</span>
|
|
<span class="o">...</span>
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addCallback</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">callback</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span>
|
|
<span class="n">Concatenate</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">,</span> <span class="n">_P</span><span class="p">],</span>
|
|
<span class="n">Union</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">],</span> <span class="n">_NextResultT</span><span class="p">],</span>
|
|
<span class="p">],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">]:</span>
|
|
<span class="o">...</span>
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addCallback</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">callback</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">Concatenate</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">,</span> <span class="n">_P</span><span class="p">],</span> <span class="n">_NextResultT</span><span class="p">],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">]:</span>
|
|
<span class="o">...</span>
|
|
|
|
<div class="viewcode-block" id="Deferred.addCallback">
|
|
<a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.commands.cmdhandler.Deferred.addCallback">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addCallback</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">callback</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-></span> <span class="s2">"Deferred[Any]"</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Convenience method for adding just a callback.</span>
|
|
|
|
<span class="sd"> See L{addCallbacks}.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="c1"># This could be implemented as a call to addCallbacks, but doing it</span>
|
|
<span class="c1"># directly is faster.</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">callbacks</span><span class="o">.</span><span class="n">append</span><span class="p">(((</span><span class="n">callback</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">),</span> <span class="p">(</span><span class="n">_failthru</span><span class="p">,</span> <span class="p">(),</span> <span class="p">{})))</span>
|
|
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">called</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_runCallbacks</span><span class="p">()</span>
|
|
|
|
<span class="k">return</span> <span class="bp">self</span></div>
|
|
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addErrback</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">errback</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">Concatenate</span><span class="p">[</span><span class="n">Failure</span><span class="p">,</span> <span class="n">_P</span><span class="p">],</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">]],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="s2">"Deferred[Union[_SelfResultT, _NextResultT]]"</span><span class="p">:</span>
|
|
<span class="o">...</span>
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addErrback</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">errback</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">Concatenate</span><span class="p">[</span><span class="n">Failure</span><span class="p">,</span> <span class="n">_P</span><span class="p">],</span> <span class="n">Failure</span><span class="p">],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="s2">"Deferred[Union[_SelfResultT]]"</span><span class="p">:</span>
|
|
<span class="o">...</span>
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addErrback</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">errback</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">Concatenate</span><span class="p">[</span><span class="n">Failure</span><span class="p">,</span> <span class="n">_P</span><span class="p">],</span> <span class="n">_NextResultT</span><span class="p">],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="s2">"Deferred[Union[_SelfResultT, _NextResultT]]"</span><span class="p">:</span>
|
|
<span class="o">...</span>
|
|
|
|
<div class="viewcode-block" id="Deferred.addErrback">
|
|
<a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.commands.cmdhandler.Deferred.addErrback">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addErrback</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">errback</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-></span> <span class="s2">"Deferred[Any]"</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Convenience method for adding just an errback.</span>
|
|
|
|
<span class="sd"> See L{addCallbacks}.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="c1"># This could be implemented as a call to addCallbacks, but doing it</span>
|
|
<span class="c1"># directly is faster.</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">callbacks</span><span class="o">.</span><span class="n">append</span><span class="p">(((</span><span class="n">passthru</span><span class="p">,</span> <span class="p">(),</span> <span class="p">{}),</span> <span class="p">(</span><span class="n">errback</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">)))</span>
|
|
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">called</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_runCallbacks</span><span class="p">()</span>
|
|
|
|
<span class="k">return</span> <span class="bp">self</span></div>
|
|
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addBoth</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">callback</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">Concatenate</span><span class="p">[</span><span class="n">Union</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">,</span> <span class="n">Failure</span><span class="p">],</span> <span class="n">_P</span><span class="p">],</span> <span class="n">Failure</span><span class="p">],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">]:</span>
|
|
<span class="o">...</span>
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addBoth</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">callback</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span>
|
|
<span class="n">Concatenate</span><span class="p">[</span><span class="n">Union</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">,</span> <span class="n">Failure</span><span class="p">],</span> <span class="n">_P</span><span class="p">],</span>
|
|
<span class="n">Union</span><span class="p">[</span><span class="n">Failure</span><span class="p">,</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">]],</span>
|
|
<span class="p">],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">]:</span>
|
|
<span class="o">...</span>
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addBoth</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">callback</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span>
|
|
<span class="n">Concatenate</span><span class="p">[</span><span class="n">Union</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">,</span> <span class="n">Failure</span><span class="p">],</span> <span class="n">_P</span><span class="p">],</span> <span class="n">Union</span><span class="p">[</span><span class="n">Failure</span><span class="p">,</span> <span class="n">_NextResultT</span><span class="p">]</span>
|
|
<span class="p">],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">]:</span>
|
|
<span class="o">...</span>
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addBoth</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">callback</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span>
|
|
<span class="n">Concatenate</span><span class="p">[</span><span class="n">Union</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">,</span> <span class="n">Failure</span><span class="p">],</span> <span class="n">_P</span><span class="p">],</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">]</span>
|
|
<span class="p">],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">]:</span>
|
|
<span class="o">...</span>
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addBoth</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">callback</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span>
|
|
<span class="n">Concatenate</span><span class="p">[</span><span class="n">Union</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">,</span> <span class="n">Failure</span><span class="p">],</span> <span class="n">_P</span><span class="p">],</span>
|
|
<span class="n">Union</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">],</span> <span class="n">_NextResultT</span><span class="p">],</span>
|
|
<span class="p">],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">]:</span>
|
|
<span class="o">...</span>
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addBoth</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">callback</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">Concatenate</span><span class="p">[</span><span class="n">Union</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">,</span> <span class="n">Failure</span><span class="p">],</span> <span class="n">_P</span><span class="p">],</span> <span class="n">_NextResultT</span><span class="p">],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">]:</span>
|
|
<span class="o">...</span>
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addBoth</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">callback</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">Concatenate</span><span class="p">[</span><span class="n">_T</span><span class="p">,</span> <span class="n">_P</span><span class="p">],</span> <span class="n">_T</span><span class="p">],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">]:</span>
|
|
<span class="o">...</span>
|
|
|
|
<div class="viewcode-block" id="Deferred.addBoth">
|
|
<a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.commands.cmdhandler.Deferred.addBoth">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addBoth</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">callback</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-></span> <span class="s2">"Deferred[Any]"</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Convenience method for adding a single callable as both a callback</span>
|
|
<span class="sd"> and an errback.</span>
|
|
|
|
<span class="sd"> See L{addCallbacks}.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="c1"># This could be implemented as a call to addCallbacks, but doing it</span>
|
|
<span class="c1"># directly is faster.</span>
|
|
<span class="n">call</span> <span class="o">=</span> <span class="p">(</span><span class="n">callback</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">callbacks</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">call</span><span class="p">,</span> <span class="n">call</span><span class="p">))</span>
|
|
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">called</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_runCallbacks</span><span class="p">()</span>
|
|
|
|
<span class="k">return</span> <span class="bp">self</span></div>
|
|
|
|
|
|
<span class="c1"># END way too many overloads</span>
|
|
|
|
<div class="viewcode-block" id="Deferred.addTimeout">
|
|
<a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.commands.cmdhandler.Deferred.addTimeout">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">addTimeout</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">timeout</span><span class="p">:</span> <span class="nb">float</span><span class="p">,</span>
|
|
<span class="n">clock</span><span class="p">:</span> <span class="n">IReactorTime</span><span class="p">,</span>
|
|
<span class="n">onTimeoutCancel</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span>
|
|
<span class="n">Callable</span><span class="p">[</span>
|
|
<span class="p">[</span><span class="n">Union</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">,</span> <span class="n">Failure</span><span class="p">],</span> <span class="nb">float</span><span class="p">],</span>
|
|
<span class="n">Union</span><span class="p">[</span><span class="n">_NextResultT</span><span class="p">,</span> <span class="n">Failure</span><span class="p">],</span>
|
|
<span class="p">]</span>
|
|
<span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="s2">"Deferred[Union[_SelfResultT, _NextResultT]]"</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Time out this L{Deferred} by scheduling it to be cancelled after</span>
|
|
<span class="sd"> C{timeout} seconds.</span>
|
|
|
|
<span class="sd"> The timeout encompasses all the callbacks and errbacks added to this</span>
|
|
<span class="sd"> L{defer.Deferred} before the call to L{addTimeout}, and none added</span>
|
|
<span class="sd"> after the call.</span>
|
|
|
|
<span class="sd"> If this L{Deferred} gets timed out, it errbacks with a L{TimeoutError},</span>
|
|
<span class="sd"> unless a cancelable function was passed to its initialization or unless</span>
|
|
<span class="sd"> a different C{onTimeoutCancel} callable is provided.</span>
|
|
|
|
<span class="sd"> @param timeout: number of seconds to wait before timing out this</span>
|
|
<span class="sd"> L{Deferred}</span>
|
|
<span class="sd"> @param clock: The object which will be used to schedule the timeout.</span>
|
|
<span class="sd"> @param onTimeoutCancel: A callable which is called immediately after</span>
|
|
<span class="sd"> this L{Deferred} times out, and not if this L{Deferred} is</span>
|
|
<span class="sd"> otherwise cancelled before the timeout. It takes an arbitrary</span>
|
|
<span class="sd"> value, which is the value of this L{Deferred} at that exact point</span>
|
|
<span class="sd"> in time (probably a L{CancelledError} L{Failure}), and the</span>
|
|
<span class="sd"> C{timeout}. The default callable (if C{None} is provided) will</span>
|
|
<span class="sd"> translate a L{CancelledError} L{Failure} into a L{TimeoutError}.</span>
|
|
|
|
<span class="sd"> @return: C{self}.</span>
|
|
|
|
<span class="sd"> @since: 16.5</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">timedOut</span> <span class="o">=</span> <span class="p">[</span><span class="kc">False</span><span class="p">]</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">timeItOut</span><span class="p">()</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">timedOut</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">cancel</span><span class="p">()</span>
|
|
|
|
<span class="n">delayedCall</span> <span class="o">=</span> <span class="n">clock</span><span class="o">.</span><span class="n">callLater</span><span class="p">(</span><span class="n">timeout</span><span class="p">,</span> <span class="n">timeItOut</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">convertCancelled</span><span class="p">(</span>
|
|
<span class="n">result</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">,</span> <span class="n">Failure</span><span class="p">],</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Union</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">,</span> <span class="n">_NextResultT</span><span class="p">,</span> <span class="n">Failure</span><span class="p">]:</span>
|
|
<span class="c1"># if C{deferred} was timed out, call the translation function,</span>
|
|
<span class="c1"># if provided, otherwise just use L{cancelledToTimedOutError}</span>
|
|
<span class="k">if</span> <span class="n">timedOut</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
|
|
<span class="n">toCall</span> <span class="o">=</span> <span class="n">onTimeoutCancel</span> <span class="ow">or</span> <span class="n">_cancelledToTimedOutError</span>
|
|
<span class="k">return</span> <span class="n">toCall</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">timeout</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">result</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">cancelTimeout</span><span class="p">(</span><span class="n">result</span><span class="p">:</span> <span class="n">_T</span><span class="p">)</span> <span class="o">-></span> <span class="n">_T</span><span class="p">:</span>
|
|
<span class="c1"># stop the pending call to cancel the deferred if it's been fired</span>
|
|
<span class="k">if</span> <span class="n">delayedCall</span><span class="o">.</span><span class="n">active</span><span class="p">():</span>
|
|
<span class="n">delayedCall</span><span class="o">.</span><span class="n">cancel</span><span class="p">()</span>
|
|
<span class="k">return</span> <span class="n">result</span>
|
|
|
|
<span class="c1"># Note: Mypy cannot infer this type, apparently thanks to the ambiguity</span>
|
|
<span class="c1"># of _SelfResultT / _NextResultT both being unbound. Explicitly</span>
|
|
<span class="c1"># annotating it seems to do the trick though.</span>
|
|
<span class="n">converted</span><span class="p">:</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">Union</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">,</span> <span class="n">_NextResultT</span><span class="p">]]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">addBoth</span><span class="p">(</span>
|
|
<span class="n">convertCancelled</span>
|
|
<span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">converted</span><span class="o">.</span><span class="n">addBoth</span><span class="p">(</span><span class="n">cancelTimeout</span><span class="p">)</span></div>
|
|
|
|
|
|
<div class="viewcode-block" id="Deferred.chainDeferred">
|
|
<a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.commands.cmdhandler.Deferred.chainDeferred">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">chainDeferred</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">d</span><span class="p">:</span> <span class="s2">"Deferred[_SelfResultT]"</span><span class="p">)</span> <span class="o">-></span> <span class="s2">"Deferred[None]"</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Chain another L{Deferred} to this L{Deferred}.</span>
|
|
|
|
<span class="sd"> This method adds callbacks to this L{Deferred} to call C{d}'s callback</span>
|
|
<span class="sd"> or errback, as appropriate. It is merely a shorthand way of performing</span>
|
|
<span class="sd"> the following::</span>
|
|
|
|
<span class="sd"> d1.addCallbacks(d2.callback, d2.errback)</span>
|
|
|
|
<span class="sd"> When you chain a deferred C{d2} to another deferred C{d1} with</span>
|
|
<span class="sd"> C{d1.chainDeferred(d2)}, you are making C{d2} participate in the</span>
|
|
<span class="sd"> callback chain of C{d1}.</span>
|
|
<span class="sd"> Thus any event that fires C{d1} will also fire C{d2}.</span>
|
|
<span class="sd"> However, the converse is B{not} true; if C{d2} is fired, C{d1} will not</span>
|
|
<span class="sd"> be affected.</span>
|
|
|
|
<span class="sd"> Note that unlike the case where chaining is caused by a L{Deferred}</span>
|
|
<span class="sd"> being returned from a callback, it is possible to cause the call</span>
|
|
<span class="sd"> stack size limit to be exceeded by chaining many L{Deferred}s</span>
|
|
<span class="sd"> together with C{chainDeferred}.</span>
|
|
|
|
<span class="sd"> @return: C{self}.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">d</span><span class="o">.</span><span class="n">_chainedTo</span> <span class="o">=</span> <span class="bp">self</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">addCallbacks</span><span class="p">(</span><span class="n">d</span><span class="o">.</span><span class="n">callback</span><span class="p">,</span> <span class="n">d</span><span class="o">.</span><span class="n">errback</span><span class="p">)</span></div>
|
|
|
|
|
|
<div class="viewcode-block" id="Deferred.callback">
|
|
<a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.commands.cmdhandler.Deferred.callback">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">callback</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">result</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">,</span> <span class="n">Failure</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Run all success callbacks that have been added to this L{Deferred}.</span>
|
|
|
|
<span class="sd"> Each callback will have its result passed as the first argument to</span>
|
|
<span class="sd"> the next; this way, the callbacks act as a 'processing chain'. If</span>
|
|
<span class="sd"> the success-callback returns a L{Failure} or raises an L{Exception},</span>
|
|
<span class="sd"> processing will continue on the *error* callback chain. If a</span>
|
|
<span class="sd"> callback (or errback) returns another L{Deferred}, this L{Deferred}</span>
|
|
<span class="sd"> will be chained to it (and further callbacks will not run until that</span>
|
|
<span class="sd"> L{Deferred} has a result).</span>
|
|
|
|
<span class="sd"> An instance of L{Deferred} may only have either L{callback} or</span>
|
|
<span class="sd"> L{errback} called on it, and only once.</span>
|
|
|
|
<span class="sd"> @param result: The object which will be passed to the first callback</span>
|
|
<span class="sd"> added to this L{Deferred} (via L{addCallback}), unless C{result} is</span>
|
|
<span class="sd"> a L{Failure}, in which case the behavior is the same as calling</span>
|
|
<span class="sd"> C{errback(result)}.</span>
|
|
|
|
<span class="sd"> @raise AlreadyCalledError: If L{callback} or L{errback} has already been</span>
|
|
<span class="sd"> called on this L{Deferred}.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_startRunCallbacks</span><span class="p">(</span><span class="n">result</span><span class="p">)</span></div>
|
|
|
|
|
|
<div class="viewcode-block" id="Deferred.errback">
|
|
<a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.commands.cmdhandler.Deferred.errback">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">errback</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">fail</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Union</span><span class="p">[</span><span class="n">Failure</span><span class="p">,</span> <span class="ne">BaseException</span><span class="p">]]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Run all error callbacks that have been added to this L{Deferred}.</span>
|
|
|
|
<span class="sd"> Each callback will have its result passed as the first</span>
|
|
<span class="sd"> argument to the next; this way, the callbacks act as a</span>
|
|
<span class="sd"> 'processing chain'. Also, if the error-callback returns a non-Failure</span>
|
|
<span class="sd"> or doesn't raise an L{Exception}, processing will continue on the</span>
|
|
<span class="sd"> *success*-callback chain.</span>
|
|
|
|
<span class="sd"> If the argument that's passed to me is not a L{Failure} instance,</span>
|
|
<span class="sd"> it will be embedded in one. If no argument is passed, a</span>
|
|
<span class="sd"> L{Failure} instance will be created based on the current</span>
|
|
<span class="sd"> traceback stack.</span>
|
|
|
|
<span class="sd"> Passing a string as `fail' is deprecated, and will be punished with</span>
|
|
<span class="sd"> a warning message.</span>
|
|
|
|
<span class="sd"> An instance of L{Deferred} may only have either L{callback} or</span>
|
|
<span class="sd"> L{errback} called on it, and only once.</span>
|
|
|
|
<span class="sd"> @param fail: The L{Failure} object which will be passed to the first</span>
|
|
<span class="sd"> errback added to this L{Deferred} (via L{addErrback}).</span>
|
|
<span class="sd"> Alternatively, a L{Exception} instance from which a L{Failure} will</span>
|
|
<span class="sd"> be constructed (with no traceback) or L{None} to create a L{Failure}</span>
|
|
<span class="sd"> instance from the current exception state (with a traceback).</span>
|
|
|
|
<span class="sd"> @raise AlreadyCalledError: If L{callback} or L{errback} has already been</span>
|
|
<span class="sd"> called on this L{Deferred}.</span>
|
|
<span class="sd"> @raise NoCurrentExceptionError: If C{fail} is L{None} but there is</span>
|
|
<span class="sd"> no current exception state.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="n">fail</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">fail</span> <span class="o">=</span> <span class="n">Failure</span><span class="p">(</span><span class="n">captureVars</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">debug</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">fail</span><span class="p">,</span> <span class="n">Failure</span><span class="p">):</span>
|
|
<span class="n">fail</span> <span class="o">=</span> <span class="n">Failure</span><span class="p">(</span><span class="n">fail</span><span class="p">)</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_startRunCallbacks</span><span class="p">(</span><span class="n">fail</span><span class="p">)</span></div>
|
|
|
|
|
|
<div class="viewcode-block" id="Deferred.pause">
|
|
<a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.commands.cmdhandler.Deferred.pause">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">pause</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Stop processing on a L{Deferred} until L{unpause}() is called.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">paused</span> <span class="o">+=</span> <span class="mi">1</span></div>
|
|
|
|
|
|
<div class="viewcode-block" id="Deferred.unpause">
|
|
<a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.commands.cmdhandler.Deferred.unpause">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">unpause</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Process all callbacks made since L{pause}() was called.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">paused</span> <span class="o">-=</span> <span class="mi">1</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">paused</span><span class="p">:</span>
|
|
<span class="k">return</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">called</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_runCallbacks</span><span class="p">()</span></div>
|
|
|
|
|
|
<div class="viewcode-block" id="Deferred.cancel">
|
|
<a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.commands.cmdhandler.Deferred.cancel">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">cancel</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Cancel this L{Deferred}.</span>
|
|
|
|
<span class="sd"> If the L{Deferred} has not yet had its C{errback} or C{callback} method</span>
|
|
<span class="sd"> invoked, call the canceller function provided to the constructor. If</span>
|
|
<span class="sd"> that function does not invoke C{callback} or C{errback}, or if no</span>
|
|
<span class="sd"> canceller function was provided, errback with L{CancelledError}.</span>
|
|
|
|
<span class="sd"> If this L{Deferred} is waiting on another L{Deferred}, forward the</span>
|
|
<span class="sd"> cancellation to the other L{Deferred}.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">called</span><span class="p">:</span>
|
|
<span class="n">canceller</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_canceller</span>
|
|
<span class="k">if</span> <span class="n">canceller</span><span class="p">:</span>
|
|
<span class="n">canceller</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># Arrange to eat the callback that will eventually be fired</span>
|
|
<span class="c1"># since there was no real canceller.</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_suppressAlreadyCalled</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">called</span><span class="p">:</span>
|
|
<span class="c1"># There was no canceller, or the canceller didn't call</span>
|
|
<span class="c1"># callback or errback.</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">errback</span><span class="p">(</span><span class="n">Failure</span><span class="p">(</span><span class="n">CancelledError</span><span class="p">()))</span>
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">result</span><span class="p">,</span> <span class="n">Deferred</span><span class="p">):</span>
|
|
<span class="c1"># Waiting for another deferred -- cancel it instead.</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">result</span><span class="o">.</span><span class="n">cancel</span><span class="p">()</span></div>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_startRunCallbacks</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">result</span><span class="p">:</span> <span class="nb">object</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">called</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_suppressAlreadyCalled</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_suppressAlreadyCalled</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="k">return</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">debug</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_debugInfo</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_debugInfo</span> <span class="o">=</span> <span class="n">DebugInfo</span><span class="p">()</span>
|
|
<span class="n">extra</span> <span class="o">=</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">_debugInfo</span><span class="o">.</span><span class="n">_getDebugTracebacks</span><span class="p">()</span>
|
|
<span class="k">raise</span> <span class="n">AlreadyCalledError</span><span class="p">(</span><span class="n">extra</span><span class="p">)</span>
|
|
<span class="k">raise</span> <span class="n">AlreadyCalledError</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">debug</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_debugInfo</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_debugInfo</span> <span class="o">=</span> <span class="n">DebugInfo</span><span class="p">()</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_debugInfo</span><span class="o">.</span><span class="n">invoker</span> <span class="o">=</span> <span class="n">traceback</span><span class="o">.</span><span class="n">format_stack</span><span class="p">()[:</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">called</span> <span class="o">=</span> <span class="kc">True</span>
|
|
|
|
<span class="c1"># Clear the canceller to avoid any circular references. This is safe to</span>
|
|
<span class="c1"># do as the canceller does not get called after the deferred has fired</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_canceller</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">result</span> <span class="o">=</span> <span class="n">result</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_runCallbacks</span><span class="p">()</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_continuation</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="n">_CallbackChain</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Build a tuple of callback and errback with L{_Sentinel._CONTINUE}.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">triple</span> <span class="o">=</span> <span class="p">(</span><span class="n">_CONTINUE</span><span class="p">,</span> <span class="p">(</span><span class="bp">self</span><span class="p">,),</span> <span class="n">_NONE_KWARGS</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="p">(</span><span class="n">triple</span><span class="p">,</span> <span class="n">triple</span><span class="p">)</span> <span class="c1"># type: ignore[return-value]</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_runCallbacks</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Run the chain of callbacks once a result is available.</span>
|
|
|
|
<span class="sd"> This consists of a simple loop over all of the callbacks, calling each</span>
|
|
<span class="sd"> with the current result and making the current result equal to the</span>
|
|
<span class="sd"> return value (or raised exception) of that call.</span>
|
|
|
|
<span class="sd"> If L{_runningCallbacks} is true, this loop won't run at all, since</span>
|
|
<span class="sd"> it is already running above us on the call stack. If C{self.paused} is</span>
|
|
<span class="sd"> true, the loop also won't run, because that's what it means to be</span>
|
|
<span class="sd"> paused.</span>
|
|
|
|
<span class="sd"> The loop will terminate before processing all of the callbacks if a</span>
|
|
<span class="sd"> L{Deferred} without a result is encountered.</span>
|
|
|
|
<span class="sd"> If a L{Deferred} I{with} a result is encountered, that result is taken</span>
|
|
<span class="sd"> and the loop proceeds.</span>
|
|
|
|
<span class="sd"> @note: The implementation is complicated slightly by the fact that</span>
|
|
<span class="sd"> chaining (associating two L{Deferred}s with each other such that one</span>
|
|
<span class="sd"> will wait for the result of the other, as happens when a Deferred is</span>
|
|
<span class="sd"> returned from a callback on another L{Deferred}) is supported</span>
|
|
<span class="sd"> iteratively rather than recursively, to avoid running out of stack</span>
|
|
<span class="sd"> frames when processing long chains.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_runningCallbacks</span><span class="p">:</span>
|
|
<span class="c1"># Don't recursively run callbacks</span>
|
|
<span class="k">return</span>
|
|
|
|
<span class="c1"># Keep track of all the Deferreds encountered while propagating results</span>
|
|
<span class="c1"># up a chain. The way a Deferred gets onto this stack is by having</span>
|
|
<span class="c1"># added its _continuation() to the callbacks list of a second Deferred</span>
|
|
<span class="c1"># and then that second Deferred being fired. ie, if ever had _chainedTo</span>
|
|
<span class="c1"># set to something other than None, you might end up on this stack.</span>
|
|
<span class="n">chain</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">Any</span><span class="p">]]</span> <span class="o">=</span> <span class="p">[</span><span class="bp">self</span><span class="p">]</span>
|
|
|
|
<span class="k">while</span> <span class="n">chain</span><span class="p">:</span>
|
|
<span class="n">current</span> <span class="o">=</span> <span class="n">chain</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
|
|
|
|
<span class="k">if</span> <span class="n">current</span><span class="o">.</span><span class="n">paused</span><span class="p">:</span>
|
|
<span class="c1"># This Deferred isn't going to produce a result at all. All the</span>
|
|
<span class="c1"># Deferreds up the chain waiting on it will just have to...</span>
|
|
<span class="c1"># wait.</span>
|
|
<span class="k">return</span>
|
|
|
|
<span class="n">finished</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">current</span><span class="o">.</span><span class="n">_chainedTo</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="k">while</span> <span class="n">current</span><span class="o">.</span><span class="n">callbacks</span><span class="p">:</span>
|
|
<span class="n">item</span> <span class="o">=</span> <span class="n">current</span><span class="o">.</span><span class="n">callbacks</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">current</span><span class="o">.</span><span class="n">result</span><span class="p">,</span> <span class="n">Failure</span><span class="p">):</span>
|
|
<span class="n">callback</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span> <span class="o">=</span> <span class="n">item</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># type note: Callback signature also works for Errbacks in</span>
|
|
<span class="c1"># this context.</span>
|
|
<span class="n">callback</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span> <span class="o">=</span> <span class="n">item</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
|
|
|
<span class="c1"># Avoid recursion if we can.</span>
|
|
<span class="k">if</span> <span class="n">callback</span> <span class="ow">is</span> <span class="n">_CONTINUE</span><span class="p">:</span>
|
|
<span class="c1"># Give the waiting Deferred our current result and then</span>
|
|
<span class="c1"># forget about that result ourselves.</span>
|
|
|
|
<span class="c1"># We don't use cast() for performance reasons:</span>
|
|
<span class="n">chainee</span><span class="p">:</span> <span class="n">Deferred</span><span class="p">[</span><span class="nb">object</span><span class="p">]</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="c1"># type: ignore[assignment]</span>
|
|
<span class="n">chainee</span><span class="o">.</span><span class="n">result</span> <span class="o">=</span> <span class="n">current</span><span class="o">.</span><span class="n">result</span>
|
|
<span class="n">current</span><span class="o">.</span><span class="n">result</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="c1"># Making sure to update _debugInfo</span>
|
|
<span class="k">if</span> <span class="n">current</span><span class="o">.</span><span class="n">_debugInfo</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">current</span><span class="o">.</span><span class="n">_debugInfo</span><span class="o">.</span><span class="n">failResult</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">chainee</span><span class="o">.</span><span class="n">paused</span> <span class="o">-=</span> <span class="mi">1</span>
|
|
<span class="n">chain</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">chainee</span><span class="p">)</span>
|
|
<span class="c1"># Delay cleaning this Deferred and popping it from the chain</span>
|
|
<span class="c1"># until after we've dealt with chainee.</span>
|
|
<span class="n">finished</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="k">break</span>
|
|
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">current</span><span class="o">.</span><span class="n">_runningCallbacks</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="c1"># type note: mypy sees `callback is _CONTINUE` above and</span>
|
|
<span class="c1"># then decides that `callback` is not callable.</span>
|
|
<span class="c1"># This goes away when we use `_Sentinel._CONTINUE`</span>
|
|
<span class="c1"># instead, but we don't want to do that attribute</span>
|
|
<span class="c1"># lookup in this hot code path, so we ignore the mypy</span>
|
|
<span class="c1"># complaint here.</span>
|
|
<span class="n">current</span><span class="o">.</span><span class="n">result</span> <span class="o">=</span> <span class="n">callback</span><span class="p">(</span> <span class="c1"># type: ignore[misc]</span>
|
|
<span class="n">current</span><span class="o">.</span><span class="n">result</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">current</span><span class="o">.</span><span class="n">result</span> <span class="ow">is</span> <span class="n">current</span><span class="p">:</span>
|
|
<span class="n">warnAboutFunction</span><span class="p">(</span>
|
|
<span class="n">callback</span><span class="p">,</span>
|
|
<span class="s2">"Callback returned the Deferred "</span>
|
|
<span class="s2">"it was attached to; this breaks the "</span>
|
|
<span class="s2">"callback chain and will raise an "</span>
|
|
<span class="s2">"exception in the future."</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="k">finally</span><span class="p">:</span>
|
|
<span class="n">current</span><span class="o">.</span><span class="n">_runningCallbacks</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="k">except</span> <span class="ne">BaseException</span><span class="p">:</span>
|
|
<span class="c1"># Including full frame information in the Failure is quite</span>
|
|
<span class="c1"># expensive, so we avoid it unless self.debug is set.</span>
|
|
<span class="n">current</span><span class="o">.</span><span class="n">result</span> <span class="o">=</span> <span class="n">Failure</span><span class="p">(</span><span class="n">captureVars</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">debug</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># isinstance() with Awaitable subclass is expensive:</span>
|
|
<span class="k">if</span> <span class="nb">type</span><span class="p">(</span><span class="n">current</span><span class="o">.</span><span class="n">result</span><span class="p">)</span> <span class="ow">in</span> <span class="n">_DEFERRED_SUBCLASSES</span><span class="p">:</span>
|
|
<span class="c1"># Can't use cast() cause it's in the performance hot path:</span>
|
|
<span class="n">currentResult</span><span class="p">:</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">]</span> <span class="o">=</span> <span class="n">current</span><span class="o">.</span><span class="n">result</span> <span class="c1"># type: ignore[assignment]</span>
|
|
<span class="c1"># The result is another Deferred. If it has a result,</span>
|
|
<span class="c1"># we can take it and keep going.</span>
|
|
<span class="n">resultResult</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">currentResult</span><span class="p">,</span> <span class="s2">"result"</span><span class="p">,</span> <span class="n">_NO_RESULT</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="p">(</span>
|
|
<span class="n">resultResult</span> <span class="ow">is</span> <span class="n">_NO_RESULT</span>
|
|
<span class="ow">or</span> <span class="nb">type</span><span class="p">(</span><span class="n">resultResult</span><span class="p">)</span> <span class="ow">in</span> <span class="n">_DEFERRED_SUBCLASSES</span>
|
|
<span class="ow">or</span> <span class="n">currentResult</span><span class="o">.</span><span class="n">paused</span>
|
|
<span class="p">):</span>
|
|
<span class="c1"># Nope, it didn't. Pause and chain.</span>
|
|
<span class="n">current</span><span class="o">.</span><span class="n">pause</span><span class="p">()</span>
|
|
<span class="n">current</span><span class="o">.</span><span class="n">_chainedTo</span> <span class="o">=</span> <span class="n">currentResult</span>
|
|
<span class="c1"># Note: current.result has no result, so it's not</span>
|
|
<span class="c1"># running its callbacks right now. Therefore we can</span>
|
|
<span class="c1"># append to the callbacks list directly instead of</span>
|
|
<span class="c1"># using addCallbacks.</span>
|
|
<span class="n">currentResult</span><span class="o">.</span><span class="n">callbacks</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">current</span><span class="o">.</span><span class="n">_continuation</span><span class="p">())</span>
|
|
<span class="k">break</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># Yep, it did. Steal it.</span>
|
|
<span class="n">currentResult</span><span class="o">.</span><span class="n">result</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="c1"># Make sure _debugInfo's failure state is updated.</span>
|
|
<span class="k">if</span> <span class="n">currentResult</span><span class="o">.</span><span class="n">_debugInfo</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">currentResult</span><span class="o">.</span><span class="n">_debugInfo</span><span class="o">.</span><span class="n">failResult</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">current</span><span class="o">.</span><span class="n">result</span> <span class="o">=</span> <span class="n">resultResult</span>
|
|
|
|
<span class="k">if</span> <span class="n">finished</span><span class="p">:</span>
|
|
<span class="c1"># As much of the callback chain - perhaps all of it - as can be</span>
|
|
<span class="c1"># processed right now has been. The current Deferred is waiting on</span>
|
|
<span class="c1"># another Deferred or for more callbacks. Before finishing with it,</span>
|
|
<span class="c1"># make sure its _debugInfo is in the proper state.</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">current</span><span class="o">.</span><span class="n">result</span><span class="p">,</span> <span class="n">Failure</span><span class="p">):</span>
|
|
<span class="c1"># Stash the Failure in the _debugInfo for unhandled error</span>
|
|
<span class="c1"># reporting.</span>
|
|
<span class="k">if</span> <span class="n">current</span><span class="o">.</span><span class="n">_debugInfo</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">current</span><span class="o">.</span><span class="n">_debugInfo</span> <span class="o">=</span> <span class="n">DebugInfo</span><span class="p">()</span>
|
|
<span class="n">current</span><span class="o">.</span><span class="n">_debugInfo</span><span class="o">.</span><span class="n">failResult</span> <span class="o">=</span> <span class="n">current</span><span class="o">.</span><span class="n">result</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># Clear out any Failure in the _debugInfo, since the result</span>
|
|
<span class="c1"># is no longer a Failure.</span>
|
|
<span class="k">if</span> <span class="n">current</span><span class="o">.</span><span class="n">_debugInfo</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">current</span><span class="o">.</span><span class="n">_debugInfo</span><span class="o">.</span><span class="n">failResult</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="c1"># This Deferred is done, pop it from the chain and move back up</span>
|
|
<span class="c1"># to the Deferred which supplied us with our result.</span>
|
|
<span class="n">chain</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Return a string representation of this L{Deferred}.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">cname</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span>
|
|
<span class="n">result</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"result"</span><span class="p">,</span> <span class="n">_NO_RESULT</span><span class="p">)</span>
|
|
<span class="n">myID</span> <span class="o">=</span> <span class="nb">id</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_chainedTo</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">result</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">" waiting on Deferred at 0x</span><span class="si">{</span><span class="nb">id</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_chainedTo</span><span class="p">)</span><span class="si">:</span><span class="s2">x</span><span class="si">}</span><span class="s2">"</span>
|
|
<span class="k">elif</span> <span class="n">result</span> <span class="ow">is</span> <span class="n">_NO_RESULT</span><span class="p">:</span>
|
|
<span class="n">result</span> <span class="o">=</span> <span class="s2">""</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">result</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">" current result: </span><span class="si">{</span><span class="n">result</span><span class="si">!r}</span><span class="s2">"</span>
|
|
<span class="k">return</span> <span class="sa">f</span><span class="s2">"<</span><span class="si">{</span><span class="n">cname</span><span class="si">}</span><span class="s2"> at 0x</span><span class="si">{</span><span class="n">myID</span><span class="si">:</span><span class="s2">x</span><span class="si">}{</span><span class="n">result</span><span class="si">}</span><span class="s2">>"</span>
|
|
|
|
<span class="fm">__repr__</span> <span class="o">=</span> <span class="fm">__str__</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="n">Generator</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">],</span> <span class="kc">None</span><span class="p">,</span> <span class="n">_SelfResultT</span><span class="p">]:</span>
|
|
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">paused</span><span class="p">:</span>
|
|
<span class="c1"># If we're paused, we have no result to give</span>
|
|
<span class="k">yield</span> <span class="bp">self</span>
|
|
<span class="k">continue</span>
|
|
|
|
<span class="n">result</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"result"</span><span class="p">,</span> <span class="n">_NO_RESULT</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">result</span> <span class="ow">is</span> <span class="n">_NO_RESULT</span><span class="p">:</span>
|
|
<span class="k">yield</span> <span class="bp">self</span>
|
|
<span class="k">continue</span>
|
|
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">Failure</span><span class="p">):</span>
|
|
<span class="c1"># Clear the failure on debugInfo so it doesn't raise "unhandled</span>
|
|
<span class="c1"># exception"</span>
|
|
<span class="k">assert</span> <span class="bp">self</span><span class="o">.</span><span class="n">_debugInfo</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_debugInfo</span><span class="o">.</span><span class="n">failResult</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">result</span><span class="o">.</span><span class="n">raiseException</span><span class="p">()</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">result</span> <span class="c1"># type: ignore[return-value]</span>
|
|
|
|
<span class="fm">__await__</span> <span class="o">=</span> <span class="fm">__iter__</span>
|
|
|
|
<div class="viewcode-block" id="Deferred.asFuture">
|
|
<a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.commands.cmdhandler.Deferred.asFuture">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">asFuture</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">loop</span><span class="p">:</span> <span class="n">AbstractEventLoop</span><span class="p">)</span> <span class="o">-></span> <span class="s2">"Future[_SelfResultT]"</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Adapt this L{Deferred} into a L{Future} which is bound to C{loop}.</span>
|
|
|
|
<span class="sd"> @note: converting a L{Deferred} to an L{Future} consumes both</span>
|
|
<span class="sd"> its result and its errors, so this method implicitly converts</span>
|
|
<span class="sd"> C{self} into a L{Deferred} firing with L{None}, regardless of what</span>
|
|
<span class="sd"> its result previously would have been.</span>
|
|
|
|
<span class="sd"> @since: Twisted 17.5.0</span>
|
|
|
|
<span class="sd"> @param loop: The L{asyncio} event loop to bind the L{Future} to.</span>
|
|
|
|
<span class="sd"> @return: A L{Future} which will fire when the L{Deferred} fires.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">future</span> <span class="o">=</span> <span class="n">loop</span><span class="o">.</span><span class="n">create_future</span><span class="p">()</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">checkCancel</span><span class="p">(</span><span class="n">futureAgain</span><span class="p">:</span> <span class="s2">"Future[_SelfResultT]"</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">futureAgain</span><span class="o">.</span><span class="n">cancelled</span><span class="p">():</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">cancel</span><span class="p">()</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">maybeFail</span><span class="p">(</span><span class="n">failure</span><span class="p">:</span> <span class="n">Failure</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">future</span><span class="o">.</span><span class="n">cancelled</span><span class="p">():</span>
|
|
<span class="n">future</span><span class="o">.</span><span class="n">set_exception</span><span class="p">(</span><span class="n">failure</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">maybeSucceed</span><span class="p">(</span><span class="n">result</span><span class="p">:</span> <span class="nb">object</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">future</span><span class="o">.</span><span class="n">cancelled</span><span class="p">():</span>
|
|
<span class="n">future</span><span class="o">.</span><span class="n">set_result</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">addCallbacks</span><span class="p">(</span><span class="n">maybeSucceed</span><span class="p">,</span> <span class="n">maybeFail</span><span class="p">)</span>
|
|
<span class="n">future</span><span class="o">.</span><span class="n">add_done_callback</span><span class="p">(</span><span class="n">checkCancel</span><span class="p">)</span>
|
|
|
|
<span class="k">return</span> <span class="n">future</span></div>
|
|
|
|
|
|
<div class="viewcode-block" id="Deferred.fromFuture">
|
|
<a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.commands.cmdhandler.Deferred.fromFuture">[docs]</a>
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">fromFuture</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">future</span><span class="p">:</span> <span class="s2">"Future[_SelfResultT]"</span><span class="p">)</span> <span class="o">-></span> <span class="s2">"Deferred[_SelfResultT]"</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Adapt a L{Future} to a L{Deferred}.</span>
|
|
|
|
<span class="sd"> @note: This creates a L{Deferred} from a L{Future}, I{not} from</span>
|
|
<span class="sd"> a C{coroutine}; in other words, you will need to call</span>
|
|
<span class="sd"> L{asyncio.ensure_future}, L{asyncio.loop.create_task} or create an</span>
|
|
<span class="sd"> L{asyncio.Task} yourself to get from a C{coroutine} to a</span>
|
|
<span class="sd"> L{Future} if what you have is an awaitable coroutine and</span>
|
|
<span class="sd"> not a L{Future}. (The length of this list of techniques is</span>
|
|
<span class="sd"> exactly why we have left it to the caller!)</span>
|
|
|
|
<span class="sd"> @since: Twisted 17.5.0</span>
|
|
|
|
<span class="sd"> @param future: The L{Future} to adapt.</span>
|
|
|
|
<span class="sd"> @return: A L{Deferred} which will fire when the L{Future} fires.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">adapt</span><span class="p">(</span><span class="n">result</span><span class="p">:</span> <span class="n">Future</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">extracted</span><span class="p">:</span> <span class="n">_SelfResultT</span> <span class="o">|</span> <span class="n">Failure</span> <span class="o">=</span> <span class="n">result</span><span class="o">.</span><span class="n">result</span><span class="p">()</span>
|
|
<span class="k">except</span> <span class="ne">BaseException</span><span class="p">:</span>
|
|
<span class="n">extracted</span> <span class="o">=</span> <span class="n">Failure</span><span class="p">()</span>
|
|
<span class="n">actual</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="n">extracted</span><span class="p">)</span>
|
|
|
|
<span class="n">futureCancel</span> <span class="o">=</span> <span class="nb">object</span><span class="p">()</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">cancel</span><span class="p">(</span><span class="n">reself</span><span class="p">:</span> <span class="n">Deferred</span><span class="p">[</span><span class="nb">object</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">future</span><span class="o">.</span><span class="n">cancel</span><span class="p">()</span>
|
|
<span class="n">reself</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="n">futureCancel</span><span class="p">)</span>
|
|
|
|
<span class="bp">self</span> <span class="o">=</span> <span class="bp">cls</span><span class="p">(</span><span class="n">cancel</span><span class="p">)</span>
|
|
<span class="n">actual</span> <span class="o">=</span> <span class="bp">self</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">uncancel</span><span class="p">(</span>
|
|
<span class="n">result</span><span class="p">:</span> <span class="n">_SelfResultT</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Union</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">,</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">]]:</span>
|
|
<span class="k">if</span> <span class="n">result</span> <span class="ow">is</span> <span class="n">futureCancel</span><span class="p">:</span>
|
|
<span class="k">nonlocal</span> <span class="n">actual</span>
|
|
<span class="n">actual</span> <span class="o">=</span> <span class="n">Deferred</span><span class="p">()</span>
|
|
<span class="k">return</span> <span class="n">actual</span>
|
|
<span class="k">return</span> <span class="n">result</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">addCallback</span><span class="p">(</span><span class="n">uncancel</span><span class="p">)</span>
|
|
<span class="n">future</span><span class="o">.</span><span class="n">add_done_callback</span><span class="p">(</span><span class="n">adapt</span><span class="p">)</span>
|
|
|
|
<span class="k">return</span> <span class="bp">self</span></div>
|
|
|
|
|
|
<div class="viewcode-block" id="Deferred.fromCoroutine">
|
|
<a class="viewcode-back" href="../../../api/evennia.scripts.scripts.html#evennia.commands.cmdhandler.Deferred.fromCoroutine">[docs]</a>
|
|
<span class="nd">@classmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">fromCoroutine</span><span class="p">(</span>
|
|
<span class="bp">cls</span><span class="p">,</span>
|
|
<span class="n">coro</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span>
|
|
<span class="n">Coroutine</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">Any</span><span class="p">],</span> <span class="n">Any</span><span class="p">,</span> <span class="n">_T</span><span class="p">],</span>
|
|
<span class="n">Generator</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">Any</span><span class="p">],</span> <span class="n">Any</span><span class="p">,</span> <span class="n">_T</span><span class="p">],</span>
|
|
<span class="p">],</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="s2">"Deferred[_T]"</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Schedule the execution of a coroutine that awaits on L{Deferred}s,</span>
|
|
<span class="sd"> wrapping it in a L{Deferred} that will fire on success/failure of the</span>
|
|
<span class="sd"> coroutine.</span>
|
|
|
|
<span class="sd"> Coroutine functions return a coroutine object, similar to how</span>
|
|
<span class="sd"> generators work. This function turns that coroutine into a Deferred,</span>
|
|
<span class="sd"> meaning that it can be used in regular Twisted code. For example::</span>
|
|
|
|
<span class="sd"> import treq</span>
|
|
<span class="sd"> from twisted.internet.defer import Deferred</span>
|
|
<span class="sd"> from twisted.internet.task import react</span>
|
|
|
|
<span class="sd"> async def crawl(pages):</span>
|
|
<span class="sd"> results = {}</span>
|
|
<span class="sd"> for page in pages:</span>
|
|
<span class="sd"> results[page] = await treq.content(await treq.get(page))</span>
|
|
<span class="sd"> return results</span>
|
|
|
|
<span class="sd"> def main(reactor):</span>
|
|
<span class="sd"> pages = [</span>
|
|
<span class="sd"> "http://localhost:8080"</span>
|
|
<span class="sd"> ]</span>
|
|
<span class="sd"> d = Deferred.fromCoroutine(crawl(pages))</span>
|
|
<span class="sd"> d.addCallback(print)</span>
|
|
<span class="sd"> return d</span>
|
|
|
|
<span class="sd"> react(main)</span>
|
|
|
|
<span class="sd"> @since: Twisted 21.2.0</span>
|
|
|
|
<span class="sd"> @param coro: The coroutine object to schedule.</span>
|
|
|
|
<span class="sd"> @raise ValueError: If C{coro} is not a coroutine or generator.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="c1"># asyncio.iscoroutine <3.12 identifies generators as coroutines, too.</span>
|
|
<span class="c1"># for >=3.12 we need to check isgenerator also</span>
|
|
<span class="c1"># see https://github.com/python/cpython/issues/102748</span>
|
|
<span class="k">if</span> <span class="n">iscoroutine</span><span class="p">(</span><span class="n">coro</span><span class="p">)</span> <span class="ow">or</span> <span class="n">inspect</span><span class="o">.</span><span class="n">isgenerator</span><span class="p">(</span><span class="n">coro</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="n">_cancellableInlineCallbacks</span><span class="p">(</span><span class="n">coro</span><span class="p">)</span>
|
|
<span class="k">raise</span> <span class="n">NotACoroutineError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">coro</span><span class="si">!r}</span><span class="s2"> is not a coroutine"</span><span class="p">)</span></div>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">__init_subclass__</span><span class="p">(</span><span class="bp">cls</span><span class="p">:</span> <span class="n">Type</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">Any</span><span class="p">]],</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Any</span><span class="p">):</span>
|
|
<span class="c1"># Whenever a subclass is created, record it in L{_DEFERRED_SUBCLASSES}</span>
|
|
<span class="c1"># so we can emulate C{isinstance()} more efficiently.</span>
|
|
<span class="n">_DEFERRED_SUBCLASSES</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">cls</span><span class="p">)</span></div>
|
|
|
|
|
|
|
|
<span class="n">_DEFERRED_SUBCLASSES</span> <span class="o">=</span> <span class="p">[</span><span class="n">Deferred</span><span class="p">]</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">ensureDeferred</span><span class="p">(</span>
|
|
<span class="n">coro</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span>
|
|
<span class="n">Coroutine</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">Any</span><span class="p">],</span> <span class="n">Any</span><span class="p">,</span> <span class="n">_T</span><span class="p">],</span>
|
|
<span class="n">Generator</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">Any</span><span class="p">],</span> <span class="n">Any</span><span class="p">,</span> <span class="n">_T</span><span class="p">],</span>
|
|
<span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">],</span>
|
|
<span class="p">]</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">]:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Schedule the execution of a coroutine that awaits/yields from L{Deferred}s,</span>
|
|
<span class="sd"> wrapping it in a L{Deferred} that will fire on success/failure of the</span>
|
|
<span class="sd"> coroutine. If a Deferred is passed to this function, it will be returned</span>
|
|
<span class="sd"> directly (mimicking the L{asyncio.ensure_future} function).</span>
|
|
|
|
<span class="sd"> See L{Deferred.fromCoroutine} for examples of coroutines.</span>
|
|
|
|
<span class="sd"> @param coro: The coroutine object to schedule, or a L{Deferred}.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="nb">type</span><span class="p">(</span><span class="n">coro</span><span class="p">)</span> <span class="ow">in</span> <span class="n">_DEFERRED_SUBCLASSES</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">coro</span> <span class="c1"># type: ignore[return-value]</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">Deferred</span><span class="o">.</span><span class="n">fromCoroutine</span><span class="p">(</span><span class="n">coro</span><span class="p">)</span> <span class="c1"># type: ignore[arg-type]</span>
|
|
<span class="k">except</span> <span class="n">NotACoroutineError</span><span class="p">:</span>
|
|
<span class="c1"># It's not a coroutine. Raise an exception, but say that it's also</span>
|
|
<span class="c1"># not a Deferred so the error makes sense.</span>
|
|
<span class="k">raise</span> <span class="n">NotACoroutineError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">coro</span><span class="si">!r}</span><span class="s2"> is not a coroutine or a Deferred"</span><span class="p">)</span>
|
|
|
|
|
|
<span class="nd">@comparable</span>
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">FirstError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> First error to occur in a L{DeferredList} if C{fireOnOneErrback} is set.</span>
|
|
|
|
<span class="sd"> @ivar subFailure: The L{Failure} that occurred.</span>
|
|
<span class="sd"> @ivar index: The index of the L{Deferred} in the L{DeferredList} where</span>
|
|
<span class="sd"> it happened.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">failure</span><span class="p">:</span> <span class="n">Failure</span><span class="p">,</span> <span class="n">index</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="ne">Exception</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">failure</span><span class="p">,</span> <span class="n">index</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">subFailure</span> <span class="o">=</span> <span class="n">failure</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">index</span> <span class="o">=</span> <span class="n">index</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> The I{repr} of L{FirstError} instances includes the repr of the</span>
|
|
<span class="sd"> wrapped failure's exception and the index of the L{FirstError}.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">return</span> <span class="s2">"FirstError[#</span><span class="si">%d</span><span class="s2">, </span><span class="si">%r</span><span class="s2">]"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">index</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">subFailure</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> The I{str} of L{FirstError} instances includes the I{str} of the</span>
|
|
<span class="sd"> entire wrapped failure (including its traceback and exception) and</span>
|
|
<span class="sd"> the index of the L{FirstError}.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">return</span> <span class="s2">"FirstError[#</span><span class="si">%d</span><span class="s2">, </span><span class="si">%s</span><span class="s2">]"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">index</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">subFailure</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">__cmp__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">:</span> <span class="nb">object</span><span class="p">)</span> <span class="o">-></span> <span class="nb">int</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Comparison between L{FirstError} and other L{FirstError} instances</span>
|
|
<span class="sd"> is defined as the comparison of the index and sub-failure of each</span>
|
|
<span class="sd"> instance. L{FirstError} instances don't compare equal to anything</span>
|
|
<span class="sd"> that isn't a L{FirstError} instance.</span>
|
|
|
|
<span class="sd"> @since: 8.2</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">FirstError</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="n">cmp</span><span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">index</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">subFailure</span><span class="p">),</span> <span class="p">(</span><span class="n">other</span><span class="o">.</span><span class="n">index</span><span class="p">,</span> <span class="n">other</span><span class="o">.</span><span class="n">subFailure</span><span class="p">))</span>
|
|
<span class="k">return</span> <span class="o">-</span><span class="mi">1</span>
|
|
|
|
|
|
<span class="n">_DeferredListSingleResultT</span> <span class="o">=</span> <span class="n">Tuple</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">,</span> <span class="nb">int</span><span class="p">]</span>
|
|
<span class="n">_DeferredListResultItemT</span> <span class="o">=</span> <span class="n">Tuple</span><span class="p">[</span><span class="nb">bool</span><span class="p">,</span> <span class="n">_SelfResultT</span><span class="p">]</span>
|
|
<span class="n">_DeferredListResultListT</span> <span class="o">=</span> <span class="n">List</span><span class="p">[</span><span class="n">_DeferredListResultItemT</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">]]</span>
|
|
|
|
<span class="k">if</span> <span class="n">TYPE_CHECKING</span><span class="p">:</span>
|
|
<span class="c1"># The result type is different depending on whether fireOnOneCallback</span>
|
|
<span class="c1"># is True or False. The type system is not flexible enough to handle</span>
|
|
<span class="c1"># that in a class definition, so instead we pretend that DeferredList</span>
|
|
<span class="c1"># is a function that returns a Deferred.</span>
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_DeferredList</span><span class="p">(</span>
|
|
<span class="n">deferredList</span><span class="p">:</span> <span class="n">Iterable</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">]],</span>
|
|
<span class="n">fireOnOneCallback</span><span class="p">:</span> <span class="n">Literal</span><span class="p">[</span><span class="kc">True</span><span class="p">],</span>
|
|
<span class="n">fireOnOneErrback</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
|
|
<span class="n">consumeErrors</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_DeferredListSingleResultT</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">]]:</span>
|
|
<span class="o">...</span>
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_DeferredList</span><span class="p">(</span>
|
|
<span class="n">deferredList</span><span class="p">:</span> <span class="n">Iterable</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">]],</span>
|
|
<span class="n">fireOnOneCallback</span><span class="p">:</span> <span class="n">Literal</span><span class="p">[</span><span class="kc">False</span><span class="p">]</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
|
|
<span class="n">fireOnOneErrback</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
|
|
<span class="n">consumeErrors</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_DeferredListResultListT</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">]]:</span>
|
|
<span class="o">...</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_DeferredList</span><span class="p">(</span>
|
|
<span class="n">deferredList</span><span class="p">:</span> <span class="n">Iterable</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">]],</span>
|
|
<span class="n">fireOnOneCallback</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
|
|
<span class="n">fireOnOneErrback</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
|
|
<span class="n">consumeErrors</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Union</span><span class="p">[</span>
|
|
<span class="n">Deferred</span><span class="p">[</span><span class="n">_DeferredListSingleResultT</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">]],</span>
|
|
<span class="n">Deferred</span><span class="p">[</span><span class="n">_DeferredListResultListT</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">]],</span>
|
|
<span class="p">]:</span>
|
|
<span class="o">...</span>
|
|
|
|
<span class="n">DeferredList</span> <span class="o">=</span> <span class="n">_DeferredList</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">DeferredList</span><span class="p">(</span> <span class="c1"># type: ignore[no-redef] # noqa:F811</span>
|
|
<span class="n">Deferred</span><span class="p">[</span><span class="n">_DeferredListResultListT</span><span class="p">[</span><span class="n">Any</span><span class="p">]]</span>
|
|
<span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> L{DeferredList} is a tool for collecting the results of several Deferreds.</span>
|
|
|
|
<span class="sd"> This tracks a list of L{Deferred}s for their results, and makes a single</span>
|
|
<span class="sd"> callback when they have all completed. By default, the ultimate result is a</span>
|
|
<span class="sd"> list of (success, result) tuples, 'success' being a boolean.</span>
|
|
<span class="sd"> L{DeferredList} exposes the same API that L{Deferred} does, so callbacks and</span>
|
|
<span class="sd"> errbacks can be added to it in the same way.</span>
|
|
|
|
<span class="sd"> L{DeferredList} is implemented by adding callbacks and errbacks to each</span>
|
|
<span class="sd"> L{Deferred} in the list passed to it. This means callbacks and errbacks</span>
|
|
<span class="sd"> added to the Deferreds before they are passed to L{DeferredList} will change</span>
|
|
<span class="sd"> the result that L{DeferredList} sees (i.e., L{DeferredList} is not special).</span>
|
|
<span class="sd"> Callbacks and errbacks can also be added to the Deferreds after they are</span>
|
|
<span class="sd"> passed to L{DeferredList} and L{DeferredList} may change the result that</span>
|
|
<span class="sd"> they see.</span>
|
|
|
|
<span class="sd"> See the documentation for the C{__init__} arguments for more information.</span>
|
|
|
|
<span class="sd"> @ivar _deferredList: The L{list} of L{Deferred}s to track.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">fireOnOneCallback</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="n">fireOnOneErrback</span> <span class="o">=</span> <span class="kc">False</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">deferredList</span><span class="p">:</span> <span class="n">Iterable</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">]],</span>
|
|
<span class="n">fireOnOneCallback</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
|
|
<span class="n">fireOnOneErrback</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
|
|
<span class="n">consumeErrors</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
|
|
<span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Initialize a DeferredList.</span>
|
|
|
|
<span class="sd"> @param deferredList: The deferreds to track.</span>
|
|
<span class="sd"> @param fireOnOneCallback: (keyword param) a flag indicating that this</span>
|
|
<span class="sd"> L{DeferredList} will fire when the first L{Deferred} in</span>
|
|
<span class="sd"> C{deferredList} fires with a non-failure result without waiting for</span>
|
|
<span class="sd"> any of the other Deferreds. When this flag is set, the DeferredList</span>
|
|
<span class="sd"> will fire with a two-tuple: the first element is the result of the</span>
|
|
<span class="sd"> Deferred which fired; the second element is the index in</span>
|
|
<span class="sd"> C{deferredList} of that Deferred.</span>
|
|
<span class="sd"> @param fireOnOneErrback: (keyword param) a flag indicating that this</span>
|
|
<span class="sd"> L{DeferredList} will fire when the first L{Deferred} in</span>
|
|
<span class="sd"> C{deferredList} fires with a failure result without waiting for any</span>
|
|
<span class="sd"> of the other Deferreds. When this flag is set, if a Deferred in the</span>
|
|
<span class="sd"> list errbacks, the DeferredList will errback with a L{FirstError}</span>
|
|
<span class="sd"> failure wrapping the failure of that Deferred.</span>
|
|
<span class="sd"> @param consumeErrors: (keyword param) a flag indicating that failures in</span>
|
|
<span class="sd"> any of the included L{Deferred}s should not be propagated to</span>
|
|
<span class="sd"> errbacks added to the individual L{Deferred}s after this</span>
|
|
<span class="sd"> L{DeferredList} is constructed. After constructing the</span>
|
|
<span class="sd"> L{DeferredList}, any errors in the individual L{Deferred}s will be</span>
|
|
<span class="sd"> converted to a callback result of L{None}. This is useful to</span>
|
|
<span class="sd"> prevent spurious 'Unhandled error in Deferred' messages from being</span>
|
|
<span class="sd"> logged. This does not prevent C{fireOnOneErrback} from working.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_deferredList</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">deferredList</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Note this contains optional result values as the DeferredList is</span>
|
|
<span class="c1"># processing its results, even though the callback result will not,</span>
|
|
<span class="c1"># which is why we aren't using _DeferredListResultListT here.</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">resultList</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Optional</span><span class="p">[</span><span class="n">_DeferredListResultItemT</span><span class="p">[</span><span class="n">Any</span><span class="p">]]]</span> <span class="o">=</span> <span class="p">[</span><span class="kc">None</span><span class="p">]</span> <span class="o">*</span> <span class="nb">len</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_deferredList</span>
|
|
<span class="p">)</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> The final result, in progress.</span>
|
|
<span class="sd"> Each item in the list corresponds to the L{Deferred} at the same</span>
|
|
<span class="sd"> position in L{_deferredList}. It will be L{None} if the L{Deferred}</span>
|
|
<span class="sd"> did not complete yet, or a C{(success, result)} pair if it did.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">Deferred</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_deferredList</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">fireOnOneCallback</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">callback</span><span class="p">([])</span>
|
|
|
|
<span class="c1"># These flags need to be set *before* attaching callbacks to the</span>
|
|
<span class="c1"># deferreds, because the callbacks use these flags, and will run</span>
|
|
<span class="c1"># synchronously if any of the deferreds are already fired.</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">fireOnOneCallback</span> <span class="o">=</span> <span class="n">fireOnOneCallback</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">fireOnOneErrback</span> <span class="o">=</span> <span class="n">fireOnOneErrback</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">consumeErrors</span> <span class="o">=</span> <span class="n">consumeErrors</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">finishedCount</span> <span class="o">=</span> <span class="mi">0</span>
|
|
|
|
<span class="n">index</span> <span class="o">=</span> <span class="mi">0</span>
|
|
<span class="k">for</span> <span class="n">deferred</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_deferredList</span><span class="p">:</span>
|
|
<span class="n">deferred</span><span class="o">.</span><span class="n">addCallbacks</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_cbDeferred</span><span class="p">,</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_cbDeferred</span><span class="p">,</span>
|
|
<span class="n">callbackArgs</span><span class="o">=</span><span class="p">(</span><span class="n">index</span><span class="p">,</span> <span class="n">SUCCESS</span><span class="p">),</span>
|
|
<span class="n">errbackArgs</span><span class="o">=</span><span class="p">(</span><span class="n">index</span><span class="p">,</span> <span class="n">FAILURE</span><span class="p">),</span>
|
|
<span class="p">)</span>
|
|
<span class="n">index</span> <span class="o">=</span> <span class="n">index</span> <span class="o">+</span> <span class="mi">1</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_cbDeferred</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span> <span class="n">result</span><span class="p">:</span> <span class="n">_SelfResultT</span><span class="p">,</span> <span class="n">index</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">succeeded</span><span class="p">:</span> <span class="nb">bool</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Optional</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">]:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> (internal) Callback for when one of my deferreds fires.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">resultList</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">succeeded</span><span class="p">,</span> <span class="n">result</span><span class="p">)</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">finishedCount</span> <span class="o">+=</span> <span class="mi">1</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">called</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">succeeded</span> <span class="o">==</span> <span class="n">SUCCESS</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">fireOnOneCallback</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">callback</span><span class="p">((</span><span class="n">result</span><span class="p">,</span> <span class="n">index</span><span class="p">))</span> <span class="c1"># type: ignore[arg-type]</span>
|
|
<span class="k">elif</span> <span class="n">succeeded</span> <span class="o">==</span> <span class="n">FAILURE</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">fireOnOneErrback</span><span class="p">:</span>
|
|
<span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">Failure</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">errback</span><span class="p">(</span><span class="n">Failure</span><span class="p">(</span><span class="n">FirstError</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">index</span><span class="p">)))</span>
|
|
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">finishedCount</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">resultList</span><span class="p">):</span>
|
|
<span class="c1"># At this point, None values in self.resultList have been</span>
|
|
<span class="c1"># replaced by result values, so we cast it to</span>
|
|
<span class="c1"># _DeferredListResultListT to match the callback result type.</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="n">cast</span><span class="p">(</span><span class="n">_DeferredListResultListT</span><span class="p">[</span><span class="n">Any</span><span class="p">],</span> <span class="bp">self</span><span class="o">.</span><span class="n">resultList</span><span class="p">))</span>
|
|
|
|
<span class="k">if</span> <span class="n">succeeded</span> <span class="o">==</span> <span class="n">FAILURE</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">consumeErrors</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="kc">None</span>
|
|
|
|
<span class="k">return</span> <span class="n">result</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">cancel</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Cancel this L{DeferredList}.</span>
|
|
|
|
<span class="sd"> If the L{DeferredList} hasn't fired yet, cancel every L{Deferred} in</span>
|
|
<span class="sd"> the list.</span>
|
|
|
|
<span class="sd"> If the L{DeferredList} has fired, including the case where the</span>
|
|
<span class="sd"> C{fireOnOneCallback}/C{fireOnOneErrback} flag is set and the</span>
|
|
<span class="sd"> L{DeferredList} fires because one L{Deferred} in the list fires with a</span>
|
|
<span class="sd"> non-failure/failure result, do nothing in the C{cancel} method.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">called</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">deferred</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_deferredList</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">deferred</span><span class="o">.</span><span class="n">cancel</span><span class="p">()</span>
|
|
<span class="k">except</span> <span class="ne">BaseException</span><span class="p">:</span>
|
|
<span class="n">log</span><span class="o">.</span><span class="n">failure</span><span class="p">(</span><span class="s2">"Exception raised from user supplied canceller"</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_parseDeferredListResult</span><span class="p">(</span>
|
|
<span class="n">resultList</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">_DeferredListResultItemT</span><span class="p">[</span><span class="n">_T</span><span class="p">]],</span> <span class="n">fireOnOneErrback</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span> <span class="o">/</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">List</span><span class="p">[</span><span class="n">_T</span><span class="p">]:</span>
|
|
<span class="k">if</span> <span class="n">__debug__</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">result</span> <span class="ow">in</span> <span class="n">resultList</span><span class="p">:</span>
|
|
<span class="k">assert</span> <span class="n">result</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
<span class="n">success</span><span class="p">,</span> <span class="n">value</span> <span class="o">=</span> <span class="n">result</span>
|
|
<span class="k">assert</span> <span class="n">success</span>
|
|
<span class="k">return</span> <span class="p">[</span><span class="n">x</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">resultList</span><span class="p">]</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">gatherResults</span><span class="p">(</span>
|
|
<span class="n">deferredList</span><span class="p">:</span> <span class="n">Iterable</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">]],</span> <span class="n">consumeErrors</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="n">_T</span><span class="p">]]:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Returns, via a L{Deferred}, a list with the results of the given</span>
|
|
<span class="sd"> L{Deferred}s - in effect, a "join" of multiple deferred operations.</span>
|
|
|
|
<span class="sd"> The returned L{Deferred} will fire when I{all} of the provided L{Deferred}s</span>
|
|
<span class="sd"> have fired, or when any one of them has failed.</span>
|
|
|
|
<span class="sd"> This method can be cancelled by calling the C{cancel} method of the</span>
|
|
<span class="sd"> L{Deferred}, all the L{Deferred}s in the list will be cancelled.</span>
|
|
|
|
<span class="sd"> This differs from L{DeferredList} in that you don't need to parse</span>
|
|
<span class="sd"> the result for success/failure.</span>
|
|
|
|
<span class="sd"> @param consumeErrors: (keyword param) a flag, defaulting to False,</span>
|
|
<span class="sd"> indicating that failures in any of the given L{Deferred}s should not be</span>
|
|
<span class="sd"> propagated to errbacks added to the individual L{Deferred}s after this</span>
|
|
<span class="sd"> L{gatherResults} invocation. Any such errors in the individual</span>
|
|
<span class="sd"> L{Deferred}s will be converted to a callback result of L{None}. This</span>
|
|
<span class="sd"> is useful to prevent spurious 'Unhandled error in Deferred' messages</span>
|
|
<span class="sd"> from being logged. This parameter is available since 11.1.0.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">return</span> <span class="n">DeferredList</span><span class="p">(</span>
|
|
<span class="n">deferredList</span><span class="p">,</span> <span class="n">fireOnOneErrback</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">consumeErrors</span><span class="o">=</span><span class="n">consumeErrors</span>
|
|
<span class="p">)</span><span class="o">.</span><span class="n">addCallback</span><span class="p">(</span><span class="n">_parseDeferredListResult</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">FailureGroup</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> More than one failure occurred.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">failures</span><span class="p">:</span> <span class="n">Sequence</span><span class="p">[</span><span class="n">Failure</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="nb">super</span><span class="p">(</span><span class="n">FailureGroup</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="fm">__init__</span><span class="p">()</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">failures</span> <span class="o">=</span> <span class="n">failures</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">race</span><span class="p">(</span><span class="n">ds</span><span class="p">:</span> <span class="n">Sequence</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">]])</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="nb">tuple</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="n">_T</span><span class="p">]]:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Select the first available result from the sequence of Deferreds and</span>
|
|
<span class="sd"> cancel the rest.</span>
|
|
|
|
<span class="sd"> @return: A cancellable L{Deferred} that fires with the index and output of</span>
|
|
<span class="sd"> the element of C{ds} to have a success result first, or that fires</span>
|
|
<span class="sd"> with L{FailureGroup} holding a list of their failures if they all</span>
|
|
<span class="sd"> fail.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="c1"># Keep track of the Deferred for the action which completed first. When</span>
|
|
<span class="c1"># it completes, all of the other Deferreds will get cancelled but this one</span>
|
|
<span class="c1"># shouldn't be. Even though it "completed" it isn't really done - the</span>
|
|
<span class="c1"># caller will still be using it for something. If we cancelled it,</span>
|
|
<span class="c1"># cancellation could propagate down to them.</span>
|
|
<span class="n">winner</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">]]</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="c1"># The cancellation function for the Deferred this function returns.</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">cancel</span><span class="p">(</span><span class="n">result</span><span class="p">:</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="c1"># If it is cancelled then we cancel all of the Deferreds for the</span>
|
|
<span class="c1"># individual actions because there is no longer the possibility of</span>
|
|
<span class="c1"># delivering any of their results anywhere. We don't have to fire</span>
|
|
<span class="c1"># `result` because the Deferred will do that for us.</span>
|
|
<span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="n">to_cancel</span><span class="p">:</span>
|
|
<span class="n">d</span><span class="o">.</span><span class="n">cancel</span><span class="p">()</span>
|
|
|
|
<span class="c1"># The Deferred that this function will return. It will fire with the</span>
|
|
<span class="c1"># index and output of the action that completes first, or errback if all</span>
|
|
<span class="c1"># of the actions fail. If it is cancelled, all of the actions will be</span>
|
|
<span class="c1"># cancelled.</span>
|
|
<span class="n">final_result</span><span class="p">:</span> <span class="n">Deferred</span><span class="p">[</span><span class="nb">tuple</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="n">_T</span><span class="p">]]</span> <span class="o">=</span> <span class="n">Deferred</span><span class="p">(</span><span class="n">canceller</span><span class="o">=</span><span class="n">cancel</span><span class="p">)</span>
|
|
|
|
<span class="c1"># A callback for an individual action.</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">succeeded</span><span class="p">(</span><span class="n">this_output</span><span class="p">:</span> <span class="n">_T</span><span class="p">,</span> <span class="n">this_index</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="c1"># If it is the first action to succeed then it becomes the "winner",</span>
|
|
<span class="c1"># its index/output become the externally visible result, and the rest</span>
|
|
<span class="c1"># of the action Deferreds get cancelled. If it is not the first</span>
|
|
<span class="c1"># action to succeed (because some action did not support</span>
|
|
<span class="c1"># cancellation), just ignore the result. It is uncommon for this</span>
|
|
<span class="c1"># callback to be entered twice. The only way it can happen is if one</span>
|
|
<span class="c1"># of the input Deferreds has a cancellation function that fires the</span>
|
|
<span class="c1"># Deferred with a success result.</span>
|
|
<span class="k">nonlocal</span> <span class="n">winner</span>
|
|
<span class="k">if</span> <span class="n">winner</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="c1"># This is the first success. Act on it.</span>
|
|
<span class="n">winner</span> <span class="o">=</span> <span class="n">to_cancel</span><span class="p">[</span><span class="n">this_index</span><span class="p">]</span>
|
|
|
|
<span class="c1"># Cancel the rest.</span>
|
|
<span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="n">to_cancel</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">d</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">winner</span><span class="p">:</span>
|
|
<span class="n">d</span><span class="o">.</span><span class="n">cancel</span><span class="p">()</span>
|
|
|
|
<span class="c1"># Fire our Deferred</span>
|
|
<span class="n">final_result</span><span class="o">.</span><span class="n">callback</span><span class="p">((</span><span class="n">this_index</span><span class="p">,</span> <span class="n">this_output</span><span class="p">))</span>
|
|
|
|
<span class="c1"># Keep track of how many actions have failed. If they all fail we need to</span>
|
|
<span class="c1"># deliver failure notification on our externally visible result.</span>
|
|
<span class="n">failure_state</span> <span class="o">=</span> <span class="p">[]</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">failed</span><span class="p">(</span><span class="n">failure</span><span class="p">:</span> <span class="n">Failure</span><span class="p">,</span> <span class="n">this_index</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">failure_state</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">this_index</span><span class="p">,</span> <span class="n">failure</span><span class="p">))</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">failure_state</span><span class="p">)</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">to_cancel</span><span class="p">):</span>
|
|
<span class="c1"># Every operation failed.</span>
|
|
<span class="n">failure_state</span><span class="o">.</span><span class="n">sort</span><span class="p">()</span>
|
|
<span class="n">failures</span> <span class="o">=</span> <span class="p">[</span><span class="n">f</span> <span class="k">for</span> <span class="p">(</span><span class="n">ignored</span><span class="p">,</span> <span class="n">f</span><span class="p">)</span> <span class="ow">in</span> <span class="n">failure_state</span><span class="p">]</span>
|
|
<span class="n">final_result</span><span class="o">.</span><span class="n">errback</span><span class="p">(</span><span class="n">FailureGroup</span><span class="p">(</span><span class="n">failures</span><span class="p">))</span>
|
|
|
|
<span class="c1"># Copy the sequence of Deferreds so we know it doesn't get mutated out</span>
|
|
<span class="c1"># from under us.</span>
|
|
<span class="n">to_cancel</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">ds</span><span class="p">)</span>
|
|
<span class="k">for</span> <span class="n">index</span><span class="p">,</span> <span class="n">d</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">ds</span><span class="p">):</span>
|
|
<span class="c1"># Propagate the position of this action as well as the argument to f</span>
|
|
<span class="c1"># to the success callback so we can cancel the right Deferreds and</span>
|
|
<span class="c1"># propagate the result outwards.</span>
|
|
<span class="n">d</span><span class="o">.</span><span class="n">addCallbacks</span><span class="p">(</span><span class="n">succeeded</span><span class="p">,</span> <span class="n">failed</span><span class="p">,</span> <span class="n">callbackArgs</span><span class="o">=</span><span class="p">(</span><span class="n">index</span><span class="p">,),</span> <span class="n">errbackArgs</span><span class="o">=</span><span class="p">(</span><span class="n">index</span><span class="p">,))</span>
|
|
|
|
<span class="k">return</span> <span class="n">final_result</span>
|
|
|
|
|
|
<span class="c1"># Constants for use with DeferredList</span>
|
|
<span class="n">SUCCESS</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">FAILURE</span> <span class="o">=</span> <span class="kc">False</span>
|
|
|
|
|
|
<span class="c1">## deferredGenerator</span>
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">waitForDeferred</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> See L{deferredGenerator}.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">result</span><span class="p">:</span> <span class="n">Any</span> <span class="o">=</span> <span class="n">_NO_RESULT</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">d</span><span class="p">:</span> <span class="n">Deferred</span><span class="p">[</span><span class="nb">object</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span>
|
|
<span class="s2">"twisted.internet.defer.waitForDeferred was deprecated in "</span>
|
|
<span class="s2">"Twisted 15.0.0; please use twisted.internet.defer.inlineCallbacks "</span>
|
|
<span class="s2">"instead"</span><span class="p">,</span>
|
|
<span class="ne">DeprecationWarning</span><span class="p">,</span>
|
|
<span class="n">stacklevel</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">Deferred</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"You must give waitForDeferred a Deferred. You gave it </span><span class="si">{</span><span class="n">d</span><span class="si">!r}</span><span class="s2">."</span>
|
|
<span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">d</span> <span class="o">=</span> <span class="n">d</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">getResult</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="n">Any</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">result</span><span class="p">,</span> <span class="n">Failure</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">result</span><span class="o">.</span><span class="n">raiseException</span><span class="p">()</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">result</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">_NO_RESULT</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">result</span>
|
|
|
|
|
|
<span class="n">_DeferableGenerator</span> <span class="o">=</span> <span class="n">Generator</span><span class="p">[</span><span class="nb">object</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">]</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_deferGenerator</span><span class="p">(</span>
|
|
<span class="n">g</span><span class="p">:</span> <span class="n">_DeferableGenerator</span><span class="p">,</span> <span class="n">deferred</span><span class="p">:</span> <span class="n">Deferred</span><span class="p">[</span><span class="nb">object</span><span class="p">]</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">Any</span><span class="p">]:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> See L{deferredGenerator}.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">result</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="c1"># This function is complicated by the need to prevent unbounded recursion</span>
|
|
<span class="c1"># arising from repeatedly yielding immediately ready deferreds. This while</span>
|
|
<span class="c1"># loop and the waiting variable solve that by manually unfolding the</span>
|
|
<span class="c1"># recursion.</span>
|
|
|
|
<span class="c1"># defgen is waiting for result? # result</span>
|
|
<span class="c1"># type note: List[Any] because you can't annotate List items by index.</span>
|
|
<span class="c1"># …better fix would be to create a class, but we need to jettison</span>
|
|
<span class="c1"># deferredGenerator anyway.</span>
|
|
<span class="n">waiting</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="kc">True</span><span class="p">,</span> <span class="kc">None</span><span class="p">]</span>
|
|
|
|
<span class="k">while</span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">result</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">StopIteration</span><span class="p">:</span>
|
|
<span class="n">deferred</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">deferred</span>
|
|
<span class="k">except</span> <span class="ne">BaseException</span><span class="p">:</span>
|
|
<span class="n">deferred</span><span class="o">.</span><span class="n">errback</span><span class="p">()</span>
|
|
<span class="k">return</span> <span class="n">deferred</span>
|
|
|
|
<span class="c1"># Deferred.callback(Deferred) raises an error; we catch this case</span>
|
|
<span class="c1"># early here and give a nicer error message to the user in case</span>
|
|
<span class="c1"># they yield a Deferred.</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">Deferred</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="n">fail</span><span class="p">(</span><span class="ne">TypeError</span><span class="p">(</span><span class="s2">"Yield waitForDeferred(d), not d!"</span><span class="p">))</span>
|
|
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">waitForDeferred</span><span class="p">):</span>
|
|
<span class="c1"># a waitForDeferred was yielded, get the result.</span>
|
|
<span class="c1"># Pass result in so it don't get changed going around the loop</span>
|
|
<span class="c1"># This isn't a problem for waiting, as it's only reused if</span>
|
|
<span class="c1"># gotResult has already been executed.</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">gotResult</span><span class="p">(</span>
|
|
<span class="n">r</span><span class="p">:</span> <span class="nb">object</span><span class="p">,</span> <span class="n">result</span><span class="p">:</span> <span class="n">waitForDeferred</span> <span class="o">=</span> <span class="n">cast</span><span class="p">(</span><span class="n">waitForDeferred</span><span class="p">,</span> <span class="n">result</span><span class="p">)</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">result</span><span class="o">.</span><span class="n">result</span> <span class="o">=</span> <span class="n">r</span>
|
|
<span class="k">if</span> <span class="n">waiting</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
|
|
<span class="n">waiting</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="n">waiting</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">r</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">_deferGenerator</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">deferred</span><span class="p">)</span>
|
|
|
|
<span class="n">result</span><span class="o">.</span><span class="n">d</span><span class="o">.</span><span class="n">addBoth</span><span class="p">(</span><span class="n">gotResult</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">waiting</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
|
|
<span class="c1"># Haven't called back yet, set flag so that we get reinvoked</span>
|
|
<span class="c1"># and return from the loop</span>
|
|
<span class="n">waiting</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="k">return</span> <span class="n">deferred</span>
|
|
<span class="c1"># Reset waiting to initial values for next loop</span>
|
|
<span class="n">waiting</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">waiting</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="n">result</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
|
|
<span class="nd">@deprecated</span><span class="p">(</span><span class="n">Version</span><span class="p">(</span><span class="s2">"Twisted"</span><span class="p">,</span> <span class="mi">15</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="s2">"twisted.internet.defer.inlineCallbacks"</span><span class="p">)</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">deferredGenerator</span><span class="p">(</span>
|
|
<span class="n">f</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">_DeferableGenerator</span><span class="p">]</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">Deferred</span><span class="p">[</span><span class="nb">object</span><span class="p">]]:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> L{deferredGenerator} and L{waitForDeferred} help you write</span>
|
|
<span class="sd"> L{Deferred}-using code that looks like a regular sequential function.</span>
|
|
<span class="sd"> Consider the use of L{inlineCallbacks} instead, which can accomplish</span>
|
|
<span class="sd"> the same thing in a more concise manner.</span>
|
|
|
|
<span class="sd"> There are two important functions involved: L{waitForDeferred}, and</span>
|
|
<span class="sd"> L{deferredGenerator}. They are used together, like this::</span>
|
|
|
|
<span class="sd"> @deferredGenerator</span>
|
|
<span class="sd"> def thingummy():</span>
|
|
<span class="sd"> thing = waitForDeferred(makeSomeRequestResultingInDeferred())</span>
|
|
<span class="sd"> yield thing</span>
|
|
<span class="sd"> thing = thing.getResult()</span>
|
|
<span class="sd"> print(thing) #the result! hoorj!</span>
|
|
|
|
<span class="sd"> L{waitForDeferred} returns something that you should immediately yield; when</span>
|
|
<span class="sd"> your generator is resumed, calling C{thing.getResult()} will either give you</span>
|
|
<span class="sd"> the result of the L{Deferred} if it was a success, or raise an exception if it</span>
|
|
<span class="sd"> was a failure. Calling C{getResult} is B{absolutely mandatory}. If you do</span>
|
|
<span class="sd"> not call it, I{your program will not work}.</span>
|
|
|
|
<span class="sd"> L{deferredGenerator} takes one of these waitForDeferred-using generator</span>
|
|
<span class="sd"> functions and converts it into a function that returns a L{Deferred}. The</span>
|
|
<span class="sd"> result of the L{Deferred} will be the last value that your generator yielded</span>
|
|
<span class="sd"> unless the last value is a L{waitForDeferred} instance, in which case the</span>
|
|
<span class="sd"> result will be L{None}. If the function raises an unhandled exception, the</span>
|
|
<span class="sd"> L{Deferred} will errback instead. Remember that C{return result} won't work;</span>
|
|
<span class="sd"> use C{yield result; return} in place of that.</span>
|
|
|
|
<span class="sd"> Note that not yielding anything from your generator will make the L{Deferred}</span>
|
|
<span class="sd"> result in L{None}. Yielding a L{Deferred} from your generator is also an error</span>
|
|
<span class="sd"> condition; always yield C{waitForDeferred(d)} instead.</span>
|
|
|
|
<span class="sd"> The L{Deferred} returned from your deferred generator may also errback if your</span>
|
|
<span class="sd"> generator raised an exception. For example::</span>
|
|
|
|
<span class="sd"> @deferredGenerator</span>
|
|
<span class="sd"> def thingummy():</span>
|
|
<span class="sd"> thing = waitForDeferred(makeSomeRequestResultingInDeferred())</span>
|
|
<span class="sd"> yield thing</span>
|
|
<span class="sd"> thing = thing.getResult()</span>
|
|
<span class="sd"> if thing == 'I love Twisted':</span>
|
|
<span class="sd"> # will become the result of the Deferred</span>
|
|
<span class="sd"> yield 'TWISTED IS GREAT!'</span>
|
|
<span class="sd"> return</span>
|
|
<span class="sd"> else:</span>
|
|
<span class="sd"> # will trigger an errback</span>
|
|
<span class="sd"> raise Exception('DESTROY ALL LIFE')</span>
|
|
|
|
<span class="sd"> Put succinctly, these functions connect deferred-using code with this 'fake</span>
|
|
<span class="sd"> blocking' style in both directions: L{waitForDeferred} converts from a</span>
|
|
<span class="sd"> L{Deferred} to the 'blocking' style, and L{deferredGenerator} converts from the</span>
|
|
<span class="sd"> 'blocking' style to a L{Deferred}.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="nd">@wraps</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">unwindGenerator</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="nb">object</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="nb">object</span><span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="nb">object</span><span class="p">]:</span>
|
|
<span class="k">return</span> <span class="n">_deferGenerator</span><span class="p">(</span><span class="n">f</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">),</span> <span class="n">Deferred</span><span class="p">())</span>
|
|
|
|
<span class="k">return</span> <span class="n">unwindGenerator</span>
|
|
|
|
|
|
<span class="c1">## inlineCallbacks</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">_DefGen_Return</span><span class="p">(</span><span class="ne">BaseException</span><span class="p">):</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">:</span> <span class="nb">object</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">value</span>
|
|
|
|
|
|
<span class="nd">@deprecated</span><span class="p">(</span>
|
|
<span class="n">Version</span><span class="p">(</span><span class="s2">"Twisted"</span><span class="p">,</span> <span class="mi">24</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span>
|
|
<span class="n">replacement</span><span class="o">=</span><span class="s2">"standard return statement"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">returnValue</span><span class="p">(</span><span class="n">val</span><span class="p">:</span> <span class="nb">object</span><span class="p">)</span> <span class="o">-></span> <span class="n">NoReturn</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Return val from a L{inlineCallbacks} generator.</span>
|
|
|
|
<span class="sd"> Note: this is currently implemented by raising an exception</span>
|
|
<span class="sd"> derived from L{BaseException}. You might want to change any</span>
|
|
<span class="sd"> 'except:' clauses to an 'except Exception:' clause so as not to</span>
|
|
<span class="sd"> catch this exception.</span>
|
|
|
|
<span class="sd"> Also: while this function currently will work when called from</span>
|
|
<span class="sd"> within arbitrary functions called from within the generator, do</span>
|
|
<span class="sd"> not rely upon this behavior.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">raise</span> <span class="n">_DefGen_Return</span><span class="p">(</span><span class="n">val</span><span class="p">)</span>
|
|
|
|
|
|
<span class="nd">@attr</span><span class="o">.</span><span class="n">s</span><span class="p">(</span><span class="n">auto_attribs</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">_CancellationStatus</span><span class="p">(</span><span class="n">Generic</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">]):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Cancellation status of an L{inlineCallbacks} invocation.</span>
|
|
|
|
<span class="sd"> @ivar deferred: the L{Deferred} to callback or errback when the generator</span>
|
|
<span class="sd"> invocation has finished.</span>
|
|
<span class="sd"> @ivar waitingOn: the L{Deferred} being waited upon (which</span>
|
|
<span class="sd"> L{_inlineCallbacks} must fill out before returning)</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">deferred</span><span class="p">:</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">]</span>
|
|
<span class="n">waitingOn</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">_SelfResultT</span><span class="p">]]</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_gotResultInlineCallbacks</span><span class="p">(</span>
|
|
<span class="n">r</span><span class="p">:</span> <span class="nb">object</span><span class="p">,</span>
|
|
<span class="n">waiting</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">],</span>
|
|
<span class="n">gen</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span>
|
|
<span class="n">Generator</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">Any</span><span class="p">],</span> <span class="n">Any</span><span class="p">,</span> <span class="n">_T</span><span class="p">],</span>
|
|
<span class="n">Coroutine</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">Any</span><span class="p">],</span> <span class="n">Any</span><span class="p">,</span> <span class="n">_T</span><span class="p">],</span>
|
|
<span class="p">],</span>
|
|
<span class="n">status</span><span class="p">:</span> <span class="n">_CancellationStatus</span><span class="p">[</span><span class="n">_T</span><span class="p">],</span>
|
|
<span class="n">context</span><span class="p">:</span> <span class="n">_Context</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Helper for L{_inlineCallbacks} to handle a nested L{Deferred} firing.</span>
|
|
|
|
<span class="sd"> @param r: The result of the L{Deferred}</span>
|
|
<span class="sd"> @param waiting: Whether the L{_inlineCallbacks} was waiting, and the result.</span>
|
|
<span class="sd"> @param gen: a generator object returned by calling a function or method</span>
|
|
<span class="sd"> decorated with C{@}L{inlineCallbacks}</span>
|
|
<span class="sd"> @param status: a L{_CancellationStatus} tracking the current status of C{gen}</span>
|
|
<span class="sd"> @param context: the contextvars context to run `gen` in</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="n">waiting</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
|
|
<span class="n">waiting</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="n">waiting</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">r</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">_inlineCallbacks</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">gen</span><span class="p">,</span> <span class="n">status</span><span class="p">,</span> <span class="n">context</span><span class="p">)</span>
|
|
|
|
|
|
<span class="nd">@_extraneous</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_inlineCallbacks</span><span class="p">(</span>
|
|
<span class="n">result</span><span class="p">:</span> <span class="nb">object</span><span class="p">,</span>
|
|
<span class="n">gen</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span>
|
|
<span class="n">Generator</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">Any</span><span class="p">],</span> <span class="n">Any</span><span class="p">,</span> <span class="n">_T</span><span class="p">],</span>
|
|
<span class="n">Coroutine</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">Any</span><span class="p">],</span> <span class="n">Any</span><span class="p">,</span> <span class="n">_T</span><span class="p">],</span>
|
|
<span class="p">],</span>
|
|
<span class="n">status</span><span class="p">:</span> <span class="n">_CancellationStatus</span><span class="p">[</span><span class="n">_T</span><span class="p">],</span>
|
|
<span class="n">context</span><span class="p">:</span> <span class="n">_Context</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Carry out the work of L{inlineCallbacks}.</span>
|
|
|
|
<span class="sd"> Iterate the generator produced by an C{@}L{inlineCallbacks}-decorated</span>
|
|
<span class="sd"> function, C{gen}, C{send()}ing it the results of each value C{yield}ed by</span>
|
|
<span class="sd"> that generator, until a L{Deferred} is yielded, at which point a callback</span>
|
|
<span class="sd"> is added to that L{Deferred} to call this function again.</span>
|
|
|
|
<span class="sd"> @param result: The last result seen by this generator. Note that this is</span>
|
|
<span class="sd"> never a L{Deferred} - by the time this function is invoked, the</span>
|
|
<span class="sd"> L{Deferred} has been called back and this will be a particular result</span>
|
|
<span class="sd"> at a point in its callback chain.</span>
|
|
|
|
<span class="sd"> @param gen: a generator object returned by calling a function or method</span>
|
|
<span class="sd"> decorated with C{@}L{inlineCallbacks}</span>
|
|
|
|
<span class="sd"> @param status: a L{_CancellationStatus} tracking the current status of C{gen}</span>
|
|
|
|
<span class="sd"> @param context: the contextvars context to run `gen` in</span>
|
|
<span class="sd"> """</span>
|
|
<span class="c1"># This function is complicated by the need to prevent unbounded recursion</span>
|
|
<span class="c1"># arising from repeatedly yielding immediately ready deferreds. This while</span>
|
|
<span class="c1"># loop and the waiting variable solve that by manually unfolding the</span>
|
|
<span class="c1"># recursion.</span>
|
|
|
|
<span class="c1"># waiting for result? # result</span>
|
|
<span class="n">waiting</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="kc">True</span><span class="p">,</span> <span class="kc">None</span><span class="p">]</span>
|
|
|
|
<span class="n">stopIteration</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="n">callbackValue</span><span class="p">:</span> <span class="n">Any</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="k">while</span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="c1"># Send the last result back as the result of the yield expression.</span>
|
|
<span class="n">isFailure</span> <span class="o">=</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">Failure</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">isFailure</span><span class="p">:</span>
|
|
<span class="n">result</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">run</span><span class="p">(</span>
|
|
<span class="n">cast</span><span class="p">(</span><span class="n">Failure</span><span class="p">,</span> <span class="n">result</span><span class="p">)</span><span class="o">.</span><span class="n">throwExceptionIntoGenerator</span><span class="p">,</span> <span class="n">gen</span>
|
|
<span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">result</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">gen</span><span class="o">.</span><span class="n">send</span><span class="p">,</span> <span class="n">result</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">StopIteration</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
|
<span class="c1"># fell off the end, or "return" statement</span>
|
|
<span class="n">stopIteration</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">callbackValue</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="s2">"value"</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
|
|
|
<span class="k">except</span> <span class="n">_DefGen_Return</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
|
<span class="c1"># returnValue() was called; time to give a result to the original</span>
|
|
<span class="c1"># Deferred. First though, let's try to identify the potentially</span>
|
|
<span class="c1"># confusing situation which results when returnValue() is</span>
|
|
<span class="c1"># accidentally invoked from a different function, one that wasn't</span>
|
|
<span class="c1"># decorated with @inlineCallbacks.</span>
|
|
|
|
<span class="c1"># The traceback starts in this frame (the one for</span>
|
|
<span class="c1"># _inlineCallbacks); the next one down should be the application</span>
|
|
<span class="c1"># code.</span>
|
|
<span class="n">excInfo</span> <span class="o">=</span> <span class="n">exc_info</span><span class="p">()</span>
|
|
<span class="k">assert</span> <span class="n">excInfo</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
|
|
<span class="n">traceback</span> <span class="o">=</span> <span class="n">excInfo</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
|
<span class="k">assert</span> <span class="n">traceback</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
|
|
<span class="n">appCodeTrace</span> <span class="o">=</span> <span class="n">traceback</span><span class="o">.</span><span class="n">tb_next</span>
|
|
<span class="k">assert</span> <span class="n">appCodeTrace</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
|
|
<span class="k">if</span> <span class="n">_oldPypyStack</span><span class="p">:</span>
|
|
<span class="c1"># PyPy versions through 7.3.13 add an extra frame; 7.3.14 fixed</span>
|
|
<span class="c1"># this discrepancy with CPython. This code can be removed once</span>
|
|
<span class="c1"># we no longer need to support PyPy 7.3.13 or older.</span>
|
|
<span class="n">appCodeTrace</span> <span class="o">=</span> <span class="n">appCodeTrace</span><span class="o">.</span><span class="n">tb_next</span>
|
|
<span class="k">assert</span> <span class="n">appCodeTrace</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
|
|
<span class="k">if</span> <span class="n">isFailure</span><span class="p">:</span>
|
|
<span class="c1"># If we invoked this generator frame by throwing an exception</span>
|
|
<span class="c1"># into it, then throwExceptionIntoGenerator will consume an</span>
|
|
<span class="c1"># additional stack frame itself, so we need to skip that too.</span>
|
|
<span class="n">appCodeTrace</span> <span class="o">=</span> <span class="n">appCodeTrace</span><span class="o">.</span><span class="n">tb_next</span>
|
|
<span class="k">assert</span> <span class="n">appCodeTrace</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
|
|
<span class="c1"># Now that we've identified the frame being exited by the</span>
|
|
<span class="c1"># exception, let's figure out if returnValue was called from it</span>
|
|
<span class="c1"># directly. returnValue itself consumes a stack frame, so the</span>
|
|
<span class="c1"># application code will have a tb_next, but it will *not* have a</span>
|
|
<span class="c1"># second tb_next.</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># Note that there's one additional level due to returnValue being</span>
|
|
<span class="c1"># deprecated</span>
|
|
<span class="k">assert</span> <span class="n">appCodeTrace</span><span class="o">.</span><span class="n">tb_next</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
<span class="k">assert</span> <span class="n">appCodeTrace</span><span class="o">.</span><span class="n">tb_next</span><span class="o">.</span><span class="n">tb_next</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
<span class="k">if</span> <span class="n">appCodeTrace</span><span class="o">.</span><span class="n">tb_next</span><span class="o">.</span><span class="n">tb_next</span><span class="o">.</span><span class="n">tb_next</span><span class="p">:</span>
|
|
<span class="c1"># If returnValue was invoked non-local to the frame which it is</span>
|
|
<span class="c1"># exiting, identify the frame that ultimately invoked</span>
|
|
<span class="c1"># returnValue so that we can warn the user, as this behavior is</span>
|
|
<span class="c1"># confusing.</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># Note that there's one additional level due to returnValue being</span>
|
|
<span class="c1"># deprecated</span>
|
|
<span class="n">ultimateTrace</span> <span class="o">=</span> <span class="n">appCodeTrace</span>
|
|
|
|
<span class="k">assert</span> <span class="n">ultimateTrace</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
<span class="k">assert</span> <span class="n">ultimateTrace</span><span class="o">.</span><span class="n">tb_next</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
|
|
<span class="c1"># Note that there's one additional level due to returnValue being</span>
|
|
<span class="c1"># deprecated</span>
|
|
<span class="k">assert</span> <span class="n">ultimateTrace</span><span class="o">.</span><span class="n">tb_next</span><span class="o">.</span><span class="n">tb_next</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
<span class="k">while</span> <span class="n">ultimateTrace</span><span class="o">.</span><span class="n">tb_next</span><span class="o">.</span><span class="n">tb_next</span><span class="o">.</span><span class="n">tb_next</span><span class="p">:</span>
|
|
<span class="n">ultimateTrace</span> <span class="o">=</span> <span class="n">ultimateTrace</span><span class="o">.</span><span class="n">tb_next</span>
|
|
<span class="k">assert</span> <span class="n">ultimateTrace</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
|
|
<span class="n">filename</span> <span class="o">=</span> <span class="n">ultimateTrace</span><span class="o">.</span><span class="n">tb_frame</span><span class="o">.</span><span class="n">f_code</span><span class="o">.</span><span class="n">co_filename</span>
|
|
<span class="n">lineno</span> <span class="o">=</span> <span class="n">ultimateTrace</span><span class="o">.</span><span class="n">tb_lineno</span>
|
|
|
|
<span class="k">assert</span> <span class="n">ultimateTrace</span><span class="o">.</span><span class="n">tb_frame</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
<span class="k">assert</span> <span class="n">appCodeTrace</span><span class="o">.</span><span class="n">tb_frame</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
<span class="n">warnings</span><span class="o">.</span><span class="n">warn_explicit</span><span class="p">(</span>
|
|
<span class="s2">"returnValue() in </span><span class="si">%r</span><span class="s2"> causing </span><span class="si">%r</span><span class="s2"> to exit: "</span>
|
|
<span class="s2">"returnValue should only be invoked by functions decorated "</span>
|
|
<span class="s2">"with inlineCallbacks"</span>
|
|
<span class="o">%</span> <span class="p">(</span>
|
|
<span class="n">ultimateTrace</span><span class="o">.</span><span class="n">tb_frame</span><span class="o">.</span><span class="n">f_code</span><span class="o">.</span><span class="n">co_name</span><span class="p">,</span>
|
|
<span class="n">appCodeTrace</span><span class="o">.</span><span class="n">tb_frame</span><span class="o">.</span><span class="n">f_code</span><span class="o">.</span><span class="n">co_name</span><span class="p">,</span>
|
|
<span class="p">),</span>
|
|
<span class="ne">DeprecationWarning</span><span class="p">,</span>
|
|
<span class="n">filename</span><span class="p">,</span>
|
|
<span class="n">lineno</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="n">stopIteration</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">callbackValue</span> <span class="o">=</span> <span class="n">e</span><span class="o">.</span><span class="n">value</span>
|
|
|
|
<span class="k">except</span> <span class="ne">BaseException</span><span class="p">:</span>
|
|
<span class="n">status</span><span class="o">.</span><span class="n">deferred</span><span class="o">.</span><span class="n">errback</span><span class="p">()</span>
|
|
<span class="k">return</span>
|
|
|
|
<span class="k">if</span> <span class="n">stopIteration</span><span class="p">:</span>
|
|
<span class="c1"># Call the callback outside of the exception handler to avoid inappropriate/confusing</span>
|
|
<span class="c1"># "During handling of the above exception, another exception occurred:" if the callback</span>
|
|
<span class="c1"># itself throws an exception.</span>
|
|
<span class="n">status</span><span class="o">.</span><span class="n">deferred</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="n">callbackValue</span><span class="p">)</span>
|
|
<span class="k">return</span>
|
|
|
|
<span class="n">isDeferred</span> <span class="o">=</span> <span class="nb">type</span><span class="p">(</span><span class="n">result</span><span class="p">)</span> <span class="ow">in</span> <span class="n">_DEFERRED_SUBCLASSES</span>
|
|
<span class="c1"># iscoroutine() is pretty expensive in this context, so avoid calling</span>
|
|
<span class="c1"># it unnecessarily:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">isDeferred</span> <span class="ow">and</span> <span class="p">(</span><span class="n">iscoroutine</span><span class="p">(</span><span class="n">result</span><span class="p">)</span> <span class="ow">or</span> <span class="n">inspect</span><span class="o">.</span><span class="n">isgenerator</span><span class="p">(</span><span class="n">result</span><span class="p">)):</span>
|
|
<span class="n">result</span> <span class="o">=</span> <span class="n">_cancellableInlineCallbacks</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
|
|
<span class="n">isDeferred</span> <span class="o">=</span> <span class="kc">True</span>
|
|
|
|
<span class="k">if</span> <span class="n">isDeferred</span><span class="p">:</span>
|
|
<span class="c1"># We don't cast() to Deferred because that does more work in the hot path</span>
|
|
|
|
<span class="c1"># a deferred was yielded, get the result.</span>
|
|
<span class="n">result</span><span class="o">.</span><span class="n">addBoth</span><span class="p">(</span><span class="n">_gotResultInlineCallbacks</span><span class="p">,</span> <span class="n">waiting</span><span class="p">,</span> <span class="n">gen</span><span class="p">,</span> <span class="n">status</span><span class="p">,</span> <span class="n">context</span><span class="p">)</span> <span class="c1"># type: ignore[attr-defined]</span>
|
|
<span class="k">if</span> <span class="n">waiting</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
|
|
<span class="c1"># Haven't called back yet, set flag so that we get reinvoked</span>
|
|
<span class="c1"># and return from the loop</span>
|
|
<span class="n">waiting</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="n">status</span><span class="o">.</span><span class="n">waitingOn</span> <span class="o">=</span> <span class="n">result</span> <span class="c1"># type: ignore[assignment]</span>
|
|
<span class="k">return</span>
|
|
|
|
<span class="n">result</span> <span class="o">=</span> <span class="n">waiting</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
|
<span class="c1"># Reset waiting to initial values for next loop. gotResult uses</span>
|
|
<span class="c1"># waiting, but this isn't a problem because gotResult is only</span>
|
|
<span class="c1"># executed once, and if it hasn't been executed yet, the return</span>
|
|
<span class="c1"># branch above would have been taken.</span>
|
|
|
|
<span class="n">waiting</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">waiting</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_addCancelCallbackToDeferred</span><span class="p">(</span>
|
|
<span class="n">it</span><span class="p">:</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">],</span> <span class="n">status</span><span class="p">:</span> <span class="n">_CancellationStatus</span><span class="p">[</span><span class="n">_T</span><span class="p">]</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Helper for L{_cancellableInlineCallbacks} to add</span>
|
|
<span class="sd"> L{_handleCancelInlineCallbacks} as the first errback.</span>
|
|
|
|
<span class="sd"> @param it: The L{Deferred} to add the errback to.</span>
|
|
<span class="sd"> @param status: a L{_CancellationStatus} tracking the current status of C{gen}</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">it</span><span class="o">.</span><span class="n">callbacks</span><span class="p">,</span> <span class="n">tmp</span> <span class="o">=</span> <span class="p">[],</span> <span class="n">it</span><span class="o">.</span><span class="n">callbacks</span>
|
|
<span class="n">it</span> <span class="o">=</span> <span class="n">it</span><span class="o">.</span><span class="n">addErrback</span><span class="p">(</span><span class="n">_handleCancelInlineCallbacks</span><span class="p">,</span> <span class="n">status</span><span class="p">)</span>
|
|
<span class="n">it</span><span class="o">.</span><span class="n">callbacks</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">tmp</span><span class="p">)</span>
|
|
<span class="n">it</span><span class="o">.</span><span class="n">errback</span><span class="p">(</span><span class="n">_InternalInlineCallbacksCancelledError</span><span class="p">())</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_handleCancelInlineCallbacks</span><span class="p">(</span>
|
|
<span class="n">result</span><span class="p">:</span> <span class="n">Failure</span><span class="p">,</span> <span class="n">status</span><span class="p">:</span> <span class="n">_CancellationStatus</span><span class="p">[</span><span class="n">_T</span><span class="p">],</span> <span class="o">/</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">]:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Propagate the cancellation of an C{@}L{inlineCallbacks} to the</span>
|
|
<span class="sd"> L{Deferred} it is waiting on.</span>
|
|
|
|
<span class="sd"> @param result: An L{_InternalInlineCallbacksCancelledError} from</span>
|
|
<span class="sd"> C{cancel()}.</span>
|
|
<span class="sd"> @param status: a L{_CancellationStatus} tracking the current status of C{gen}</span>
|
|
<span class="sd"> @return: A new L{Deferred} that the C{@}L{inlineCallbacks} generator</span>
|
|
<span class="sd"> can callback or errback through.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">result</span><span class="o">.</span><span class="n">trap</span><span class="p">(</span><span class="n">_InternalInlineCallbacksCancelledError</span><span class="p">)</span>
|
|
<span class="n">status</span><span class="o">.</span><span class="n">deferred</span> <span class="o">=</span> <span class="n">Deferred</span><span class="p">(</span><span class="k">lambda</span> <span class="n">d</span><span class="p">:</span> <span class="n">_addCancelCallbackToDeferred</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">status</span><span class="p">))</span>
|
|
|
|
<span class="c1"># We would only end up here if the inlineCallback is waiting on</span>
|
|
<span class="c1"># another Deferred. It needs to be cancelled.</span>
|
|
<span class="n">awaited</span> <span class="o">=</span> <span class="n">status</span><span class="o">.</span><span class="n">waitingOn</span>
|
|
<span class="k">assert</span> <span class="n">awaited</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
<span class="n">awaited</span><span class="o">.</span><span class="n">cancel</span><span class="p">()</span>
|
|
|
|
<span class="k">return</span> <span class="n">status</span><span class="o">.</span><span class="n">deferred</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_cancellableInlineCallbacks</span><span class="p">(</span>
|
|
<span class="n">gen</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span>
|
|
<span class="n">Generator</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">Any</span><span class="p">],</span> <span class="nb">object</span><span class="p">,</span> <span class="n">_T</span><span class="p">],</span>
|
|
<span class="n">Coroutine</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">Any</span><span class="p">],</span> <span class="nb">object</span><span class="p">,</span> <span class="n">_T</span><span class="p">],</span>
|
|
<span class="p">]</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">]:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Make an C{@}L{inlineCallbacks} cancellable.</span>
|
|
|
|
<span class="sd"> @param gen: a generator object returned by calling a function or method</span>
|
|
<span class="sd"> decorated with C{@}L{inlineCallbacks}</span>
|
|
|
|
<span class="sd"> @return: L{Deferred} for the C{@}L{inlineCallbacks} that is cancellable.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">deferred</span><span class="p">:</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">]</span> <span class="o">=</span> <span class="n">Deferred</span><span class="p">(</span><span class="k">lambda</span> <span class="n">d</span><span class="p">:</span> <span class="n">_addCancelCallbackToDeferred</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">status</span><span class="p">))</span>
|
|
<span class="n">status</span> <span class="o">=</span> <span class="n">_CancellationStatus</span><span class="p">(</span><span class="n">deferred</span><span class="p">)</span>
|
|
|
|
<span class="n">_inlineCallbacks</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="n">gen</span><span class="p">,</span> <span class="n">status</span><span class="p">,</span> <span class="n">_copy_context</span><span class="p">())</span>
|
|
|
|
<span class="k">return</span> <span class="n">deferred</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">_InternalInlineCallbacksCancelledError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> A unique exception used only in L{_cancellableInlineCallbacks} to verify</span>
|
|
<span class="sd"> that an L{inlineCallbacks} is being cancelled as expected.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
|
|
<div class="viewcode-block" id="inlineCallbacks">
|
|
<a class="viewcode-back" href="../../../api/evennia.commands.cmdhandler.html#evennia.commands.cmdhandler.inlineCallbacks">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">inlineCallbacks</span><span class="p">(</span>
|
|
<span class="n">f</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">_P</span><span class="p">,</span> <span class="n">Generator</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">Any</span><span class="p">],</span> <span class="n">Any</span><span class="p">,</span> <span class="n">_T</span><span class="p">]]</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Callable</span><span class="p">[</span><span class="n">_P</span><span class="p">,</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">]]:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> L{inlineCallbacks} helps you write L{Deferred}-using code that looks like a</span>
|
|
<span class="sd"> regular sequential function. For example::</span>
|
|
|
|
<span class="sd"> @inlineCallbacks</span>
|
|
<span class="sd"> def thingummy():</span>
|
|
<span class="sd"> thing = yield makeSomeRequestResultingInDeferred()</span>
|
|
<span class="sd"> print(thing) # the result! hoorj!</span>
|
|
|
|
<span class="sd"> When you call anything that results in a L{Deferred}, you can simply yield it;</span>
|
|
<span class="sd"> your generator will automatically be resumed when the Deferred's result is</span>
|
|
<span class="sd"> available. The generator will be sent the result of the L{Deferred} with the</span>
|
|
<span class="sd"> 'send' method on generators, or if the result was a failure, 'throw'.</span>
|
|
|
|
<span class="sd"> Things that are not L{Deferred}s may also be yielded, and your generator</span>
|
|
<span class="sd"> will be resumed with the same object sent back. This means C{yield}</span>
|
|
<span class="sd"> performs an operation roughly equivalent to L{maybeDeferred}.</span>
|
|
|
|
<span class="sd"> Your inlineCallbacks-enabled generator will return a L{Deferred} object, which</span>
|
|
<span class="sd"> will result in the return value of the generator (or will fail with a</span>
|
|
<span class="sd"> failure object if your generator raises an unhandled exception). Inside</span>
|
|
<span class="sd"> the generator simply use C{return result} to return a value.</span>
|
|
|
|
<span class="sd"> Be aware that generator must not return a L{Deferred}.</span>
|
|
<span class="sd"> If you believe the thing you'd like to return could be a L{Deferred}, do</span>
|
|
<span class="sd"> this::</span>
|
|
|
|
<span class="sd"> result = yield result</span>
|
|
<span class="sd"> return result</span>
|
|
|
|
<span class="sd"> The L{Deferred} returned from your deferred generator may errback if your</span>
|
|
<span class="sd"> generator raised an exception::</span>
|
|
|
|
<span class="sd"> @inlineCallbacks</span>
|
|
<span class="sd"> def thingummy():</span>
|
|
<span class="sd"> thing = yield makeSomeRequestResultingInDeferred()</span>
|
|
<span class="sd"> if thing == 'I love Twisted':</span>
|
|
<span class="sd"> # will become the result of the Deferred</span>
|
|
<span class="sd"> return 'TWISTED IS GREAT!'</span>
|
|
<span class="sd"> else:</span>
|
|
<span class="sd"> # will trigger an errback</span>
|
|
<span class="sd"> raise Exception('DESTROY ALL LIFE')</span>
|
|
|
|
<span class="sd"> You can cancel the L{Deferred} returned from your L{inlineCallbacks}</span>
|
|
<span class="sd"> generator before it is fired by your generator completing (either by</span>
|
|
<span class="sd"> reaching its end, a C{return} statement, or by calling L{returnValue}).</span>
|
|
<span class="sd"> A C{CancelledError} will be raised from the C{yield}ed L{Deferred} that</span>
|
|
<span class="sd"> has been cancelled if that C{Deferred} does not otherwise suppress it.</span>
|
|
|
|
<span class="sd"> C{inlineCallbacks} behaves very similarly to coroutines. Since Twisted 24.7.0</span>
|
|
<span class="sd"> it is possible to rewrite functions using C{inlineCallbacks} to C{async def}</span>
|
|
<span class="sd"> in piecewise manner and be mostly compatible to existing code.</span>
|
|
|
|
<span class="sd"> The rewrite process is simply replacing C{inlineCallbacks} decorator with</span>
|
|
<span class="sd"> C{async def} and all C{yield} occurrences in the function body with C{await}.</span>
|
|
<span class="sd"> The function will no longer return a C{Deferred} but a awaitable coroutine.</span>
|
|
<span class="sd"> This return value will obviously not have C{Deferred} methods such as</span>
|
|
<span class="sd"> C{addCallback}, but it will be possible to C{yield} it in other code based</span>
|
|
<span class="sd"> on C{inlineCallbacks}.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="nd">@wraps</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">unwindGenerator</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">]:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">gen</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="n">_DefGen_Return</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span>
|
|
<span class="s2">"inlineCallbacks requires </span><span class="si">%r</span><span class="s2"> to produce a generator; instead"</span>
|
|
<span class="s2">"caught returnValue being used in a non-generator"</span> <span class="o">%</span> <span class="p">(</span><span class="n">f</span><span class="p">,)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">gen</span><span class="p">,</span> <span class="n">GeneratorType</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span>
|
|
<span class="s2">"inlineCallbacks requires </span><span class="si">%r</span><span class="s2"> to produce a generator; "</span>
|
|
<span class="s2">"instead got </span><span class="si">%r</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">gen</span><span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">_cancellableInlineCallbacks</span><span class="p">(</span><span class="n">gen</span><span class="p">)</span>
|
|
|
|
<span class="k">return</span> <span class="n">unwindGenerator</span></div>
|
|
|
|
|
|
|
|
<span class="c1">## DeferredLock/DeferredQueue</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">_ConcurrencyPrimitive</span><span class="p">(</span><span class="n">ABC</span><span class="p">):</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">:</span> <span class="n">Self</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">waiting</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">Self</span><span class="p">]]</span> <span class="o">=</span> <span class="p">[]</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_releaseAndReturn</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">r</span><span class="p">:</span> <span class="n">_T</span><span class="p">)</span> <span class="o">-></span> <span class="n">_T</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">release</span><span class="p">()</span>
|
|
<span class="k">return</span> <span class="n">r</span>
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">run</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">:</span> <span class="n">Self</span><span class="p">,</span>
|
|
<span class="o">/</span><span class="p">,</span>
|
|
<span class="n">f</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">_P</span><span class="p">,</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">]],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">]:</span>
|
|
<span class="o">...</span>
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">run</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">:</span> <span class="n">Self</span><span class="p">,</span>
|
|
<span class="o">/</span><span class="p">,</span>
|
|
<span class="n">f</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">_P</span><span class="p">,</span> <span class="n">Coroutine</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">Any</span><span class="p">],</span> <span class="n">Any</span><span class="p">,</span> <span class="n">_T</span><span class="p">]],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">]:</span>
|
|
<span class="o">...</span>
|
|
|
|
<span class="nd">@overload</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">run</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">:</span> <span class="n">Self</span><span class="p">,</span> <span class="o">/</span><span class="p">,</span> <span class="n">f</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">_P</span><span class="p">,</span> <span class="n">_T</span><span class="p">],</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">]:</span>
|
|
<span class="o">...</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">run</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">:</span> <span class="n">Self</span><span class="p">,</span>
|
|
<span class="o">/</span><span class="p">,</span>
|
|
<span class="n">f</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">_P</span><span class="p">,</span> <span class="n">Union</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">],</span> <span class="n">Coroutine</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">Any</span><span class="p">],</span> <span class="n">Any</span><span class="p">,</span> <span class="n">_T</span><span class="p">],</span> <span class="n">_T</span><span class="p">]],</span>
|
|
<span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">_P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">]:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Acquire, run, release.</span>
|
|
|
|
<span class="sd"> This method takes a callable as its first argument and any</span>
|
|
<span class="sd"> number of other positional and keyword arguments. When the</span>
|
|
<span class="sd"> lock or semaphore is acquired, the callable will be invoked</span>
|
|
<span class="sd"> with those arguments.</span>
|
|
|
|
<span class="sd"> The callable may return a L{Deferred}; if it does, the lock or</span>
|
|
<span class="sd"> semaphore won't be released until that L{Deferred} fires.</span>
|
|
|
|
<span class="sd"> @return: L{Deferred} of function result.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">execute</span><span class="p">(</span><span class="n">ignoredResult</span><span class="p">:</span> <span class="nb">object</span><span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">]:</span>
|
|
<span class="c1"># maybeDeferred arg type requires one of the possible union members</span>
|
|
<span class="c1"># and won't accept all possible union members</span>
|
|
<span class="k">return</span> <span class="n">maybeDeferred</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span><span class="o">.</span><span class="n">addBoth</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_releaseAndReturn</span>
|
|
<span class="p">)</span> <span class="c1"># type: ignore[return-value]</span>
|
|
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span><span class="o">.</span><span class="n">addCallback</span><span class="p">(</span><span class="n">execute</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__aenter__</span><span class="p">(</span><span class="bp">self</span><span class="p">:</span> <span class="n">Self</span><span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">Self</span><span class="p">]:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> We can be used as an asynchronous context manager.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__aexit__</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">__exc_type</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Type</span><span class="p">[</span><span class="ne">BaseException</span><span class="p">]],</span>
|
|
<span class="n">__exc_value</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="ne">BaseException</span><span class="p">],</span>
|
|
<span class="n">__traceback</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">TracebackType</span><span class="p">],</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">Literal</span><span class="p">[</span><span class="kc">False</span><span class="p">]]:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">release</span><span class="p">()</span>
|
|
<span class="c1"># We return False to indicate that we have not consumed the</span>
|
|
<span class="c1"># exception, if any.</span>
|
|
<span class="k">return</span> <span class="n">succeed</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
|
|
|
|
<span class="nd">@abstractmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">acquire</span><span class="p">(</span><span class="bp">self</span><span class="p">:</span> <span class="n">Self</span><span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">Self</span><span class="p">]:</span>
|
|
<span class="k">pass</span>
|
|
|
|
<span class="nd">@abstractmethod</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">release</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">pass</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">DeferredLock</span><span class="p">(</span><span class="n">_ConcurrencyPrimitive</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> A lock for event driven systems.</span>
|
|
|
|
<span class="sd"> @ivar locked: C{True} when this Lock has been acquired, false at all other</span>
|
|
<span class="sd"> times. Do not change this value, but it is useful to examine for the</span>
|
|
<span class="sd"> equivalent of a "non-blocking" acquisition.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">locked</span> <span class="o">=</span> <span class="kc">False</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_cancelAcquire</span><span class="p">(</span><span class="bp">self</span><span class="p">:</span> <span class="n">Self</span><span class="p">,</span> <span class="n">d</span><span class="p">:</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">Self</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Remove a deferred d from our waiting list, as the deferred has been</span>
|
|
<span class="sd"> canceled.</span>
|
|
|
|
<span class="sd"> Note: We do not need to wrap this in a try/except to catch d not</span>
|
|
<span class="sd"> being in self.waiting because this canceller will not be called if</span>
|
|
<span class="sd"> d has fired. release() pops a deferred out of self.waiting and</span>
|
|
<span class="sd"> calls it, so the canceller will no longer be called.</span>
|
|
|
|
<span class="sd"> @param d: The deferred that has been canceled.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">waiting</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">acquire</span><span class="p">(</span><span class="bp">self</span><span class="p">:</span> <span class="n">Self</span><span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">Self</span><span class="p">]:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Attempt to acquire the lock. Returns a L{Deferred} that fires on</span>
|
|
<span class="sd"> lock acquisition with the L{DeferredLock} as the value. If the lock</span>
|
|
<span class="sd"> is locked, then the Deferred is placed at the end of a waiting list.</span>
|
|
|
|
<span class="sd"> @return: a L{Deferred} which fires on lock acquisition.</span>
|
|
<span class="sd"> @rtype: a L{Deferred}</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">d</span><span class="p">:</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">Self</span><span class="p">]</span> <span class="o">=</span> <span class="n">Deferred</span><span class="p">(</span><span class="n">canceller</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_cancelAcquire</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">locked</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">waiting</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">locked</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">d</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">d</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">release</span><span class="p">(</span><span class="bp">self</span><span class="p">:</span> <span class="n">Self</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Release the lock. If there is a waiting list, then the first</span>
|
|
<span class="sd"> L{Deferred} in that waiting list will be called back.</span>
|
|
|
|
<span class="sd"> Should be called by whomever did the L{acquire}() when the shared</span>
|
|
<span class="sd"> resource is free.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">assert</span> <span class="bp">self</span><span class="o">.</span><span class="n">locked</span><span class="p">,</span> <span class="s2">"Tried to release an unlocked lock"</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">locked</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">waiting</span><span class="p">:</span>
|
|
<span class="c1"># someone is waiting to acquire lock</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">locked</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">d</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">waiting</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
|
|
<span class="n">d</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">DeferredSemaphore</span><span class="p">(</span><span class="n">_ConcurrencyPrimitive</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> A semaphore for event driven systems.</span>
|
|
|
|
<span class="sd"> If you are looking into this as a means of limiting parallelism, you might</span>
|
|
<span class="sd"> find L{twisted.internet.task.Cooperator} more useful.</span>
|
|
|
|
<span class="sd"> @ivar limit: At most this many users may acquire this semaphore at</span>
|
|
<span class="sd"> once.</span>
|
|
<span class="sd"> @ivar tokens: The difference between C{limit} and the number of users</span>
|
|
<span class="sd"> which have currently acquired this semaphore.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">tokens</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> @param tokens: initial value of L{tokens} and L{limit}</span>
|
|
<span class="sd"> @type tokens: L{int}</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">_ConcurrencyPrimitive</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">tokens</span> <span class="o"><</span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"DeferredSemaphore requires tokens >= 1"</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">tokens</span> <span class="o">=</span> <span class="n">tokens</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">limit</span> <span class="o">=</span> <span class="n">tokens</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_cancelAcquire</span><span class="p">(</span><span class="bp">self</span><span class="p">:</span> <span class="n">Self</span><span class="p">,</span> <span class="n">d</span><span class="p">:</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">Self</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Remove a deferred d from our waiting list, as the deferred has been</span>
|
|
<span class="sd"> canceled.</span>
|
|
|
|
<span class="sd"> Note: We do not need to wrap this in a try/except to catch d not</span>
|
|
<span class="sd"> being in self.waiting because this canceller will not be called if</span>
|
|
<span class="sd"> d has fired. release() pops a deferred out of self.waiting and</span>
|
|
<span class="sd"> calls it, so the canceller will no longer be called.</span>
|
|
|
|
<span class="sd"> @param d: The deferred that has been canceled.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">waiting</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">acquire</span><span class="p">(</span><span class="bp">self</span><span class="p">:</span> <span class="n">Self</span><span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">Self</span><span class="p">]:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Attempt to acquire the token.</span>
|
|
|
|
<span class="sd"> @return: a L{Deferred} which fires on token acquisition.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">assert</span> <span class="p">(</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">tokens</span> <span class="o">>=</span> <span class="mi">0</span>
|
|
<span class="p">),</span> <span class="s2">"Internal inconsistency?? tokens should never be negative"</span>
|
|
<span class="n">d</span><span class="p">:</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">Self</span><span class="p">]</span> <span class="o">=</span> <span class="n">Deferred</span><span class="p">(</span><span class="n">canceller</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_cancelAcquire</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">tokens</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">waiting</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">tokens</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">tokens</span> <span class="o">-</span> <span class="mi">1</span>
|
|
<span class="n">d</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">d</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">release</span><span class="p">(</span><span class="bp">self</span><span class="p">:</span> <span class="n">Self</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Release the token.</span>
|
|
|
|
<span class="sd"> Should be called by whoever did the L{acquire}() when the shared</span>
|
|
<span class="sd"> resource is free.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">assert</span> <span class="p">(</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">tokens</span> <span class="o"><</span> <span class="bp">self</span><span class="o">.</span><span class="n">limit</span>
|
|
<span class="p">),</span> <span class="s2">"Someone released me too many times: too many tokens!"</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">tokens</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">tokens</span> <span class="o">+</span> <span class="mi">1</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">waiting</span><span class="p">:</span>
|
|
<span class="c1"># someone is waiting to acquire token</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">tokens</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">tokens</span> <span class="o">-</span> <span class="mi">1</span>
|
|
<span class="n">d</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">waiting</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
|
|
<span class="n">d</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">QueueOverflow</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
|
<span class="k">pass</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">QueueUnderflow</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
|
<span class="k">pass</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">DeferredQueue</span><span class="p">(</span><span class="n">Generic</span><span class="p">[</span><span class="n">_T</span><span class="p">]):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> An event driven queue.</span>
|
|
|
|
<span class="sd"> Objects may be added as usual to this queue. When an attempt is</span>
|
|
<span class="sd"> made to retrieve an object when the queue is empty, a L{Deferred} is</span>
|
|
<span class="sd"> returned which will fire when an object becomes available.</span>
|
|
|
|
<span class="sd"> @ivar size: The maximum number of objects to allow into the queue</span>
|
|
<span class="sd"> at a time. When an attempt to add a new object would exceed this</span>
|
|
<span class="sd"> limit, L{QueueOverflow} is raised synchronously. L{None} for no limit.</span>
|
|
<span class="sd"> @ivar backlog: The maximum number of L{Deferred} gets to allow at</span>
|
|
<span class="sd"> one time. When an attempt is made to get an object which would</span>
|
|
<span class="sd"> exceed this limit, L{QueueUnderflow} is raised synchronously. L{None}</span>
|
|
<span class="sd"> for no limit.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span> <span class="n">size</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="n">backlog</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">waiting</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">]]</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">pending</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">_T</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">size</span> <span class="o">=</span> <span class="n">size</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">backlog</span> <span class="o">=</span> <span class="n">backlog</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_cancelGet</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">d</span><span class="p">:</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Remove a deferred d from our waiting list, as the deferred has been</span>
|
|
<span class="sd"> canceled.</span>
|
|
|
|
<span class="sd"> Note: We do not need to wrap this in a try/except to catch d not</span>
|
|
<span class="sd"> being in self.waiting because this canceller will not be called if</span>
|
|
<span class="sd"> d has fired. put() pops a deferred out of self.waiting and calls</span>
|
|
<span class="sd"> it, so the canceller will no longer be called.</span>
|
|
|
|
<span class="sd"> @param d: The deferred that has been canceled.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">waiting</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">put</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">:</span> <span class="n">_T</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Add an object to this queue.</span>
|
|
|
|
<span class="sd"> @raise QueueOverflow: Too many objects are in this queue.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">waiting</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">waiting</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">size</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">pending</span><span class="p">)</span> <span class="o"><</span> <span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">pending</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="n">QueueOverflow</span><span class="p">()</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">get</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">]:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Attempt to retrieve and remove an object from the queue.</span>
|
|
|
|
<span class="sd"> @return: a L{Deferred} which fires with the next object available in</span>
|
|
<span class="sd"> the queue.</span>
|
|
|
|
<span class="sd"> @raise QueueUnderflow: Too many (more than C{backlog})</span>
|
|
<span class="sd"> L{Deferred}s are already waiting for an object from this queue.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">pending</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">succeed</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">pending</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">))</span>
|
|
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">backlog</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">waiting</span><span class="p">)</span> <span class="o"><</span> <span class="bp">self</span><span class="o">.</span><span class="n">backlog</span><span class="p">:</span>
|
|
<span class="n">d</span><span class="p">:</span> <span class="n">Deferred</span><span class="p">[</span><span class="n">_T</span><span class="p">]</span> <span class="o">=</span> <span class="n">Deferred</span><span class="p">(</span><span class="n">canceller</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_cancelGet</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">waiting</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">d</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="n">QueueUnderflow</span><span class="p">()</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">AlreadyTryingToLockError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Raised when L{DeferredFilesystemLock.deferUntilLocked} is called twice on a</span>
|
|
<span class="sd"> single L{DeferredFilesystemLock}.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">DeferredFilesystemLock</span><span class="p">(</span><span class="n">lockfile</span><span class="o">.</span><span class="n">FilesystemLock</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> A L{FilesystemLock} that allows for a L{Deferred} to be fired when the lock is</span>
|
|
<span class="sd"> acquired.</span>
|
|
|
|
<span class="sd"> @ivar _scheduler: The object in charge of scheduling retries. In this</span>
|
|
<span class="sd"> implementation this is parameterized for testing.</span>
|
|
<span class="sd"> @ivar _interval: The retry interval for an L{IReactorTime} based scheduler.</span>
|
|
<span class="sd"> @ivar _tryLockCall: An L{IDelayedCall} based on C{_interval} that will manage</span>
|
|
<span class="sd"> the next retry for acquiring the lock.</span>
|
|
<span class="sd"> @ivar _timeoutCall: An L{IDelayedCall} based on C{deferUntilLocked}'s timeout</span>
|
|
<span class="sd"> argument. This is in charge of timing out our attempt to acquire the</span>
|
|
<span class="sd"> lock.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">_interval</span> <span class="o">=</span> <span class="mi">1</span>
|
|
<span class="n">_tryLockCall</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">IDelayedCall</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">_timeoutCall</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">IDelayedCall</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">scheduler</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">IReactorTime</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> @param name: The name of the lock to acquire</span>
|
|
<span class="sd"> @param scheduler: An object which provides L{IReactorTime}</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">lockfile</span><span class="o">.</span><span class="n">FilesystemLock</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">scheduler</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">twisted.internet</span><span class="w"> </span><span class="kn">import</span> <span class="n">reactor</span>
|
|
|
|
<span class="n">scheduler</span> <span class="o">=</span> <span class="n">cast</span><span class="p">(</span><span class="n">IReactorTime</span><span class="p">,</span> <span class="n">reactor</span><span class="p">)</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_scheduler</span> <span class="o">=</span> <span class="n">scheduler</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">deferUntilLocked</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">timeout</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">float</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">)</span> <span class="o">-></span> <span class="n">Deferred</span><span class="p">[</span><span class="kc">None</span><span class="p">]:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Wait until we acquire this lock. This method is not safe for</span>
|
|
<span class="sd"> concurrent use.</span>
|
|
|
|
<span class="sd"> @param timeout: the number of seconds after which to time out if the</span>
|
|
<span class="sd"> lock has not been acquired.</span>
|
|
|
|
<span class="sd"> @return: a L{Deferred} which will callback when the lock is acquired, or</span>
|
|
<span class="sd"> errback with a L{TimeoutError} after timing out or an</span>
|
|
<span class="sd"> L{AlreadyTryingToLockError} if the L{deferUntilLocked} has already</span>
|
|
<span class="sd"> been called and not successfully locked the file.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_tryLockCall</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">fail</span><span class="p">(</span>
|
|
<span class="n">AlreadyTryingToLockError</span><span class="p">(</span>
|
|
<span class="s2">"deferUntilLocked isn't safe for concurrent use."</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_cancelLock</span><span class="p">(</span><span class="n">reason</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="n">Failure</span><span class="p">,</span> <span class="ne">Exception</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Cancel a L{DeferredFilesystemLock.deferUntilLocked} call.</span>
|
|
|
|
<span class="sd"> @type reason: L{Failure}</span>
|
|
<span class="sd"> @param reason: The reason why the call is cancelled.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">assert</span> <span class="bp">self</span><span class="o">.</span><span class="n">_tryLockCall</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_tryLockCall</span><span class="o">.</span><span class="n">cancel</span><span class="p">()</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_tryLockCall</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_timeoutCall</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">_timeoutCall</span><span class="o">.</span><span class="n">active</span><span class="p">():</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_timeoutCall</span><span class="o">.</span><span class="n">cancel</span><span class="p">()</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_timeoutCall</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">lock</span><span class="p">():</span>
|
|
<span class="n">d</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">d</span><span class="o">.</span><span class="n">errback</span><span class="p">(</span><span class="n">reason</span><span class="p">)</span>
|
|
|
|
<span class="n">d</span><span class="p">:</span> <span class="n">Deferred</span><span class="p">[</span><span class="kc">None</span><span class="p">]</span> <span class="o">=</span> <span class="n">Deferred</span><span class="p">(</span><span class="k">lambda</span> <span class="n">deferred</span><span class="p">:</span> <span class="n">_cancelLock</span><span class="p">(</span><span class="n">CancelledError</span><span class="p">()))</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_tryLock</span><span class="p">()</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">lock</span><span class="p">():</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_timeoutCall</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_timeoutCall</span><span class="o">.</span><span class="n">cancel</span><span class="p">()</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_timeoutCall</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_tryLockCall</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="n">d</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">timeout</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">_timeoutCall</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">reason</span> <span class="o">=</span> <span class="n">Failure</span><span class="p">(</span>
|
|
<span class="ne">TimeoutError</span><span class="p">(</span>
|
|
<span class="s2">"Timed out acquiring lock: </span><span class="si">%s</span><span class="s2"> after </span><span class="si">%f</span><span class="s2">s"</span>
|
|
<span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">timeout</span><span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_timeoutCall</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_scheduler</span><span class="o">.</span><span class="n">callLater</span><span class="p">(</span>
|
|
<span class="n">timeout</span><span class="p">,</span> <span class="n">_cancelLock</span><span class="p">,</span> <span class="n">reason</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_tryLockCall</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_scheduler</span><span class="o">.</span><span class="n">callLater</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_interval</span><span class="p">,</span> <span class="n">_tryLock</span><span class="p">)</span>
|
|
|
|
<span class="n">_tryLock</span><span class="p">()</span>
|
|
|
|
<span class="k">return</span> <span class="n">d</span>
|
|
|
|
|
|
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="s2">"Deferred"</span><span class="p">,</span>
|
|
<span class="s2">"DeferredList"</span><span class="p">,</span>
|
|
<span class="s2">"succeed"</span><span class="p">,</span>
|
|
<span class="s2">"fail"</span><span class="p">,</span>
|
|
<span class="s2">"FAILURE"</span><span class="p">,</span>
|
|
<span class="s2">"SUCCESS"</span><span class="p">,</span>
|
|
<span class="s2">"AlreadyCalledError"</span><span class="p">,</span>
|
|
<span class="s2">"TimeoutError"</span><span class="p">,</span>
|
|
<span class="s2">"gatherResults"</span><span class="p">,</span>
|
|
<span class="s2">"maybeDeferred"</span><span class="p">,</span>
|
|
<span class="s2">"ensureDeferred"</span><span class="p">,</span>
|
|
<span class="s2">"waitForDeferred"</span><span class="p">,</span>
|
|
<span class="s2">"deferredGenerator"</span><span class="p">,</span>
|
|
<span class="s2">"inlineCallbacks"</span><span class="p">,</span>
|
|
<span class="s2">"returnValue"</span><span class="p">,</span>
|
|
<span class="s2">"DeferredLock"</span><span class="p">,</span>
|
|
<span class="s2">"DeferredSemaphore"</span><span class="p">,</span>
|
|
<span class="s2">"DeferredQueue"</span><span class="p">,</span>
|
|
<span class="s2">"DeferredFilesystemLock"</span><span class="p">,</span>
|
|
<span class="s2">"AlreadyTryingToLockError"</span><span class="p">,</span>
|
|
<span class="s2">"CancelledError"</span><span class="p">,</span>
|
|
<span class="p">]</span>
|
|
</pre></div>
|
|
|
|
<div class="clearer"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sphinxsidebar" role="navigation" aria-label="Main">
|
|
<div class="sphinxsidebarwrapper">
|
|
<p class="logo"><a href="../../../index.html">
|
|
<img class="logo" src="../../../_static/evennia_logo.png" alt="Logo of Evennia"/>
|
|
</a></p>
|
|
<search id="searchbox" style="display: none" role="search">
|
|
<h3 id="searchlabel">Quick search</h3>
|
|
<div class="searchformwrapper">
|
|
<form class="search" action="../../../search.html" method="get">
|
|
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
|
<input type="submit" value="Go" />
|
|
</form>
|
|
</div>
|
|
</search>
|
|
<script>document.getElementById('searchbox').style.display = "block"</script><h3>Links</h3>
|
|
<ul>
|
|
<li><a href="https://www.evennia.com/docs/latest/index.html">Documentation Top</a> </li>
|
|
<li><a href="https://www.evennia.com">Evennia Home</a> </li>
|
|
<li><a href="https://github.com/evennia/evennia">Github</a> </li>
|
|
<li><a href="http://games.evennia.com">Game Index</a> </li>
|
|
<li>
|
|
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
|
|
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
|
|
<a href="https://evennia.blogspot.com/">Blog</a>
|
|
</li>
|
|
</ul>
|
|
<h3>Doc Versions</h3>
|
|
<ul>
|
|
|
|
<li>
|
|
<a href="https://www.evennia.com/docs/latest/index.html">latest (main branch)</a>
|
|
</li>
|
|
|
|
|
|
<li>
|
|
<a href="https://www.evennia.com/docs/5.x/index.html">v5.0.0 branch (outdated)</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="https://www.evennia.com/docs/4.x/index.html">v4.0.0 branch (outdated)</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="https://www.evennia.com/docs/3.x/index.html">v3.0.0 branch (outdated)</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="https://www.evennia.com/docs/2.x/index.html">v2.0.0 branch (outdated)</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="https://www.evennia.com/docs/1.x/index.html">v1.0.0 branch (outdated)</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="https://www.evennia.com/docs/0.x/index.html">v0.9.5 branch (outdated)</a>
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
</div>
|
|
<div class="clearer"></div>
|
|
</div>
|
|
<div class="related" role="navigation" aria-label="Related">
|
|
<h3>Navigation</h3>
|
|
<ul>
|
|
<li class="right" style="margin-right: 10px">
|
|
<a href="../../../genindex.html" title="General Index"
|
|
>index</a></li>
|
|
<li class="right" >
|
|
<a href="../../../py-modindex.html" title="Python Module Index"
|
|
>modules</a> |</li>
|
|
<li class="nav-item nav-item-0"><a href="../../../index.html">Evennia</a> »</li>
|
|
<li class="nav-item nav-item-1"><a href="../../index.html" >Module code</a> »</li>
|
|
<li class="nav-item nav-item-this"><a href="">twisted.internet.defer</a></li>
|
|
</ul>
|
|
</div>
|
|
<div class="footer" role="contentinfo">
|
|
© Copyright 2024, The Evennia developer community.
|
|
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.2.3.
|
|
</div>
|
|
</body>
|
|
</html> |