evennia/docs/1.0-dev/_modules/evennia/commands/cmdset.html
2020-11-14 11:55:52 +01:00

769 lines
No EOL
75 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>evennia.commands.cmdset &#8212; Evennia 1.0-dev documentation</title>
<link rel="stylesheet" href="../../../_static/nature.css" type="text/css" />
<link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
<script id="documentation_options" data-url_root="../../../" src="../../../_static/documentation_options.js"></script>
<script src="../../../_static/jquery.js"></script>
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<link rel="shortcut 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 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 1.0-dev</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-2"><a href="../../evennia.html" accesskey="U">evennia</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">evennia.commands.cmdset</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<h1>Source code for evennia.commands.cmdset</h1><div class="highlight"><pre>
<span></span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">A Command Set (CmdSet) holds a set of commands. The Cmdsets can be</span>
<span class="sd">merged and combined to create new sets of commands in a</span>
<span class="sd">non-destructive way. This makes them very powerful for implementing</span>
<span class="sd">custom game states where different commands (or different variations</span>
<span class="sd">of commands) are available to the accounts depending on circumstance.</span>
<span class="sd">The available merge operations are partly borrowed from mathematical</span>
<span class="sd">Set theory.</span>
<span class="sd">* Union The two command sets are merged so that as many commands as</span>
<span class="sd"> possible of each cmdset ends up in the merged cmdset. Same-name</span>
<span class="sd"> commands are merged by priority. This is the most common default.</span>
<span class="sd"> Ex: A1,A3 + B1,B2,B4,B5 = A1,B2,A3,B4,B5</span>
<span class="sd">* Intersect - Only commands found in *both* cmdsets (i.e. which have</span>
<span class="sd"> same names) end up in the merged cmdset, with the higher-priority</span>
<span class="sd"> cmdset replacing the lower one. Ex: A1,A3 + B1,B2,B4,B5 = A1</span>
<span class="sd">* Replace - The commands of this cmdset completely replaces the</span>
<span class="sd"> lower-priority cmdset&#39;s commands, regardless of if same-name commands</span>
<span class="sd"> exist. Ex: A1,A3 + B1,B2,B4,B5 = A1,A3</span>
<span class="sd">* Remove - This removes the relevant commands from the</span>
<span class="sd"> lower-priority cmdset completely. They are not replaced with</span>
<span class="sd"> anything, so this in effects uses the high-priority cmdset as a filter</span>
<span class="sd"> to affect the low-priority cmdset. Ex: A1,A3 + B1,B2,B4,B5 = B2,B4,B5</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">from</span> <span class="nn">weakref</span> <span class="k">import</span> <span class="n">WeakKeyDictionary</span>
<span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="k">import</span> <span class="n">gettext</span> <span class="k">as</span> <span class="n">_</span>
<span class="kn">from</span> <span class="nn">evennia.utils.utils</span> <span class="k">import</span> <span class="n">inherits_from</span><span class="p">,</span> <span class="n">is_iter</span>
<span class="n">__all__</span> <span class="o">=</span> <span class="p">(</span><span class="s2">&quot;CmdSet&quot;</span><span class="p">,)</span>
<span class="k">class</span> <span class="nc">_CmdSetMeta</span><span class="p">(</span><span class="nb">type</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> This metaclass makes some minor on-the-fly convenience fixes to</span>
<span class="sd"> the cmdset class.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">cls</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="sd">&quot;&quot;&quot;</span>
<span class="sd"> Fixes some things in the cmdclass</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="c1"># by default we key the cmdset the same as the</span>
<span class="c1"># name of its class.</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="s2">&quot;key&quot;</span><span class="p">)</span> <span class="ow">or</span> <span class="ow">not</span> <span class="bp">cls</span><span class="o">.</span><span class="n">key</span><span class="p">:</span>
<span class="bp">cls</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="vm">__name__</span>
<span class="bp">cls</span><span class="o">.</span><span class="n">path</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">%s</span><span class="s2">.</span><span class="si">%s</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">cls</span><span class="o">.</span><span class="vm">__module__</span><span class="p">,</span> <span class="bp">cls</span><span class="o">.</span><span class="vm">__name__</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="bp">cls</span><span class="o">.</span><span class="n">key_mergetypes</span><span class="p">,</span> <span class="nb">dict</span><span class="p">):</span>
<span class="bp">cls</span><span class="o">.</span><span class="n">key_mergetypes</span> <span class="o">=</span> <span class="p">{}</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</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>
<div class="viewcode-block" id="CmdSet"><a class="viewcode-back" href="../../../api/evennia.commands.cmdset.html#evennia.commands.cmdset.CmdSet">[docs]</a><span class="k">class</span> <span class="nc">CmdSet</span><span class="p">(</span><span class="nb">object</span><span class="p">,</span> <span class="n">metaclass</span><span class="o">=</span><span class="n">_CmdSetMeta</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> This class describes a unique cmdset that understands priorities.</span>
<span class="sd"> CmdSets can be merged and made to perform various set operations</span>
<span class="sd"> on each other. CmdSets have priorities that affect which of their</span>
<span class="sd"> ingoing commands gets used.</span>
<span class="sd"> In the examples, cmdset A always have higher priority than cmdset B.</span>
<span class="sd"> key - the name of the cmdset. This can be used on its own for game</span>
<span class="sd"> operations</span>
<span class="sd"> mergetype (partly from Set theory):</span>
<span class="sd"> Union - The two command sets are merged so that as many</span>
<span class="sd"> commands as possible of each cmdset ends up in the</span>
<span class="sd"> merged cmdset. Same-name commands are merged by</span>
<span class="sd"> priority. This is the most common default.</span>
<span class="sd"> Ex: A1,A3 + B1,B2,B4,B5 = A1,B2,A3,B4,B5</span>
<span class="sd"> Intersect - Only commands found in *both* cmdsets</span>
<span class="sd"> (i.e. which have same names) end up in the merged</span>
<span class="sd"> cmdset, with the higher-priority cmdset replacing the</span>
<span class="sd"> lower one. Ex: A1,A3 + B1,B2,B4,B5 = A1</span>
<span class="sd"> Replace - The commands of this cmdset completely replaces</span>
<span class="sd"> the lower-priority cmdset&#39;s commands, regardless</span>
<span class="sd"> of if same-name commands exist.</span>
<span class="sd"> Ex: A1,A3 + B1,B2,B4,B5 = A1,A3</span>
<span class="sd"> Remove - This removes the relevant commands from the</span>
<span class="sd"> lower-priority cmdset completely. They are not</span>
<span class="sd"> replaced with anything, so this in effects uses the</span>
<span class="sd"> high-priority cmdset as a filter to affect the</span>
<span class="sd"> low-priority cmdset.</span>
<span class="sd"> Ex: A1,A3 + B1,B2,B4,B5 = B2,B4,B5</span>
<span class="sd"> Note: Commands longer than 2 characters and starting</span>
<span class="sd"> with double underscrores, like &#39;__noinput_command&#39;</span>
<span class="sd"> are considered &#39;system commands&#39; and are</span>
<span class="sd"> excempt from all merge operations - they are</span>
<span class="sd"> ALWAYS included across mergers and only affected</span>
<span class="sd"> if same-named system commands replace them.</span>
<span class="sd"> priority- All cmdsets are always merged in pairs of two so that</span>
<span class="sd"> the higher set&#39;s mergetype is applied to the</span>
<span class="sd"> lower-priority cmdset. Default commands have priority 0,</span>
<span class="sd"> high-priority ones like Exits and Channels have 10 and 9.</span>
<span class="sd"> Priorities can be negative as well to give default</span>
<span class="sd"> commands preference.</span>
<span class="sd"> duplicates - determines what happens when two sets of equal</span>
<span class="sd"> priority merge (only). Defaults to None and has the first of them in the</span>
<span class="sd"> merger (i.e. A above) automatically taking</span>
<span class="sd"> precedence. But if `duplicates` is true, the</span>
<span class="sd"> result will be a merger with more than one of each</span>
<span class="sd"> name match. This will usually lead to the account</span>
<span class="sd"> receiving a multiple-match error higher up the road,</span>
<span class="sd"> but can be good for things like cmdsets on non-account</span>
<span class="sd"> objects in a room, to allow the system to warn that</span>
<span class="sd"> more than one &#39;ball&#39; in the room has the same &#39;kick&#39;</span>
<span class="sd"> command defined on it, so it may offer a chance to</span>
<span class="sd"> select which ball to kick ... Allowing duplicates</span>
<span class="sd"> only makes sense for Union and Intersect, the setting</span>
<span class="sd"> is ignored for the other mergetypes.</span>
<span class="sd"> Note that the `duplicates` flag is *not* propagated in</span>
<span class="sd"> a cmdset merger. So `A + B = C` will result in</span>
<span class="sd"> a cmdset with duplicate commands, but C.duplicates will</span>
<span class="sd"> be `None`. For duplication to apply to a whole cmdset</span>
<span class="sd"> stack merge, _all_ cmdsets in the stack must have</span>
<span class="sd"> `.duplicates=True` set.</span>
<span class="sd"> Finally, if a final cmdset has `.duplicates=None` (the normal</span>
<span class="sd"> unless created alone with another value), the cmdhandler</span>
<span class="sd"> will assume True for object-based cmdsets and False for</span>
<span class="sd"> all other. This is usually the most intuitive outcome.</span>
<span class="sd"> key_mergetype (dict) - allows the cmdset to define a unique</span>
<span class="sd"> mergetype for particular cmdsets. Format is</span>
<span class="sd"> {CmdSetkeystring:mergetype}. Priorities still apply.</span>
<span class="sd"> Example: {&#39;Myevilcmdset&#39;,&#39;Replace&#39;} which would make</span>
<span class="sd"> sure for this set to always use &#39;Replace&#39; on</span>
<span class="sd"> Myevilcmdset no matter what overall mergetype this set</span>
<span class="sd"> has.</span>
<span class="sd"> no_objs - don&#39;t include any commands from nearby objects</span>
<span class="sd"> when searching for suitable commands</span>
<span class="sd"> no_exits - ignore the names of exits when matching against</span>
<span class="sd"> commands</span>
<span class="sd"> no_channels - ignore the name of channels when matching against</span>
<span class="sd"> commands (WARNING- this is dangerous since the</span>
<span class="sd"> account can then not even ask staff for help if</span>
<span class="sd"> something goes wrong)</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;Unnamed CmdSet&quot;</span>
<span class="n">mergetype</span> <span class="o">=</span> <span class="s2">&quot;Union&quot;</span>
<span class="n">priority</span> <span class="o">=</span> <span class="mi">0</span>
<span class="c1"># These flags, if set to None should be interpreted as &#39;I don&#39;t care&#39; and,</span>
<span class="c1"># will allow &quot;pass-through&quot; even of lower-prio cmdsets&#39; explicitly True/False</span>
<span class="c1"># options. If this is set to True/False however, priority matters.</span>
<span class="n">no_exits</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">no_objs</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">no_channels</span> <span class="o">=</span> <span class="kc">None</span>
<span class="c1"># The .duplicates setting does not propagate and since duplicates can only happen</span>
<span class="c1"># on same-prio cmdsets, there is no concept of passthrough on `None`.</span>
<span class="c1"># The merger of two cmdsets always return in a cmdset with `duplicates=None`</span>
<span class="c1"># (even if the result may have duplicated commands).</span>
<span class="c1"># If a final cmdset has `duplicates=None` (normal, unless the cmdset is</span>
<span class="c1"># created on its own with the flag set), the cmdhandler will auto-assume it to be</span>
<span class="c1"># True for Object-based cmdsets and stay None/False for all other entities.</span>
<span class="c1">#</span>
<span class="c1"># Example:</span>
<span class="c1"># A and C has .duplicates=True, B has .duplicates=None (or False)</span>
<span class="c1"># B + A = BA, where BA will have duplicate cmds, but BA.duplicates = None</span>
<span class="c1"># BA + C = BAC, where BAC will have more duplication, but BAC.duplicates = None</span>
<span class="c1">#</span>
<span class="c1"># Basically, for the `.duplicate` setting to survive throughout a</span>
<span class="c1"># merge-stack, every cmdset in the stack must have `duplicates` set explicitly.</span>
<span class="n">duplicates</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">permanent</span> <span class="o">=</span> <span class="kc">False</span>
<span class="n">key_mergetypes</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">errmessage</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span>
<span class="c1"># pre-store properties to duplicate straight off</span>
<span class="n">to_duplicate</span> <span class="o">=</span> <span class="p">(</span>
<span class="s2">&quot;key&quot;</span><span class="p">,</span>
<span class="s2">&quot;cmdsetobj&quot;</span><span class="p">,</span>
<span class="s2">&quot;no_exits&quot;</span><span class="p">,</span>
<span class="s2">&quot;no_objs&quot;</span><span class="p">,</span>
<span class="s2">&quot;no_channels&quot;</span><span class="p">,</span>
<span class="s2">&quot;permanent&quot;</span><span class="p">,</span>
<span class="s2">&quot;mergetype&quot;</span><span class="p">,</span>
<span class="s2">&quot;priority&quot;</span><span class="p">,</span>
<span class="s2">&quot;duplicates&quot;</span><span class="p">,</span>
<span class="s2">&quot;errmessage&quot;</span><span class="p">,</span>
<span class="p">)</span>
<div class="viewcode-block" id="CmdSet.__init__"><a class="viewcode-back" href="../../../api/evennia.commands.cmdset.html#evennia.commands.cmdset.CmdSet.__init__">[docs]</a> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cmdsetobj</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Creates a new CmdSet instance.</span>
<span class="sd"> Args:</span>
<span class="sd"> cmdsetobj (Session, Account, Object, optional): This is the database object</span>
<span class="sd"> to which this particular instance of cmdset is related. It</span>
<span class="sd"> is often a character but may also be a regular object, Account</span>
<span class="sd"> or Session.</span>
<span class="sd"> key (str, optional): The idenfier for this cmdset. This</span>
<span class="sd"> helps if wanting to selectively remov cmdsets.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="n">key</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">key</span>
<span class="bp">self</span><span class="o">.</span><span class="n">commands</span> <span class="o">=</span> <span class="p">[]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">system_commands</span> <span class="o">=</span> <span class="p">[]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">actual_mergetype</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">mergetype</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cmdsetobj</span> <span class="o">=</span> <span class="n">cmdsetobj</span>
<span class="c1"># this is set only on merged sets, in cmdhandler.py, in order to</span>
<span class="c1"># track, list and debug mergers correctly.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">merged_from</span> <span class="o">=</span> <span class="p">[]</span>
<span class="c1"># initialize system</span>
<span class="bp">self</span><span class="o">.</span><span class="n">at_cmdset_creation</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_contains_cache</span> <span class="o">=</span> <span class="n">WeakKeyDictionary</span><span class="p">()</span> <span class="c1"># {}</span></div>
<span class="c1"># Priority-sensitive merge operations for cmdsets</span>
<span class="k">def</span> <span class="nf">_union</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cmdset_a</span><span class="p">,</span> <span class="n">cmdset_b</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Merge two sets using union merger</span>
<span class="sd"> Args:</span>
<span class="sd"> cmdset_a (Cmdset): Cmdset given higher priority in the case of a tie.</span>
<span class="sd"> cmdset_b (Cmdset): Cmdset given lower priority in the case of a tie.</span>
<span class="sd"> Returns:</span>
<span class="sd"> cmdset_c (Cmdset): The result of A U B operation.</span>
<span class="sd"> Notes:</span>
<span class="sd"> Union, C = A U B, means that C gets all elements from both A and B.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">cmdset_c</span> <span class="o">=</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">_duplicate</span><span class="p">()</span>
<span class="c1"># we make copies, not refs by use of [:]</span>
<span class="n">cmdset_c</span><span class="o">.</span><span class="n">commands</span> <span class="o">=</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">commands</span><span class="p">[:]</span>
<span class="k">if</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">duplicates</span> <span class="ow">and</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">priority</span> <span class="o">==</span> <span class="n">cmdset_b</span><span class="o">.</span><span class="n">priority</span><span class="p">:</span>
<span class="n">cmdset_c</span><span class="o">.</span><span class="n">commands</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">cmdset_b</span><span class="o">.</span><span class="n">commands</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">cmdset_c</span><span class="o">.</span><span class="n">commands</span><span class="o">.</span><span class="n">extend</span><span class="p">([</span><span class="n">cmd</span> <span class="k">for</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="n">cmdset_b</span> <span class="k">if</span> <span class="n">cmd</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">cmdset_a</span><span class="p">])</span>
<span class="k">return</span> <span class="n">cmdset_c</span>
<span class="k">def</span> <span class="nf">_intersect</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cmdset_a</span><span class="p">,</span> <span class="n">cmdset_b</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Merge two sets using intersection merger</span>
<span class="sd"> Args:</span>
<span class="sd"> cmdset_a (Cmdset): Cmdset given higher priority in the case of a tie.</span>
<span class="sd"> cmdset_b (Cmdset): Cmdset given lower priority in the case of a tie.</span>
<span class="sd"> Returns:</span>
<span class="sd"> cmdset_c (Cmdset): The result of A (intersect) B operation.</span>
<span class="sd"> Notes:</span>
<span class="sd"> Intersection, C = A (intersect) B, means that C only gets the</span>
<span class="sd"> parts of A and B that are the same (that is, the commands</span>
<span class="sd"> of each set having the same name. Only the one of these</span>
<span class="sd"> having the higher prio ends up in C).</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">cmdset_c</span> <span class="o">=</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">_duplicate</span><span class="p">()</span>
<span class="k">if</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">duplicates</span> <span class="ow">and</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">priority</span> <span class="o">==</span> <span class="n">cmdset_b</span><span class="o">.</span><span class="n">priority</span><span class="p">:</span>
<span class="k">for</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="p">[</span><span class="n">cmd</span> <span class="k">for</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="n">cmdset_a</span> <span class="k">if</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="n">cmdset_b</span><span class="p">]:</span>
<span class="n">cmdset_c</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span>
<span class="n">cmdset_c</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">cmdset_b</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">cmd</span><span class="p">))</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">cmdset_c</span><span class="o">.</span><span class="n">commands</span> <span class="o">=</span> <span class="p">[</span><span class="n">cmd</span> <span class="k">for</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="n">cmdset_a</span> <span class="k">if</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="n">cmdset_b</span><span class="p">]</span>
<span class="k">return</span> <span class="n">cmdset_c</span>
<span class="k">def</span> <span class="nf">_replace</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cmdset_a</span><span class="p">,</span> <span class="n">cmdset_b</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Replace the contents of one set with another</span>
<span class="sd"> Args:</span>
<span class="sd"> cmdset_a (Cmdset): Cmdset replacing</span>
<span class="sd"> cmdset_b (Cmdset): Cmdset to replace</span>
<span class="sd"> Returns:</span>
<span class="sd"> cmdset_c (Cmdset): This is indentical to cmdset_a.</span>
<span class="sd"> Notes:</span>
<span class="sd"> C = A, where B is ignored.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">cmdset_c</span> <span class="o">=</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">_duplicate</span><span class="p">()</span>
<span class="n">cmdset_c</span><span class="o">.</span><span class="n">commands</span> <span class="o">=</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">commands</span><span class="p">[:]</span>
<span class="k">return</span> <span class="n">cmdset_c</span>
<span class="k">def</span> <span class="nf">_remove</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cmdset_a</span><span class="p">,</span> <span class="n">cmdset_b</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Filter a set by another.</span>
<span class="sd"> Args:</span>
<span class="sd"> cmdset_a (Cmdset): Cmdset acting as a removal filter.</span>
<span class="sd"> cmdset_b (Cmdset): Cmdset to filter</span>
<span class="sd"> Returns:</span>
<span class="sd"> cmdset_c (Cmdset): B, with all matching commands from A removed.</span>
<span class="sd"> Notes:</span>
<span class="sd"> C = B - A, where A is used to remove the commands of B.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">cmdset_c</span> <span class="o">=</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">_duplicate</span><span class="p">()</span>
<span class="n">cmdset_c</span><span class="o">.</span><span class="n">commands</span> <span class="o">=</span> <span class="p">[</span><span class="n">cmd</span> <span class="k">for</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="n">cmdset_b</span> <span class="k">if</span> <span class="n">cmd</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">cmdset_a</span><span class="p">]</span>
<span class="k">return</span> <span class="n">cmdset_c</span>
<span class="k">def</span> <span class="nf">_instantiate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cmd</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> checks so that object is an instantiated command and not, say</span>
<span class="sd"> a cmdclass. If it is, instantiate it. Other types, like</span>
<span class="sd"> strings, are passed through.</span>
<span class="sd"> Args:</span>
<span class="sd"> cmd (any): Entity to analyze.</span>
<span class="sd"> Returns:</span>
<span class="sd"> result (any): An instantiated Command or the input unmodified.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="n">callable</span><span class="p">(</span><span class="n">cmd</span><span class="p">):</span>
<span class="k">return</span> <span class="n">cmd</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">cmd</span>
<span class="k">def</span> <span class="nf">_duplicate</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Returns a new cmdset with the same settings as this one (no</span>
<span class="sd"> actual commands are copied over)</span>
<span class="sd"> Returns:</span>
<span class="sd"> cmdset (Cmdset): A copy of the current cmdset.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">cmdset</span> <span class="o">=</span> <span class="n">CmdSet</span><span class="p">()</span>
<span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">val</span> <span class="ow">in</span> <span class="p">((</span><span class="n">key</span><span class="p">,</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">))</span> <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">to_duplicate</span><span class="p">):</span>
<span class="k">if</span> <span class="n">val</span> <span class="o">!=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">cmdset</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
<span class="c1"># only copy if different from default; avoid turning</span>
<span class="c1"># class-vars into instance vars</span>
<span class="nb">setattr</span><span class="p">(</span><span class="n">cmdset</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">val</span><span class="p">)</span>
<span class="n">cmdset</span><span class="o">.</span><span class="n">key_mergetypes</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">key_mergetypes</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
<span class="k">return</span> <span class="n">cmdset</span>
<span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Show all commands in cmdset when printing it.</span>
<span class="sd"> Returns:</span>
<span class="sd"> commands (str): Representation of commands in Cmdset.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">perm</span> <span class="o">=</span> <span class="s2">&quot;perm&quot;</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">permanent</span> <span class="k">else</span> <span class="s2">&quot;non-perm&quot;</span>
<span class="n">options</span> <span class="o">=</span> <span class="s2">&quot;, &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span>
<span class="s2">&quot;</span><span class="si">{}</span><span class="s2">:</span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">opt</span><span class="p">,</span> <span class="s2">&quot;T&quot;</span> <span class="k">if</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">opt</span><span class="p">)</span> <span class="k">else</span> <span class="s2">&quot;F&quot;</span><span class="p">)</span>
<span class="k">for</span> <span class="n">opt</span> <span class="ow">in</span> <span class="p">(</span><span class="s2">&quot;no_exits&quot;</span><span class="p">,</span> <span class="s2">&quot;no_objs&quot;</span><span class="p">,</span> <span class="s2">&quot;no_channels&quot;</span><span class="p">,</span> <span class="s2">&quot;duplicates&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">opt</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
<span class="p">])</span>
<span class="n">options</span> <span class="o">=</span> <span class="p">(</span><span class="s2">&quot;, &quot;</span> <span class="o">+</span> <span class="n">options</span><span class="p">)</span> <span class="k">if</span> <span class="n">options</span> <span class="k">else</span> <span class="s2">&quot;&quot;</span>
<span class="k">return</span> <span class="n">f</span><span class="s2">&quot;&lt;CmdSet </span><span class="si">{self.key}</span><span class="s2">, </span><span class="si">{self.mergetype}</span><span class="s2">, </span><span class="si">{perm}</span><span class="s2">, prio </span><span class="si">{self.priority}{options}</span><span class="s2">&gt;: &quot;</span> <span class="o">+</span> <span class="s2">&quot;, &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span>
<span class="p">[</span><span class="nb">str</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span> <span class="k">for</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">commands</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">o</span><span class="p">:</span> <span class="n">o</span><span class="o">.</span><span class="n">key</span><span class="p">)])</span>
<span class="k">def</span> <span class="nf">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Allows for things like &#39;for cmd in cmdset&#39;:</span>
<span class="sd"> Returns:</span>
<span class="sd"> iterable (iter): Commands in Cmdset.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="nb">iter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">commands</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">__contains__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">othercmd</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Returns True if this cmdset contains the given command (as</span>
<span class="sd"> defined by command name and aliases). This allows for things</span>
<span class="sd"> like &#39;if cmd in cmdset&#39;</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">ret</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_contains_cache</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">othercmd</span><span class="p">)</span>
<span class="k">if</span> <span class="n">ret</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">ret</span> <span class="o">=</span> <span class="n">othercmd</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">commands</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_contains_cache</span><span class="p">[</span><span class="n">othercmd</span><span class="p">]</span> <span class="o">=</span> <span class="n">ret</span>
<span class="k">return</span> <span class="n">ret</span>
<span class="k">def</span> <span class="nf">__add__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cmdset_a</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Merge this cmdset (B) with another cmdset (A) using the + operator,</span>
<span class="sd"> C = B + A</span>
<span class="sd"> Here, we (by convention) say that &#39;A is merged onto B to form</span>
<span class="sd"> C&#39;. The actual merge operation used in the &#39;addition&#39; depends</span>
<span class="sd"> on which priorities A and B have. The one of the two with the</span>
<span class="sd"> highest priority will apply and give its properties to C. In</span>
<span class="sd"> the case of a tie, A takes priority and replaces the</span>
<span class="sd"> same-named commands in B unless A has the &#39;duplicate&#39; variable</span>
<span class="sd"> set (which means both sets&#39; commands are kept).</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="c1"># It&#39;s okay to merge with None</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">cmdset_a</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span>
<span class="n">sys_commands_a</span> <span class="o">=</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">get_system_cmds</span><span class="p">()</span>
<span class="n">sys_commands_b</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_system_cmds</span><span class="p">()</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">priority</span> <span class="o">&lt;=</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">priority</span><span class="p">:</span>
<span class="c1"># A higher or equal priority to B</span>
<span class="c1"># preserve system __commands</span>
<span class="n">sys_commands</span> <span class="o">=</span> <span class="n">sys_commands_a</span> <span class="o">+</span> <span class="p">[</span>
<span class="n">cmd</span> <span class="k">for</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="n">sys_commands_b</span> <span class="k">if</span> <span class="n">cmd</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">sys_commands_a</span>
<span class="p">]</span>
<span class="n">mergetype</span> <span class="o">=</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">key_mergetypes</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="p">,</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">mergetype</span><span class="p">)</span>
<span class="k">if</span> <span class="n">mergetype</span> <span class="o">==</span> <span class="s2">&quot;Intersect&quot;</span><span class="p">:</span>
<span class="n">cmdset_c</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_intersect</span><span class="p">(</span><span class="n">cmdset_a</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">mergetype</span> <span class="o">==</span> <span class="s2">&quot;Replace&quot;</span><span class="p">:</span>
<span class="n">cmdset_c</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_replace</span><span class="p">(</span><span class="n">cmdset_a</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">mergetype</span> <span class="o">==</span> <span class="s2">&quot;Remove&quot;</span><span class="p">:</span>
<span class="n">cmdset_c</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_remove</span><span class="p">(</span><span class="n">cmdset_a</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"># Union</span>
<span class="n">cmdset_c</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_union</span><span class="p">(</span><span class="n">cmdset_a</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span>
<span class="c1"># pass through options whenever they are set, unless the merging or higher-prio</span>
<span class="c1"># set changes the setting (i.e. has a non-None value). We don&#39;t pass through</span>
<span class="c1"># the duplicates setting; that is per-merge; the resulting .duplicates value</span>
<span class="c1"># is always None (so merging cmdsets must all have explicit values if wanting</span>
<span class="c1"># to cause duplicates).</span>
<span class="n">cmdset_c</span><span class="o">.</span><span class="n">no_channels</span> <span class="o">=</span> <span class="p">(</span>
<span class="bp">self</span><span class="o">.</span><span class="n">no_channels</span> <span class="k">if</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">no_channels</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">no_channels</span>
<span class="p">)</span>
<span class="n">cmdset_c</span><span class="o">.</span><span class="n">no_exits</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_exits</span> <span class="k">if</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">no_exits</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">no_exits</span>
<span class="n">cmdset_c</span><span class="o">.</span><span class="n">no_objs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_objs</span> <span class="k">if</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">no_objs</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">no_objs</span>
<span class="n">cmdset_c</span><span class="o">.</span><span class="n">duplicates</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># B higher priority than A</span>
<span class="c1"># preserver system __commands</span>
<span class="n">sys_commands</span> <span class="o">=</span> <span class="n">sys_commands_b</span> <span class="o">+</span> <span class="p">[</span>
<span class="n">cmd</span> <span class="k">for</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="n">sys_commands_a</span> <span class="k">if</span> <span class="n">cmd</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">sys_commands_b</span>
<span class="p">]</span>
<span class="n">mergetype</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">key_mergetypes</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">cmdset_a</span><span class="o">.</span><span class="n">key</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">mergetype</span><span class="p">)</span>
<span class="k">if</span> <span class="n">mergetype</span> <span class="o">==</span> <span class="s2">&quot;Intersect&quot;</span><span class="p">:</span>
<span class="n">cmdset_c</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_intersect</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cmdset_a</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">mergetype</span> <span class="o">==</span> <span class="s2">&quot;Replace&quot;</span><span class="p">:</span>
<span class="n">cmdset_c</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_replace</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cmdset_a</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">mergetype</span> <span class="o">==</span> <span class="s2">&quot;Remove&quot;</span><span class="p">:</span>
<span class="n">cmdset_c</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_remove</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cmdset_a</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span> <span class="c1"># Union</span>
<span class="n">cmdset_c</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_union</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cmdset_a</span><span class="p">)</span>
<span class="c1"># pass through options whenever they are set, unless the higher-prio</span>
<span class="c1"># set changes the setting (i.e. has a non-None value). We don&#39;t pass through</span>
<span class="c1"># the duplicates setting; that is per-merge; the resulting .duplicates value#</span>
<span class="c1"># is always None (so merging cmdsets must all have explicit values if wanting</span>
<span class="c1"># to cause duplicates).</span>
<span class="n">cmdset_c</span><span class="o">.</span><span class="n">no_channels</span> <span class="o">=</span> <span class="p">(</span>
<span class="n">cmdset_a</span><span class="o">.</span><span class="n">no_channels</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_channels</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_channels</span>
<span class="p">)</span>
<span class="n">cmdset_c</span><span class="o">.</span><span class="n">no_exits</span> <span class="o">=</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">no_exits</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_exits</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_exits</span>
<span class="n">cmdset_c</span><span class="o">.</span><span class="n">no_objs</span> <span class="o">=</span> <span class="n">cmdset_a</span><span class="o">.</span><span class="n">no_objs</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_objs</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_objs</span>
<span class="n">cmdset_c</span><span class="o">.</span><span class="n">duplicates</span> <span class="o">=</span> <span class="kc">None</span>
<span class="c1"># we store actual_mergetype since key_mergetypes</span>
<span class="c1"># might be different from the main mergetype.</span>
<span class="c1"># This is used for diagnosis.</span>
<span class="n">cmdset_c</span><span class="o">.</span><span class="n">actual_mergetype</span> <span class="o">=</span> <span class="n">mergetype</span>
<span class="c1"># print &quot;__add__ for %s (prio %i) called with %s (prio %i).&quot; % (self.key, self.priority, cmdset_a.key, cmdset_a.priority)</span>
<span class="c1"># return the system commands to the cmdset</span>
<span class="n">cmdset_c</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">sys_commands</span><span class="p">,</span> <span class="n">allow_duplicates</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="k">return</span> <span class="n">cmdset_c</span>
<div class="viewcode-block" id="CmdSet.add"><a class="viewcode-back" href="../../../api/evennia.commands.cmdset.html#evennia.commands.cmdset.CmdSet.add">[docs]</a> <span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cmd</span><span class="p">,</span> <span class="n">allow_duplicates</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Add a new command or commands to this CmdSet, a list of</span>
<span class="sd"> commands or a cmdset to this cmdset. Note that this is *not*</span>
<span class="sd"> a merge operation (that is handled by the + operator).</span>
<span class="sd"> Args:</span>
<span class="sd"> cmd (Command, list, Cmdset): This allows for adding one or</span>
<span class="sd"> more commands to this Cmdset in one go. If another Cmdset</span>
<span class="sd"> is given, all its commands will be added.</span>
<span class="sd"> allow_duplicates (bool, optional): If set, will not try to remove</span>
<span class="sd"> duplicate cmds in the set. This is needed during the merge process</span>
<span class="sd"> to avoid wiping commands coming from cmdsets with duplicate=True.</span>
<span class="sd"> Notes:</span>
<span class="sd"> If cmd already exists in set, it will replace the old one</span>
<span class="sd"> (no priority checking etc happens here). This is very useful</span>
<span class="sd"> when overloading default commands).</span>
<span class="sd"> If cmd is another cmdset class or -instance, the commands of</span>
<span class="sd"> that command set is added to this one, as if they were part of</span>
<span class="sd"> the original cmdset definition. No merging or priority checks</span>
<span class="sd"> are made, rather later added commands will simply replace</span>
<span class="sd"> existing ones to make a unique set.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="n">inherits_from</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="s2">&quot;evennia.commands.cmdset.CmdSet&quot;</span><span class="p">):</span>
<span class="c1"># cmd is a command set so merge all commands in that set</span>
<span class="c1"># to this one. We raise a visible error if we created</span>
<span class="c1"># an infinite loop (adding cmdset to itself somehow)</span>
<span class="n">cmdset</span> <span class="o">=</span> <span class="n">cmd</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">cmdset</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_instantiate</span><span class="p">(</span><span class="n">cmdset</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">RuntimeError</span><span class="p">:</span>
<span class="n">err</span> <span class="o">=</span> <span class="p">(</span><span class="s2">&quot;Adding cmdset </span><span class="si">{cmdset}</span><span class="s2"> to </span><span class="si">{cls}</span><span class="s2"> lead to an &quot;</span>
<span class="s2">&quot;infinite loop. When adding a cmdset to another, &quot;</span>
<span class="s2">&quot;make sure they are not themself cyclically added to &quot;</span>
<span class="s2">&quot;the new cmdset somewhere in the chain.&quot;</span><span class="p">)</span>
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="n">err</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">cmdset</span><span class="o">=</span><span class="n">cmdset</span><span class="p">,</span> <span class="bp">cls</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">)))</span>
<span class="n">cmds</span> <span class="o">=</span> <span class="n">cmdset</span><span class="o">.</span><span class="n">commands</span>
<span class="k">elif</span> <span class="n">is_iter</span><span class="p">(</span><span class="n">cmd</span><span class="p">):</span>
<span class="n">cmds</span> <span class="o">=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">_instantiate</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">cmd</span><span class="p">]</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">cmds</span> <span class="o">=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">_instantiate</span><span class="p">(</span><span class="n">cmd</span><span class="p">)]</span>
<span class="n">commands</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">commands</span>
<span class="n">system_commands</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">system_commands</span>
<span class="k">for</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="n">cmds</span><span class="p">:</span>
<span class="c1"># add all commands</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="s2">&quot;obj&quot;</span><span class="p">)</span> <span class="ow">or</span> <span class="n">cmd</span><span class="o">.</span><span class="n">obj</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">cmd</span><span class="o">.</span><span class="n">obj</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">cmdsetobj</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">ic</span> <span class="o">=</span> <span class="n">commands</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span>
<span class="n">commands</span><span class="p">[</span><span class="n">ic</span><span class="p">]</span> <span class="o">=</span> <span class="n">cmd</span> <span class="c1"># replace</span>
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
<span class="n">commands</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">commands</span> <span class="o">=</span> <span class="n">commands</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">allow_duplicates</span><span class="p">:</span>
<span class="c1"># extra run to make sure to avoid doublets</span>
<span class="bp">self</span><span class="o">.</span><span class="n">commands</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">commands</span><span class="p">))</span>
<span class="c1"># add system_command to separate list as well,</span>
<span class="c1"># for quick look-up</span>
<span class="k">if</span> <span class="n">cmd</span><span class="o">.</span><span class="n">key</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">&quot;__&quot;</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">ic</span> <span class="o">=</span> <span class="n">system_commands</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span>
<span class="n">system_commands</span><span class="p">[</span><span class="n">ic</span><span class="p">]</span> <span class="o">=</span> <span class="n">cmd</span> <span class="c1"># replace</span>
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
<span class="n">system_commands</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span></div>
<div class="viewcode-block" id="CmdSet.remove"><a class="viewcode-back" href="../../../api/evennia.commands.cmdset.html#evennia.commands.cmdset.CmdSet.remove">[docs]</a> <span class="k">def</span> <span class="nf">remove</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cmd</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Remove a command instance from the cmdset.</span>
<span class="sd"> Args:</span>
<span class="sd"> cmd (Command or str): Either the Command object to remove</span>
<span class="sd"> or the key of such a command.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">cmd</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_instantiate</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span>
<span class="k">if</span> <span class="n">cmd</span><span class="o">.</span><span class="n">key</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">&quot;__&quot;</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">ic</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">system_commands</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span>
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">system_commands</span><span class="p">[</span><span class="n">ic</span><span class="p">]</span>
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
<span class="c1"># ignore error</span>
<span class="k">pass</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">commands</span> <span class="o">=</span> <span class="p">[</span><span class="n">oldcmd</span> <span class="k">for</span> <span class="n">oldcmd</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">commands</span> <span class="k">if</span> <span class="n">oldcmd</span> <span class="o">!=</span> <span class="n">cmd</span><span class="p">]</span></div>
<div class="viewcode-block" id="CmdSet.get"><a class="viewcode-back" href="../../../api/evennia.commands.cmdset.html#evennia.commands.cmdset.CmdSet.get">[docs]</a> <span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cmd</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Get a command from the cmdset. This is mostly useful to</span>
<span class="sd"> check if the command is part of this cmdset or not.</span>
<span class="sd"> Args:</span>
<span class="sd"> cmd (Command or str): Either the Command object or its key.</span>
<span class="sd"> Returns:</span>
<span class="sd"> cmd (Command): The first matching Command in the set.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">cmd</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_instantiate</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span>
<span class="k">for</span> <span class="n">thiscmd</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">commands</span><span class="p">:</span>
<span class="k">if</span> <span class="n">thiscmd</span> <span class="o">==</span> <span class="n">cmd</span><span class="p">:</span>
<span class="k">return</span> <span class="n">thiscmd</span>
<span class="k">return</span> <span class="kc">None</span></div>
<div class="viewcode-block" id="CmdSet.count"><a class="viewcode-back" href="../../../api/evennia.commands.cmdset.html#evennia.commands.cmdset.CmdSet.count">[docs]</a> <span class="k">def</span> <span class="nf">count</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Number of commands in set.</span>
<span class="sd"> Returns:</span>
<span class="sd"> N (int): Number of commands in this Cmdset.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">commands</span><span class="p">)</span></div>
<div class="viewcode-block" id="CmdSet.get_system_cmds"><a class="viewcode-back" href="../../../api/evennia.commands.cmdset.html#evennia.commands.cmdset.CmdSet.get_system_cmds">[docs]</a> <span class="k">def</span> <span class="nf">get_system_cmds</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Get system commands in cmdset</span>
<span class="sd"> Returns:</span>
<span class="sd"> sys_cmds (list): The system commands in the set.</span>
<span class="sd"> Notes:</span>
<span class="sd"> As far as the Cmdset is concerned, system commands are any</span>
<span class="sd"> commands with a key starting with double underscore __.</span>
<span class="sd"> These are excempt from merge operations.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">system_commands</span></div>
<div class="viewcode-block" id="CmdSet.make_unique"><a class="viewcode-back" href="../../../api/evennia.commands.cmdset.html#evennia.commands.cmdset.CmdSet.make_unique">[docs]</a> <span class="k">def</span> <span class="nf">make_unique</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">caller</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Remove duplicate command-keys (unsafe)</span>
<span class="sd"> Args:</span>
<span class="sd"> caller (object): Commands on this object will</span>
<span class="sd"> get preference in the duplicate removal.</span>
<span class="sd"> Notes:</span>
<span class="sd"> This is an unsafe command meant to clean out a cmdset of</span>
<span class="sd"> doublet commands after it has been created. It is useful</span>
<span class="sd"> for commands inheriting cmdsets from the cmdhandler where</span>
<span class="sd"> obj-based cmdsets always are added double. Doublets will</span>
<span class="sd"> be weeded out with preference to commands defined on</span>
<span class="sd"> caller, otherwise just by first-come-first-served.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">unique</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">commands</span><span class="p">:</span>
<span class="k">if</span> <span class="n">cmd</span><span class="o">.</span><span class="n">key</span> <span class="ow">in</span> <span class="n">unique</span><span class="p">:</span>
<span class="n">ocmd</span> <span class="o">=</span> <span class="n">unique</span><span class="p">[</span><span class="n">cmd</span><span class="o">.</span><span class="n">key</span><span class="p">]</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">hasattr</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="s2">&quot;obj&quot;</span><span class="p">)</span> <span class="ow">and</span> <span class="n">cmd</span><span class="o">.</span><span class="n">obj</span> <span class="o">==</span> <span class="n">caller</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="p">(</span>
<span class="nb">hasattr</span><span class="p">(</span><span class="n">ocmd</span><span class="p">,</span> <span class="s2">&quot;obj&quot;</span><span class="p">)</span> <span class="ow">and</span> <span class="n">ocmd</span><span class="o">.</span><span class="n">obj</span> <span class="o">==</span> <span class="n">caller</span>
<span class="p">):</span>
<span class="n">unique</span><span class="p">[</span><span class="n">cmd</span><span class="o">.</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">cmd</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">unique</span><span class="p">[</span><span class="n">cmd</span><span class="o">.</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">cmd</span>
<span class="bp">self</span><span class="o">.</span><span class="n">commands</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">unique</span><span class="o">.</span><span class="n">values</span><span class="p">())</span></div>
<div class="viewcode-block" id="CmdSet.get_all_cmd_keys_and_aliases"><a class="viewcode-back" href="../../../api/evennia.commands.cmdset.html#evennia.commands.cmdset.CmdSet.get_all_cmd_keys_and_aliases">[docs]</a> <span class="k">def</span> <span class="nf">get_all_cmd_keys_and_aliases</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">caller</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Collects keys/aliases from commands</span>
<span class="sd"> Args:</span>
<span class="sd"> caller (Object, optional): If set, this is used to check access permissions</span>
<span class="sd"> on each command. Only commands that pass are returned.</span>
<span class="sd"> Returns:</span>
<span class="sd"> names (list): A list of all command keys and aliases in this cmdset. If `caller`</span>
<span class="sd"> was given, this list will only contain commands to which `caller` passed</span>
<span class="sd"> the `call` locktype check.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">names</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">if</span> <span class="n">caller</span><span class="p">:</span>
<span class="p">[</span><span class="n">names</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">cmd</span><span class="o">.</span><span class="n">_keyaliases</span><span class="p">)</span> <span class="k">for</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">commands</span> <span class="k">if</span> <span class="n">cmd</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">caller</span><span class="p">)]</span>
<span class="k">else</span><span class="p">:</span>
<span class="p">[</span><span class="n">names</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">cmd</span><span class="o">.</span><span class="n">_keyaliases</span><span class="p">)</span> <span class="k">for</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">commands</span><span class="p">]</span>
<span class="k">return</span> <span class="n">names</span></div>
<div class="viewcode-block" id="CmdSet.at_cmdset_creation"><a class="viewcode-back" href="../../../api/evennia.commands.cmdset.html#evennia.commands.cmdset.CmdSet.at_cmdset_creation">[docs]</a> <span class="k">def</span> <span class="nf">at_cmdset_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Hook method - this should be overloaded in the inheriting</span>
<span class="sd"> class, and should take care of populating the cmdset by use of</span>
<span class="sd"> self.add().</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">pass</span></div></div>
</pre></div>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../../../index.html">
<img class="logo" src="../../../_static/evennia_logo.png" alt="Logo"/>
</a></p>
<div 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" />
<input type="submit" value="Go" />
</form>
</div>
</div>
<script>$('#searchbox').show(0);</script>
<h3>Versions</h3>
<ul>
<li><a href="cmdset.html">1.0-dev (develop branch)</a></li>
<li><a href="../../../../0.9.5/index.html">0.9.5 (master branch)</a></li>
</ul>
</div>
</div>
<div class="clearer"></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 1.0-dev</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-2"><a href="../../evennia.html" >evennia</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">evennia.commands.cmdset</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2020, The Evennia developer community.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
</div>
</body>
</html>