evennia/docs/0.9.1/Execute-Python-Code.html
2020-06-14 21:48:02 +02:00

306 lines
No EOL
18 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Execute Python Code &mdash; Evennia 0.9.1 documentation</title>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
<link rel="index" title="Index"
href="genindex.html"/>
<link rel="search" title="Search" href="search.html"/>
<link rel="top" title="Evennia 0.9.1 documentation" href="index.html"/>
<script src="_static/js/modernizr.min.js"></script>
</head>
<body class="wy-body-for-nav" role="document">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search">
<a href="index.html" class="icon icon-home"> Evennia
</a>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="search.html" method="get">
<input type="text" name="q" placeholder="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
<!-- Local TOC -->
<div class="local-toc"><ul>
<li><a class="reference internal" href="#">Execute Python Code</a><ul>
<li><a class="reference internal" href="#available-variables">Available variables</a></li>
<li><a class="reference internal" href="#returning-output">Returning output</a></li>
<li><a class="reference internal" href="#finding-objects">Finding objects</a></li>
<li><a class="reference internal" href="#testing-code-outside-the-game">Testing code outside the game</a></li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
<nav class="wy-nav-top" role="navigation" aria-label="top navigation">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="index.html">Evennia</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="index.html">Docs</a> &raquo;</li>
<li>Execute Python Code</li>
<li class="wy-breadcrumbs-aside">
<a href="_sources/Execute-Python-Code.md.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<div class="section" id="execute-python-code">
<h1>Execute Python Code<a class="headerlink" href="#execute-python-code" title="Permalink to this headline"></a></h1>
<p>The <code class="docutils literal notranslate"><span class="pre">&#64;py</span></code> command supplied with the default command set of Evennia allows you to execute Python commands directly from inside the game. An alias to <code class="docutils literal notranslate"><span class="pre">&#64;py</span></code> is simply “<code class="docutils literal notranslate"><span class="pre">!</span></code>”. <em>Access to the <code class="docutils literal notranslate"><span class="pre">&#64;py</span></code> command should be severely restricted</em>. This is no joke - being able to execute arbitrary Python code on the server is not something you should entrust to just anybody.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@py</span> <span class="mi">1</span><span class="o">+</span><span class="mi">2</span>
<span class="o">&lt;&lt;&lt;</span> <span class="mi">3</span>
</pre></div>
</div>
<div class="section" id="available-variables">
<h2>Available variables<a class="headerlink" href="#available-variables" title="Permalink to this headline"></a></h2>
<p>A few local variables are made available when running <code class="docutils literal notranslate"><span class="pre">&#64;py</span></code>. These offer entry into the running system.</p>
<ul class="simple">
<li><p><strong>self</strong> / <strong>me</strong> - the calling object (i.e. you)</p></li>
<li><p><strong>here</strong> - the current callers location</p></li>
<li><p><strong>obj</strong> - a dummy <a class="reference internal" href="Objects.html"><span class="doc">Object</span></a> instance</p></li>
<li><p><strong>evennia</strong> - Evennias <a class="reference internal" href="Evennia-API.html"><span class="doc">flat API</span></a> - through this you can access all of Evennia.</p></li>
</ul>
<p>For accessing other objects in the same room you need to use <code class="docutils literal notranslate"><span class="pre">self.search(name)</span></code>. For objects in other locations, use one of the <code class="docutils literal notranslate"><span class="pre">evennia.search_*</span></code> methods. See <a class="reference external" href="/Execute-Python-Code.html#finding-objects">below</a>.</p>
</div>
<div class="section" id="returning-output">
<h2>Returning output<a class="headerlink" href="#returning-output" title="Permalink to this headline"></a></h2>
<p>This is an example where we import and test one of Evennias utilities found in <code class="docutils literal notranslate"><span class="pre">src/utils/utils.py</span></code>, but also accessible through <code class="docutils literal notranslate"><span class="pre">ev.utils</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@py</span> <span class="kn">from</span> <span class="nn">ev</span> <span class="k">import</span> <span class="n">utils</span><span class="p">;</span> <span class="n">utils</span><span class="o">.</span><span class="n">time_format</span><span class="p">(</span><span class="mi">33333</span><span class="p">)</span>
<span class="o">&lt;&lt;&lt;</span> <span class="n">Done</span><span class="o">.</span>
</pre></div>
</div>
<p>Note that we didnt get any return value, all we where told is that the code finished executing without error. This is often the case in more complex pieces of code which has no single obvious return value. To see the output from the <code class="docutils literal notranslate"><span class="pre">time_format()</span></code> function we need to tell the system to echo it to us explicitly with <code class="docutils literal notranslate"><span class="pre">self.msg()</span></code>.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@py</span> <span class="kn">from</span> <span class="nn">ev</span> <span class="k">import</span> <span class="n">utils</span><span class="p">;</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">utils</span><span class="o">.</span><span class="n">time_format</span><span class="p">(</span><span class="mi">33333</span><span class="p">)))</span>
<span class="mi">09</span><span class="p">:</span><span class="mi">15</span>
<span class="o">&lt;&lt;&lt;</span> <span class="n">Done</span><span class="o">.</span>
</pre></div>
</div>
<blockquote>
<div><p>Warning: When using the <code class="docutils literal notranslate"><span class="pre">msg</span></code> function wrap our argument in <code class="docutils literal notranslate"><span class="pre">str()</span></code> to convert it into a string above. This is not strictly necessary for most types of data (Evennia will usually convert to a string behind the scenes for you). But for <em>lists</em> and <em>tuples</em> you will be confused by the output if you dont wrap them in <code class="docutils literal notranslate"><span class="pre">str()</span></code>: only the first item of the iterable will be returned. This is because doing <code class="docutils literal notranslate"><span class="pre">msg(text)</span></code> is actually just a convenience shortcut; the full argument that <code class="docutils literal notranslate"><span class="pre">msg</span></code> accepts is something called an <em>outputfunc</em> on the form <code class="docutils literal notranslate"><span class="pre">(cmdname,</span> <span class="pre">(args),</span> <span class="pre">{kwargs})</span></code> (see <a class="reference internal" href="Messagepath.html"><span class="doc">the message path</span></a> for more info). Sending a list/tuple confuses Evennia to think you are sending such a structure. Converting it to a string however makes it clear it should just be displayed as-is.</p>
</div></blockquote>
<p>If you were to use Pythons standard <code class="docutils literal notranslate"><span class="pre">print</span></code>, you will see the result in your current <code class="docutils literal notranslate"><span class="pre">stdout</span></code> (your terminal by default, otherwise your log file).</p>
</div>
<div class="section" id="finding-objects">
<h2>Finding objects<a class="headerlink" href="#finding-objects" title="Permalink to this headline"></a></h2>
<p>A common use for <code class="docutils literal notranslate"><span class="pre">&#64;py</span></code> is to explore objects in the database, for debugging and performing specific operations that are not covered by a particular command.</p>
<p>Locating an object is best done using <code class="docutils literal notranslate"><span class="pre">self.search()</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@py</span> <span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">&quot;red_ball&quot;</span><span class="p">)</span>
<span class="o">&lt;&lt;&lt;</span> <span class="n">Ball</span>
<span class="nd">@py</span> <span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">&quot;red_ball&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">color</span> <span class="o">=</span> <span class="s2">&quot;red&quot;</span>
<span class="o">&lt;&lt;&lt;</span> <span class="n">Done</span><span class="o">.</span>
<span class="nd">@py</span> <span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s2">&quot;red_ball&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">color</span>
<span class="o">&lt;&lt;&lt;</span> <span class="n">red</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">self.search()</span></code> is by far the most used case, but you can also search other database tables for other Evennia entities like scripts or configuration entities. To do this you can use the generic search entries found in <code class="docutils literal notranslate"><span class="pre">ev.search_*</span></code>.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@py</span> <span class="n">evennia</span><span class="o">.</span><span class="n">search_script</span><span class="p">(</span><span class="s2">&quot;sys_game_time&quot;</span><span class="p">)</span>
<span class="o">&lt;&lt;&lt;</span> <span class="p">[</span><span class="o">&lt;</span><span class="n">src</span><span class="o">.</span><span class="n">utils</span><span class="o">.</span><span class="n">gametime</span><span class="o">.</span><span class="n">GameTime</span> <span class="nb">object</span> <span class="n">at</span> <span class="mh">0x852be2c</span><span class="o">&gt;</span><span class="p">]</span>
</pre></div>
</div>
<p>(Note that since this becomes a simple statement, we dont have to wrap it in <code class="docutils literal notranslate"><span class="pre">self.msg()</span></code> to get the output). You can also use the database model managers directly (accessible through the <code class="docutils literal notranslate"><span class="pre">objects</span></code> properties of database models or as <code class="docutils literal notranslate"><span class="pre">evennia.managers.*</span></code>). This is a bit more flexible since it gives you access to the full range of database search methods defined in each manager.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@py</span> <span class="n">evennia</span><span class="o">.</span><span class="n">managers</span><span class="o">.</span><span class="n">scripts</span><span class="o">.</span><span class="n">script_search</span><span class="p">(</span><span class="s2">&quot;sys_game_time&quot;</span><span class="p">)</span>
<span class="o">&lt;&lt;&lt;</span> <span class="p">[</span><span class="o">&lt;</span><span class="n">src</span><span class="o">.</span><span class="n">utils</span><span class="o">.</span><span class="n">gametime</span><span class="o">.</span><span class="n">GameTime</span> <span class="nb">object</span> <span class="n">at</span> <span class="mh">0x852be2c</span><span class="o">&gt;</span><span class="p">]</span>
</pre></div>
</div>
<p>The managers are useful for all sorts of database studies.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@py</span> <span class="n">ev</span><span class="o">.</span><span class="n">managers</span><span class="o">.</span><span class="n">configvalues</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
<span class="o">&lt;&lt;&lt;</span> <span class="p">[</span><span class="o">&lt;</span><span class="n">ConfigValue</span><span class="p">:</span> <span class="n">default_home</span><span class="p">]</span><span class="o">&gt;</span><span class="p">,</span> <span class="o">&lt;</span><span class="n">ConfigValue</span><span class="p">:</span><span class="n">site_name</span><span class="o">&gt;</span><span class="p">,</span> <span class="o">...</span><span class="p">]</span>
</pre></div>
</div>
</div>
<div class="section" id="testing-code-outside-the-game">
<h2>Testing code outside the game<a class="headerlink" href="#testing-code-outside-the-game" title="Permalink to this headline"></a></h2>
<p><code class="docutils literal notranslate"><span class="pre">&#64;py</span></code> has the advantage of operating inside a running server (sharing the same process), where you can test things in real time. Much of this <em>can</em> be done from the outside too though.</p>
<p>In a terminal, cd to the top of your game directory (this bit is important since we need access to your config file) and run</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">evennia</span> <span class="n">shell</span>
</pre></div>
</div>
<p>Your default Python interpreter will start up, configured to be able to work with and import all modules of your Evennia installation. From here you can explore the database and test-run individual modules as desired.</p>
<p>Its recommended that you get a more fully featured Python interpreter like <a class="reference external" href="http://ipython.scipy.org/moin/">iPython</a>. If you use a virtual environment, you can just get it with <code class="docutils literal notranslate"><span class="pre">pip</span> <span class="pre">install</span> <span class="pre">ipython</span></code>. IPython allows you to better work over several lines, and also has a lot of other editing features, such as tab-completion and <code class="docutils literal notranslate"><span class="pre">__doc__</span></code>-string reading.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ evennia shell
IPython 0.10 -- An enhanced Interactive Python
...
In [1]: import evennia
In [2]: evennia.managers.objects.all()
Out[3]: [&lt;ObjectDB: Harry&gt;, &lt;ObjectDB: Limbo&gt;, ...]
</pre></div>
</div>
<p>See the page about the <a class="reference internal" href="Evennia-API.html"><span class="doc">Evennia-API</span></a> for more things to explore.</p>
</div>
</div>
</div>
</div>
<footer>
<hr/>
<div role="contentinfo">
<p>
&copy; Copyright 2020, The Evennia developer community.
</p>
</div>
Built with <a href="http://sphinx-doc.org/">Sphinx</a> and ❤️ using a custom <a href="https://github.com/LinxiFan/Sphinx-theme">theme</a> based on <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT:'./',
VERSION:'0.9.1',
COLLAPSE_INDEX:false,
FILE_SUFFIX:'.html',
HAS_SOURCE: true,
SOURCELINK_SUFFIX: '.txt'
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/language_data.js"></script>
<script type="text/javascript" src="_static/js/theme.js"></script>
<script type="text/javascript">
jQuery(function () {
SphinxRtdTheme.StickyNav.enable();
});
</script>
</body>
</html>