evennia/docs/5.x/_modules/django/db/transaction.html
2025-07-01 10:01:48 +02:00

443 lines
No EOL
39 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>django.db.transaction &#8212; Evennia latest documentation</title>
<link rel="stylesheet" href="../../../_static/nature.css" type="text/css" />
<link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
<link rel="stylesheet" type="text/css" href="../../../_static/pygments.css?v=d75fae25" />
<link rel="stylesheet" type="text/css" href="../../../_static/nature.css?v=245aff17" />
<script id="documentation_options" data-url_root="../../../" src="../../../_static/documentation_options.js"></script>
<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="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
</head><body>
<div class="related" role="navigation" aria-label="related navigation">
<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 latest</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="../../index.html" accesskey="U">Module code</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">django.db.transaction</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<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>
</div>
</div>
<div class="bodywrapper">
<div class="body" role="main">
<h1>Source code for django.db.transaction</h1><div class="highlight"><pre>
<span></span><span class="kn">from</span><span class="w"> </span><span class="nn">contextlib</span><span class="w"> </span><span class="kn">import</span> <span class="n">ContextDecorator</span><span class="p">,</span> <span class="n">contextmanager</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">django.db</span><span class="w"> </span><span class="kn">import</span> <span class="p">(</span>
<span class="n">DEFAULT_DB_ALIAS</span><span class="p">,</span>
<span class="n">DatabaseError</span><span class="p">,</span>
<span class="n">Error</span><span class="p">,</span>
<span class="n">ProgrammingError</span><span class="p">,</span>
<span class="n">connections</span><span class="p">,</span>
<span class="p">)</span>
<span class="k">class</span><span class="w"> </span><span class="nc">TransactionManagementError</span><span class="p">(</span><span class="n">ProgrammingError</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Transaction management is used improperly.&quot;&quot;&quot;</span>
<span class="k">pass</span>
<span class="k">def</span><span class="w"> </span><span class="nf">get_connection</span><span class="p">(</span><span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Get a database connection by name, or the default database connection</span>
<span class="sd"> if no name is provided. This is a private API.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="n">using</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">using</span> <span class="o">=</span> <span class="n">DEFAULT_DB_ALIAS</span>
<span class="k">return</span> <span class="n">connections</span><span class="p">[</span><span class="n">using</span><span class="p">]</span>
<span class="k">def</span><span class="w"> </span><span class="nf">get_autocommit</span><span class="p">(</span><span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Get the autocommit status of the connection.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">get_connection</span><span class="p">(</span><span class="n">using</span><span class="p">)</span><span class="o">.</span><span class="n">get_autocommit</span><span class="p">()</span>
<span class="k">def</span><span class="w"> </span><span class="nf">set_autocommit</span><span class="p">(</span><span class="n">autocommit</span><span class="p">,</span> <span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Set the autocommit status of the connection.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">get_connection</span><span class="p">(</span><span class="n">using</span><span class="p">)</span><span class="o">.</span><span class="n">set_autocommit</span><span class="p">(</span><span class="n">autocommit</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">commit</span><span class="p">(</span><span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Commit a transaction.&quot;&quot;&quot;</span>
<span class="n">get_connection</span><span class="p">(</span><span class="n">using</span><span class="p">)</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
<span class="k">def</span><span class="w"> </span><span class="nf">rollback</span><span class="p">(</span><span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Roll back a transaction.&quot;&quot;&quot;</span>
<span class="n">get_connection</span><span class="p">(</span><span class="n">using</span><span class="p">)</span><span class="o">.</span><span class="n">rollback</span><span class="p">()</span>
<span class="k">def</span><span class="w"> </span><span class="nf">savepoint</span><span class="p">(</span><span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Create a savepoint (if supported and required by the backend) inside the</span>
<span class="sd"> current transaction. Return an identifier for the savepoint that will be</span>
<span class="sd"> used for the subsequent rollback or commit.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">get_connection</span><span class="p">(</span><span class="n">using</span><span class="p">)</span><span class="o">.</span><span class="n">savepoint</span><span class="p">()</span>
<span class="k">def</span><span class="w"> </span><span class="nf">savepoint_rollback</span><span class="p">(</span><span class="n">sid</span><span class="p">,</span> <span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Roll back the most recent savepoint (if one exists). Do nothing if</span>
<span class="sd"> savepoints are not supported.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">get_connection</span><span class="p">(</span><span class="n">using</span><span class="p">)</span><span class="o">.</span><span class="n">savepoint_rollback</span><span class="p">(</span><span class="n">sid</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">savepoint_commit</span><span class="p">(</span><span class="n">sid</span><span class="p">,</span> <span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Commit the most recent savepoint (if one exists). Do nothing if</span>
<span class="sd"> savepoints are not supported.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">get_connection</span><span class="p">(</span><span class="n">using</span><span class="p">)</span><span class="o">.</span><span class="n">savepoint_commit</span><span class="p">(</span><span class="n">sid</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">clean_savepoints</span><span class="p">(</span><span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Reset the counter used to generate unique savepoint ids in this thread.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">get_connection</span><span class="p">(</span><span class="n">using</span><span class="p">)</span><span class="o">.</span><span class="n">clean_savepoints</span><span class="p">()</span>
<span class="k">def</span><span class="w"> </span><span class="nf">get_rollback</span><span class="p">(</span><span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Get the &quot;needs rollback&quot; flag -- for *advanced use* only.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">get_connection</span><span class="p">(</span><span class="n">using</span><span class="p">)</span><span class="o">.</span><span class="n">get_rollback</span><span class="p">()</span>
<span class="k">def</span><span class="w"> </span><span class="nf">set_rollback</span><span class="p">(</span><span class="n">rollback</span><span class="p">,</span> <span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Set or unset the &quot;needs rollback&quot; flag -- for *advanced use* only.</span>
<span class="sd"> When `rollback` is `True`, trigger a rollback when exiting the innermost</span>
<span class="sd"> enclosing atomic block that has `savepoint=True` (that&#39;s the default). Use</span>
<span class="sd"> this to force a rollback without raising an exception.</span>
<span class="sd"> When `rollback` is `False`, prevent such a rollback. Use this only after</span>
<span class="sd"> rolling back to a known-good state! Otherwise, you break the atomic block</span>
<span class="sd"> and data corruption may occur.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">get_connection</span><span class="p">(</span><span class="n">using</span><span class="p">)</span><span class="o">.</span><span class="n">set_rollback</span><span class="p">(</span><span class="n">rollback</span><span class="p">)</span>
<span class="nd">@contextmanager</span>
<span class="k">def</span><span class="w"> </span><span class="nf">mark_for_rollback_on_error</span><span class="p">(</span><span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Internal low-level utility to mark a transaction as &quot;needs rollback&quot; when</span>
<span class="sd"> an exception is raised while not enforcing the enclosed block to be in a</span>
<span class="sd"> transaction. This is needed by Model.save() and friends to avoid starting a</span>
<span class="sd"> transaction when in autocommit mode and a single query is executed.</span>
<span class="sd"> It&#39;s equivalent to:</span>
<span class="sd"> connection = get_connection(using)</span>
<span class="sd"> if connection.get_autocommit():</span>
<span class="sd"> yield</span>
<span class="sd"> else:</span>
<span class="sd"> with transaction.atomic(using=using, savepoint=False):</span>
<span class="sd"> yield</span>
<span class="sd"> but it uses low-level utilities to avoid performance overhead.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">yield</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
<span class="n">connection</span> <span class="o">=</span> <span class="n">get_connection</span><span class="p">(</span><span class="n">using</span><span class="p">)</span>
<span class="k">if</span> <span class="n">connection</span><span class="o">.</span><span class="n">in_atomic_block</span><span class="p">:</span>
<span class="n">connection</span><span class="o">.</span><span class="n">needs_rollback</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">connection</span><span class="o">.</span><span class="n">rollback_exc</span> <span class="o">=</span> <span class="n">exc</span>
<span class="k">raise</span>
<span class="k">def</span><span class="w"> </span><span class="nf">on_commit</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">robust</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Register `func` to be called when the current transaction is committed.</span>
<span class="sd"> If the current transaction is rolled back, `func` will not be called.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">get_connection</span><span class="p">(</span><span class="n">using</span><span class="p">)</span><span class="o">.</span><span class="n">on_commit</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">robust</span><span class="p">)</span>
<span class="c1">#################################</span>
<span class="c1"># Decorators / context managers #</span>
<span class="c1">#################################</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Atomic</span><span class="p">(</span><span class="n">ContextDecorator</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Guarantee the atomic execution of a given block.</span>
<span class="sd"> An instance can be used either as a decorator or as a context manager.</span>
<span class="sd"> When it&#39;s used as a decorator, __call__ wraps the execution of the</span>
<span class="sd"> decorated function in the instance itself, used as a context manager.</span>
<span class="sd"> When it&#39;s used as a context manager, __enter__ creates a transaction or a</span>
<span class="sd"> savepoint, depending on whether a transaction is already in progress, and</span>
<span class="sd"> __exit__ commits the transaction or releases the savepoint on normal exit,</span>
<span class="sd"> and rolls back the transaction or to the savepoint on exceptions.</span>
<span class="sd"> It&#39;s possible to disable the creation of savepoints if the goal is to</span>
<span class="sd"> ensure that some code runs within a transaction without creating overhead.</span>
<span class="sd"> A stack of savepoints identifiers is maintained as an attribute of the</span>
<span class="sd"> connection. None denotes the absence of a savepoint.</span>
<span class="sd"> This allows reentrancy even if the same AtomicWrapper is reused. For</span>
<span class="sd"> example, it&#39;s possible to define `oa = atomic(&#39;other&#39;)` and use `@oa` or</span>
<span class="sd"> `with oa:` multiple times.</span>
<span class="sd"> Since database connections are thread-local, this is thread-safe.</span>
<span class="sd"> An atomic block can be tagged as durable. In this case, raise a</span>
<span class="sd"> RuntimeError if it&#39;s nested within another atomic block. This guarantees</span>
<span class="sd"> that database changes in a durable block are committed to the database when</span>
<span class="sd"> the block exists without error.</span>
<span class="sd"> This is a private API.</span>
<span class="sd"> &quot;&quot;&quot;</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">using</span><span class="p">,</span> <span class="n">savepoint</span><span class="p">,</span> <span class="n">durable</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">using</span> <span class="o">=</span> <span class="n">using</span>
<span class="bp">self</span><span class="o">.</span><span class="n">savepoint</span> <span class="o">=</span> <span class="n">savepoint</span>
<span class="bp">self</span><span class="o">.</span><span class="n">durable</span> <span class="o">=</span> <span class="n">durable</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_from_testcase</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__enter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">connection</span> <span class="o">=</span> <span class="n">get_connection</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">using</span><span class="p">)</span>
<span class="k">if</span> <span class="p">(</span>
<span class="bp">self</span><span class="o">.</span><span class="n">durable</span>
<span class="ow">and</span> <span class="n">connection</span><span class="o">.</span><span class="n">atomic_blocks</span>
<span class="ow">and</span> <span class="ow">not</span> <span class="n">connection</span><span class="o">.</span><span class="n">atomic_blocks</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">_from_testcase</span>
<span class="p">):</span>
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span>
<span class="s2">&quot;A durable atomic block cannot be nested within another &quot;</span>
<span class="s2">&quot;atomic block.&quot;</span>
<span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">connection</span><span class="o">.</span><span class="n">in_atomic_block</span><span class="p">:</span>
<span class="c1"># Reset state when entering an outermost atomic block.</span>
<span class="n">connection</span><span class="o">.</span><span class="n">commit_on_exit</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">connection</span><span class="o">.</span><span class="n">needs_rollback</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">connection</span><span class="o">.</span><span class="n">get_autocommit</span><span class="p">():</span>
<span class="c1"># Pretend we&#39;re already in an atomic block to bypass the code</span>
<span class="c1"># that disables autocommit to enter a transaction, and make a</span>
<span class="c1"># note to deal with this case in __exit__.</span>
<span class="n">connection</span><span class="o">.</span><span class="n">in_atomic_block</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">connection</span><span class="o">.</span><span class="n">commit_on_exit</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">if</span> <span class="n">connection</span><span class="o">.</span><span class="n">in_atomic_block</span><span class="p">:</span>
<span class="c1"># We&#39;re already in a transaction; create a savepoint, unless we</span>
<span class="c1"># were told not to or we&#39;re already waiting for a rollback. The</span>
<span class="c1"># second condition avoids creating useless savepoints and prevents</span>
<span class="c1"># overwriting needs_rollback until the rollback is performed.</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">savepoint</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">connection</span><span class="o">.</span><span class="n">needs_rollback</span><span class="p">:</span>
<span class="n">sid</span> <span class="o">=</span> <span class="n">connection</span><span class="o">.</span><span class="n">savepoint</span><span class="p">()</span>
<span class="n">connection</span><span class="o">.</span><span class="n">savepoint_ids</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">sid</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">connection</span><span class="o">.</span><span class="n">savepoint_ids</span><span class="o">.</span><span class="n">append</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">connection</span><span class="o">.</span><span class="n">set_autocommit</span><span class="p">(</span>
<span class="kc">False</span><span class="p">,</span> <span class="n">force_begin_transaction_with_broken_autocommit</span><span class="o">=</span><span class="kc">True</span>
<span class="p">)</span>
<span class="n">connection</span><span class="o">.</span><span class="n">in_atomic_block</span> <span class="o">=</span> <span class="kc">True</span>
<span class="k">if</span> <span class="n">connection</span><span class="o">.</span><span class="n">in_atomic_block</span><span class="p">:</span>
<span class="n">connection</span><span class="o">.</span><span class="n">atomic_blocks</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__exit__</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">exc_value</span><span class="p">,</span> <span class="n">traceback</span><span class="p">):</span>
<span class="n">connection</span> <span class="o">=</span> <span class="n">get_connection</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">using</span><span class="p">)</span>
<span class="k">if</span> <span class="n">connection</span><span class="o">.</span><span class="n">in_atomic_block</span><span class="p">:</span>
<span class="n">connection</span><span class="o">.</span><span class="n">atomic_blocks</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
<span class="k">if</span> <span class="n">connection</span><span class="o">.</span><span class="n">savepoint_ids</span><span class="p">:</span>
<span class="n">sid</span> <span class="o">=</span> <span class="n">connection</span><span class="o">.</span><span class="n">savepoint_ids</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># Prematurely unset this flag to allow using commit or rollback.</span>
<span class="n">connection</span><span class="o">.</span><span class="n">in_atomic_block</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">if</span> <span class="n">connection</span><span class="o">.</span><span class="n">closed_in_transaction</span><span class="p">:</span>
<span class="c1"># The database will perform a rollback by itself.</span>
<span class="c1"># Wait until we exit the outermost block.</span>
<span class="k">pass</span>
<span class="k">elif</span> <span class="n">exc_type</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">connection</span><span class="o">.</span><span class="n">needs_rollback</span><span class="p">:</span>
<span class="k">if</span> <span class="n">connection</span><span class="o">.</span><span class="n">in_atomic_block</span><span class="p">:</span>
<span class="c1"># Release savepoint if there is one</span>
<span class="k">if</span> <span class="n">sid</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">connection</span><span class="o">.</span><span class="n">savepoint_commit</span><span class="p">(</span><span class="n">sid</span><span class="p">)</span>
<span class="k">except</span> <span class="n">DatabaseError</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">connection</span><span class="o">.</span><span class="n">savepoint_rollback</span><span class="p">(</span><span class="n">sid</span><span class="p">)</span>
<span class="c1"># The savepoint won&#39;t be reused. Release it to</span>
<span class="c1"># minimize overhead for the database server.</span>
<span class="n">connection</span><span class="o">.</span><span class="n">savepoint_commit</span><span class="p">(</span><span class="n">sid</span><span class="p">)</span>
<span class="k">except</span> <span class="n">Error</span><span class="p">:</span>
<span class="c1"># If rolling back to a savepoint fails, mark for</span>
<span class="c1"># rollback at a higher level and avoid shadowing</span>
<span class="c1"># the original exception.</span>
<span class="n">connection</span><span class="o">.</span><span class="n">needs_rollback</span> <span class="o">=</span> <span class="kc">True</span>
<span class="k">raise</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># Commit transaction</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">connection</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
<span class="k">except</span> <span class="n">DatabaseError</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">connection</span><span class="o">.</span><span class="n">rollback</span><span class="p">()</span>
<span class="k">except</span> <span class="n">Error</span><span class="p">:</span>
<span class="c1"># An error during rollback means that something</span>
<span class="c1"># went wrong with the connection. Drop it.</span>
<span class="n">connection</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">raise</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># This flag will be set to True again if there isn&#39;t a savepoint</span>
<span class="c1"># allowing to perform the rollback at this level.</span>
<span class="n">connection</span><span class="o">.</span><span class="n">needs_rollback</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">if</span> <span class="n">connection</span><span class="o">.</span><span class="n">in_atomic_block</span><span class="p">:</span>
<span class="c1"># Roll back to savepoint if there is one, mark for rollback</span>
<span class="c1"># otherwise.</span>
<span class="k">if</span> <span class="n">sid</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">connection</span><span class="o">.</span><span class="n">needs_rollback</span> <span class="o">=</span> <span class="kc">True</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">connection</span><span class="o">.</span><span class="n">savepoint_rollback</span><span class="p">(</span><span class="n">sid</span><span class="p">)</span>
<span class="c1"># The savepoint won&#39;t be reused. Release it to</span>
<span class="c1"># minimize overhead for the database server.</span>
<span class="n">connection</span><span class="o">.</span><span class="n">savepoint_commit</span><span class="p">(</span><span class="n">sid</span><span class="p">)</span>
<span class="k">except</span> <span class="n">Error</span><span class="p">:</span>
<span class="c1"># If rolling back to a savepoint fails, mark for</span>
<span class="c1"># rollback at a higher level and avoid shadowing</span>
<span class="c1"># the original exception.</span>
<span class="n">connection</span><span class="o">.</span><span class="n">needs_rollback</span> <span class="o">=</span> <span class="kc">True</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># Roll back transaction</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">connection</span><span class="o">.</span><span class="n">rollback</span><span class="p">()</span>
<span class="k">except</span> <span class="n">Error</span><span class="p">:</span>
<span class="c1"># An error during rollback means that something</span>
<span class="c1"># went wrong with the connection. Drop it.</span>
<span class="n">connection</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">finally</span><span class="p">:</span>
<span class="c1"># Outermost block exit when autocommit was enabled.</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">connection</span><span class="o">.</span><span class="n">in_atomic_block</span><span class="p">:</span>
<span class="k">if</span> <span class="n">connection</span><span class="o">.</span><span class="n">closed_in_transaction</span><span class="p">:</span>
<span class="n">connection</span><span class="o">.</span><span class="n">connection</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">connection</span><span class="o">.</span><span class="n">set_autocommit</span><span class="p">(</span><span class="kc">True</span><span class="p">)</span>
<span class="c1"># Outermost block exit when autocommit was disabled.</span>
<span class="k">elif</span> <span class="ow">not</span> <span class="n">connection</span><span class="o">.</span><span class="n">savepoint_ids</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">connection</span><span class="o">.</span><span class="n">commit_on_exit</span><span class="p">:</span>
<span class="k">if</span> <span class="n">connection</span><span class="o">.</span><span class="n">closed_in_transaction</span><span class="p">:</span>
<span class="n">connection</span><span class="o">.</span><span class="n">connection</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">connection</span><span class="o">.</span><span class="n">in_atomic_block</span> <span class="o">=</span> <span class="kc">False</span>
<div class="viewcode-block" id="atomic">
<a class="viewcode-back" href="../../../api/evennia.utils.idmapper.models.html#evennia.utils.idmapper.models.atomic">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">atomic</span><span class="p">(</span><span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">savepoint</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">durable</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
<span class="c1"># Bare decorator: @atomic -- although the first argument is called</span>
<span class="c1"># `using`, it&#39;s actually the function being decorated.</span>
<span class="k">if</span> <span class="nb">callable</span><span class="p">(</span><span class="n">using</span><span class="p">):</span>
<span class="k">return</span> <span class="n">Atomic</span><span class="p">(</span><span class="n">DEFAULT_DB_ALIAS</span><span class="p">,</span> <span class="n">savepoint</span><span class="p">,</span> <span class="n">durable</span><span class="p">)(</span><span class="n">using</span><span class="p">)</span>
<span class="c1"># Decorator: @atomic(...) or context manager: with atomic(...): ...</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">Atomic</span><span class="p">(</span><span class="n">using</span><span class="p">,</span> <span class="n">savepoint</span><span class="p">,</span> <span class="n">durable</span><span class="p">)</span></div>
<span class="k">def</span><span class="w"> </span><span class="nf">_non_atomic_requests</span><span class="p">(</span><span class="n">view</span><span class="p">,</span> <span class="n">using</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">view</span><span class="o">.</span><span class="n">_non_atomic_requests</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">using</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
<span class="n">view</span><span class="o">.</span><span class="n">_non_atomic_requests</span> <span class="o">=</span> <span class="p">{</span><span class="n">using</span><span class="p">}</span>
<span class="k">return</span> <span class="n">view</span>
<span class="k">def</span><span class="w"> </span><span class="nf">non_atomic_requests</span><span class="p">(</span><span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">callable</span><span class="p">(</span><span class="n">using</span><span class="p">):</span>
<span class="k">return</span> <span class="n">_non_atomic_requests</span><span class="p">(</span><span class="n">using</span><span class="p">,</span> <span class="n">DEFAULT_DB_ALIAS</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">if</span> <span class="n">using</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">using</span> <span class="o">=</span> <span class="n">DEFAULT_DB_ALIAS</span>
<span class="k">return</span> <span class="k">lambda</span> <span class="n">view</span><span class="p">:</span> <span class="n">_non_atomic_requests</span><span class="p">(</span><span class="n">view</span><span class="p">,</span> <span class="n">using</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<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 latest</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="../../index.html" >Module code</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">django.db.transaction</a></li>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2024, The Evennia developer community.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.2.3.
</div>
</body>
</html>