Revert "Updated HTML docs."

This reverts commit 51d5840b8b.
This commit is contained in:
Griatch 2022-11-14 22:43:45 +01:00
parent 51d5840b8b
commit e34f258a92
2504 changed files with 820160 additions and 0 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,295 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Coding Introduction &#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" />
<link rel="next" title="Debugging" href="Debugging.html" />
<link rel="prev" title="Updating Your Game" href="Updating-Your-Game.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="right" >
<a href="Debugging.html" title="Debugging"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="Updating-Your-Game.html" title="Updating Your Game"
accesskey="P">previous</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="Coding-Overview.html" accesskey="U">Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Coding Introduction</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="document">
<div class="documentwrapper">
<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><a href="../index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Coding Introduction</a><ul>
<li><a class="reference internal" href="#start-with-the-tutorial">Start with the tutorial</a></li>
<li><a class="reference internal" href="#python">Python</a></li>
<li><a class="reference internal" href="#explore-evennia-interactively">Explore Evennia interactively</a><ul>
<li><a class="reference internal" href="#jupyter-notebook-support">Jupyter Notebook Support</a></li>
<li><a class="reference internal" href="#more-exploration">More exploration</a></li>
</ul>
</li>
<li><a class="reference internal" href="#use-a-python-syntax-checker">Use a python syntax checker</a></li>
<li><a class="reference internal" href="#plan-before-you-code">Plan before you code</a></li>
<li><a class="reference internal" href="#code-in-your-game-folder-not-in-the-evennia-repository">Code in your game folder, not in the evennia/ repository</a></li>
<li><a class="reference internal" href="#learn-to-read-tracebacks">Learn to read tracebacks</a></li>
<li><a class="reference internal" href="#docs-are-here-to-help-you">Docs are here to help you</a></li>
<li><a class="reference internal" href="#the-most-important-point">The most important point</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="Updating-Your-Game.html"
title="previous chapter">Updating Your Game</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="Debugging.html"
title="next chapter">Debugging</a></p>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Coding/Coding-Introduction.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com">Home page</a> </li>
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
<h3>Versions</h3>
<ul>
<li><a href="Coding-Introduction.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
</ul>
</div>
</div>
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="coding-introduction">
<h1>Coding Introduction<a class="headerlink" href="#coding-introduction" title="Permalink to this headline"></a></h1>
<p>Evennia allows for a lot of freedom when designing your game - but to code efficiently you still
need to adopt some best practices as well as find a good place to start to learn.</p>
<p>Here are some pointers to get you going.</p>
<section id="start-with-the-tutorial">
<h2>Start with the tutorial<a class="headerlink" href="#start-with-the-tutorial" title="Permalink to this headline"></a></h2>
<p>Its highly recommended that you jump in on the <a class="reference internal" href="../Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Part1-Intro.html"><span class="doc std std-doc">Starting Tutorial</span></a>. Even if
you only the beginning or some part of it, it covers much of the things needed to get started.</p>
</section>
<section id="python">
<h2>Python<a class="headerlink" href="#python" title="Permalink to this headline"></a></h2>
<p>Evennia is developed using Python. Even if you are more of a designer than a coder, it is wise to
learn how to read and understand basic Python code. If you are new to Python, or need a refresher,
take a look at our <a class="reference internal" href="../Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Python-basic-introduction.html"><span class="doc std std-doc">Python introduction</span></a>.</p>
</section>
<section id="explore-evennia-interactively">
<h2>Explore Evennia interactively<a class="headerlink" href="#explore-evennia-interactively" title="Permalink to this headline"></a></h2>
<p>When new to Evennia it can be hard to find things or figure out what is available. Evennia offers a
special interactive python shell that allows you to experiment and try out things. Its recommended
to use <a class="reference external" href="https://ipython.org/">ipython</a> for this since the vanilla python prompt is very limited. Here
are some simple commands to get started:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span># [open a new console/terminal]
# [activate your evennia virtualenv in this console/terminal]
pip install -r requirements_extra.txt # install ipython etc
cd mygame
evennia shell
</pre></div>
</div>
<p>This will open an Evennia-aware python shell (using ipython). From within this shell, try</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>import evennia
evennia.&lt;TAB&gt;
</pre></div>
</div>
<p>That is, enter <code class="docutils literal notranslate"><span class="pre">evennia.</span></code> and press the <code class="docutils literal notranslate"><span class="pre">&lt;TAB&gt;</span></code> key. This will show you all the resources made
available at the top level of Evennias “flat API”. See the <a class="reference internal" href="../Evennia-API.html"><span class="doc std std-doc">flat API</span></a> page for more
info on how to explore it efficiently.</p>
<section id="jupyter-notebook-support">
<h3>Jupyter Notebook Support<a class="headerlink" href="#jupyter-notebook-support" title="Permalink to this headline"></a></h3>
<p>You can also explore evennia interactively in a <a class="reference external" href="https://jupyter.readthedocs.io/en/latest/index.html">Jupyter notebook</a>. This offers
an in-browser view of your code similar to Matlab or similar programs. There are
a few extra steps that must be taken in order for this to work:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span># [open a new console/terminal]
# [activate your evennia virtualenv in this console/terminal]
cd evennia
pip install -r requirements_extra.txt # if not done already above
</pre></div>
</div>
<p>Next, <code class="docutils literal notranslate"><span class="pre">cd</span></code> to your game folder. <em>Its important that you are in the <em>root</em> of this folder for the next command</em>:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia shell_plus --notebook &amp;
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">&amp;</span></code> at the end starts the process as a background process on Linux/Unix.
Skip it if your OS doesnt support this syntax. Your browser should now open
with the Jupyter interface. If not, open a browser to the link given on the
command line.</p>
<p>In the window, open the <code class="docutils literal notranslate"><span class="pre">new</span></code> menu in the top right and start a <code class="docutils literal notranslate"><span class="pre">Django</span> <span class="pre">Shell-Plus</span></code> notebook (or
open an existing one if you had one from before). In the first cell you must initialize
Evennia like so:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">evennia</span>
<span class="n">evennia</span><span class="o">.</span><span class="n">_init</span><span class="p">()</span>
</pre></div>
</div>
<p><em>Note that the above initialization must be run every time a new new notebook/kernel is started or restarted.</em></p>
<p>After this you can import and access all of the Evennia system, same as with <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">shell</span></code>.</p>
</section>
<section id="more-exploration">
<h3>More exploration<a class="headerlink" href="#more-exploration" title="Permalink to this headline"></a></h3>
<p>You can complement your exploration by peeking at the sections of the much more detailed
<a class="reference internal" href="../Components/Components-Overview.html"><span class="doc std std-doc">Evennia Component overview</span></a>. The <a class="reference internal" href="../Howtos/Howtos-Overview.html"><span class="doc std std-doc">Tutorials</span></a> section also contains a growing collection
of system- or implementation-specific help.</p>
</section>
</section>
<section id="use-a-python-syntax-checker">
<h2>Use a python syntax checker<a class="headerlink" href="#use-a-python-syntax-checker" title="Permalink to this headline"></a></h2>
<p>Evennia works by importing your own modules and running them as part of the server. Whereas Evennia
should just gracefully tell you what errors it finds, it can nevertheless be a good idea for you to
check your code for simple syntax errors <em>before</em> you load it into the running server. There are
many python syntax checkers out there. A fast and easy one is
<a class="reference external" href="https://pypi.python.org/pypi/pyflakes">pyflakes</a>, a more verbose one is
<a class="reference external" href="https://www.pylint.org/">pylint</a>. You can also check so that your code looks up to snuff using
<a class="reference external" href="https://pypi.python.org/pypi/pep8">pep8</a>. Even with a syntax checker you will not be able to catch
every possible problem - some bugs or problems will only appear when you actually run the code. But
using such a checker can be a good start to weed out the simple problems.</p>
</section>
<section id="plan-before-you-code">
<h2>Plan before you code<a class="headerlink" href="#plan-before-you-code" title="Permalink to this headline"></a></h2>
<p>Before you start coding away at your dream game, take a look at our <a class="reference internal" href="../Howtos/Beginner-Tutorial/Part2/Beginner-Tutorial-Game-Planning.html"><span class="doc std std-doc">Game Planning</span></a>
page. It might hopefully help you avoid some common pitfalls and time sinks.</p>
</section>
<section id="code-in-your-game-folder-not-in-the-evennia-repository">
<h2>Code in your game folder, not in the evennia/ repository<a class="headerlink" href="#code-in-your-game-folder-not-in-the-evennia-repository" title="Permalink to this headline"></a></h2>
<p>As part of the Evennia setup you will create a game folder to host your game code. This is your
home. You should <em>never</em> need to modify anything in the <code class="docutils literal notranslate"><span class="pre">evennia</span></code> library (anything you download
from us, really). You import useful functionality from here and if you see code you like, copy&amp;paste
it out into your game folder and edit it there.</p>
<p>If you find that Evennia doesnt support some functionality you need, make a <a class="reference external" href="https://github.com/evennia/evennia/issues/new/choose">Feature
Request</a> about it. Same goes for [bugs][bug]. If you add features or fix bugs
yourself, please consider <a class="reference internal" href="../Contributing.html"><span class="doc std std-doc">Contributing</span></a> your changes upstream!</p>
</section>
<section id="learn-to-read-tracebacks">
<h2>Learn to read tracebacks<a class="headerlink" href="#learn-to-read-tracebacks" title="Permalink to this headline"></a></h2>
<p>Python is very good at reporting when and where things go wrong. A <em>traceback</em> shows everything you
need to know about crashing code. The text can be pretty long, but you usually are only interested
in the last bit, where it says what the error is and at which module and line number it happened -
armed with this info you can resolve most problems.</p>
<p>Evennia will usually not show the full traceback in-game though. Instead the server outputs errors
to the terminal/console from which you started Evennia in the first place. If you want more to show
in-game you can add <code class="docutils literal notranslate"><span class="pre">IN_GAME_ERRORS</span> <span class="pre">=</span> <span class="pre">True</span></code> to your settings file. This will echo most (but not all)
tracebacks both in-game as well as to the terminal/console. This is a potential security problem
though, so dont keep this active when your game goes into production.</p>
<blockquote>
<div><p>A common confusing error is finding that objects in-game are suddenly of the type <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code>
rather than your custom typeclass. This happens when you introduce a critical Syntax error to the
module holding your custom class. Since such a module is not valid Python, Evennia cant load it at
all. Instead of crashing, Evennia will then print the full traceback to the terminal/console and
temporarily fall back to the safe <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> until you fix the problem and reload.</p>
</div></blockquote>
</section>
<section id="docs-are-here-to-help-you">
<h2>Docs are here to help you<a class="headerlink" href="#docs-are-here-to-help-you" title="Permalink to this headline"></a></h2>
<p>Some people find reading documentation extremely dull and shun it out of principle. Thats your
call, but reading docs really <em>does</em> help you, promise! Evennias documentation is pretty thorough
and knowing what is possible can often give you a lot of new cool game ideas. That said, if you
cant find the answer in the docs, dont be shy to ask questions! The <a class="reference external" href="https://sites.google.com/site/evenniaserver/discussions">discussion
group</a> and the <a class="reference external" href="https://webchat.freenode.net/?channels=evennia">irc
chat</a> are also there for you.</p>
</section>
<section id="the-most-important-point">
<h2>The most important point<a class="headerlink" href="#the-most-important-point" title="Permalink to this headline"></a></h2>
<p>And finally, of course, have fun!</p>
<p>[feature-request]: (<a class="reference external" href="https://github.com/evennia/evennia/issues/new?title=Feature+Request%3a+%3Cdescriptive+title+here%3E&amp;body=%23%23%23%23+Description+of+the+suggested+feature+and+how+it+is+supposed+to+work+for+the+admin%2fend+user%3a%0D%0A%0D%0A%0D%0A%23%23%23%23+A+list+of+arguments+for+why+you+think+this+new+feature+should+be+included+in+Evennia%3a%0D%0A%0D%0A1.%0D%0A2.%0D%0A%0D%0A%23%23%23%23+Extra+information%2c+such+as+requirements+or+ideas+on+implementation%3a%0D%0A%0D%0A">https://github.com/evennia/evennia/issues/new?title=Feature+Request:+&lt;descriptive+title+here&gt;&amp;body=####+Description+of+the+suggested+feature+and+how+it+is+supposed+to+work+for+the+admin/end+user:
####+A+list+of+arguments+for+why+you+think+this+new+feature+should+be+included+in+Evennia:
1.
2.
####+Extra+information,+such+as+requirements+or+ideas+on+implementation:
</a>
<a class="reference external" href="https://github.com/evennia/evennia/issues/new?title=Bug%3a+%3Cdescriptive+title+here%3E&amp;body=%23%23%23%23+Steps+to+reproduce+the+issue%3a%0D%0A%0D%0A1.+%0D%0A2.+%0D%0A3.+%0D%0A%0D%0A%23%23%23%23+What+I+expect+to+see+and+what+I+actually+see+%28tracebacks%2c+error+messages+etc%29%3a%0D%0A%0D%0A%0D%0A%0D%0A%23%23%23%23+Extra+information%2c+such+as+Evennia+revision%2frepo%2fbranch%2c+operating+system+and+ideas+for+how+to+solve%3a%0D%0A%0D%0A">bug</a></p>
</section>
</section>
</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="right" >
<a href="Debugging.html" title="Debugging"
>next</a> |</li>
<li class="right" >
<a href="Updating-Your-Game.html" title="Updating Your Game"
>previous</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="Coding-Overview.html" >Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Coding Introduction</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>

View file

@ -0,0 +1,270 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Coding and development help &#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" />
<link rel="next" title="Version Control" href="Version-Control.html" />
<link rel="prev" title="Web Features" href="../Concepts/Web-Features.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="right" >
<a href="Version-Control.html" title="Version Control"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="../Concepts/Web-Features.html" title="Web Features"
accesskey="P">previous</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-this"><a href="">Coding and development help</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="document">
<div class="documentwrapper">
<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><a href="../index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Coding and development help</a><ul>
<li><a class="reference internal" href="#setting-up-a-workflow">Setting up a workflow</a></li>
<li><a class="reference internal" href="#coding-away">Coding away</a></li>
<li><a class="reference internal" href="#third-party-integrations">Third-party integrations</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="../Concepts/Web-Features.html"
title="previous chapter">Web Features</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="Version-Control.html"
title="next chapter">Version Control</a></p>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Coding/Coding-Overview.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com">Home page</a> </li>
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
<h3>Versions</h3>
<ul>
<li><a href="Coding-Overview.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
</ul>
</div>
</div>
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="coding-and-development-help">
<h1>Coding and development help<a class="headerlink" href="#coding-and-development-help" title="Permalink to this headline"></a></h1>
<p>This documentation aims to help you set up a sane development environment to
make your game, also if you never coded before. If you are an experienced coder, much of this will be familiar
to you, but some things may still be useful.</p>
<section id="setting-up-a-workflow">
<h2>Setting up a workflow<a class="headerlink" href="#setting-up-a-workflow" title="Permalink to this headline"></a></h2>
<p>See also the <a class="reference internal" href="../Howtos/Beginner-Tutorial/Beginner-Tutorial-Intro.html"><span class="doc std std-doc">Beginner Tutorial</span></a>.</p>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="Version-Control.html">Version Control</a><ul>
<li class="toctree-l2"><a class="reference internal" href="Version-Control.html#setting-up-git">Setting up Git</a></li>
<li class="toctree-l2"><a class="reference internal" href="Version-Control.html#putting-your-game-folder-under-version-control">Putting your game folder under version control</a></li>
<li class="toctree-l2"><a class="reference internal" href="Version-Control.html#forking-evennia">Forking Evennia</a></li>
<li class="toctree-l2"><a class="reference internal" href="Version-Control.html#working-with-your-evennia-fork">Working with your Evennia fork</a></li>
<li class="toctree-l2"><a class="reference internal" href="Version-Control.html#sharing-your-evennia-fixes-on-github">Sharing your Evennia fixes on Github</a></li>
<li class="toctree-l2"><a class="reference internal" href="Version-Control.html#making-an-evennia-pull-request">Making an Evennia Pull Request</a></li>
<li class="toctree-l2"><a class="reference internal" href="Version-Control.html#git-tips-and-tricks">GIT tips and tricks</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="Updating-Your-Game.html">Updating Your Game</a><ul>
<li class="toctree-l2"><a class="reference internal" href="Updating-Your-Game.html#updating-with-the-latest-evennia-code-changes">Updating with the latest Evennia code changes</a></li>
<li class="toctree-l2"><a class="reference internal" href="Updating-Your-Game.html#upgrading-evennia-dependencies">Upgrading Evennia dependencies</a></li>
<li class="toctree-l2"><a class="reference internal" href="Updating-Your-Game.html#migrating-the-database-schema">Migrating the Database Schema</a></li>
<li class="toctree-l2"><a class="reference internal" href="Updating-Your-Game.html#resetting-your-database">Resetting your database</a></li>
<li class="toctree-l2"><a class="reference internal" href="Updating-Your-Game.html#more-about-schema-migrations">More about schema migrations</a></li>
</ul>
</li>
</ul>
</div>
</section>
<section id="coding-away">
<h2>Coding away<a class="headerlink" href="#coding-away" title="Permalink to this headline"></a></h2>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="Coding-Introduction.html">Coding Introduction</a><ul>
<li class="toctree-l2"><a class="reference internal" href="Coding-Introduction.html#start-with-the-tutorial">Start with the tutorial</a></li>
<li class="toctree-l2"><a class="reference internal" href="Coding-Introduction.html#python">Python</a></li>
<li class="toctree-l2"><a class="reference internal" href="Coding-Introduction.html#explore-evennia-interactively">Explore Evennia interactively</a></li>
<li class="toctree-l2"><a class="reference internal" href="Coding-Introduction.html#use-a-python-syntax-checker">Use a python syntax checker</a></li>
<li class="toctree-l2"><a class="reference internal" href="Coding-Introduction.html#plan-before-you-code">Plan before you code</a></li>
<li class="toctree-l2"><a class="reference internal" href="Coding-Introduction.html#code-in-your-game-folder-not-in-the-evennia-repository">Code in your game folder, not in the evennia/ repository</a></li>
<li class="toctree-l2"><a class="reference internal" href="Coding-Introduction.html#learn-to-read-tracebacks">Learn to read tracebacks</a></li>
<li class="toctree-l2"><a class="reference internal" href="Coding-Introduction.html#docs-are-here-to-help-you">Docs are here to help you</a></li>
<li class="toctree-l2"><a class="reference internal" href="Coding-Introduction.html#the-most-important-point">The most important point</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="Debugging.html">Debugging</a><ul>
<li class="toctree-l2"><a class="reference internal" href="Debugging.html#debugging-evennia">Debugging Evennia</a></li>
<li class="toctree-l2"><a class="reference internal" href="Debugging.html#a-simple-example-using-pdb">A simple example using pdb</a></li>
<li class="toctree-l2"><a class="reference internal" href="Debugging.html#cheat-sheet-of-pdb-pudb-commands">Cheat-sheet of pdb/pudb commands</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="Unit-Testing.html">Unit Testing</a><ul>
<li class="toctree-l2"><a class="reference internal" href="Unit-Testing.html#running-the-evennia-test-suite">Running the Evennia test suite</a></li>
<li class="toctree-l2"><a class="reference internal" href="Unit-Testing.html#running-tests-for-your-game-dir">Running tests for your game dir</a></li>
<li class="toctree-l2"><a class="reference internal" href="Unit-Testing.html#writing-new-tests">Writing new tests</a></li>
<li class="toctree-l2"><a class="reference internal" href="Unit-Testing.html#using-the-evennia-testing-classes">Using the Evennia testing classes</a></li>
<li class="toctree-l2"><a class="reference internal" href="Unit-Testing.html#unit-testing-contribs-with-custom-models">Unit testing contribs with custom models</a></li>
<li class="toctree-l2"><a class="reference internal" href="Unit-Testing.html#a-note-on-making-the-test-runner-faster">A note on making the test runner faster</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="Profiling.html">Profiling</a><ul>
<li class="toctree-l2"><a class="reference internal" href="Profiling.html#introduction">Introduction</a></li>
<li class="toctree-l2"><a class="reference internal" href="Profiling.html#simple-timer-tests">Simple timer tests</a></li>
<li class="toctree-l2"><a class="reference internal" href="Profiling.html#using-cprofile">Using cProfile</a></li>
<li class="toctree-l2"><a class="reference internal" href="Profiling.html#the-dummyrunner">The Dummyrunner</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="Quirks.html">Quirks</a><ul>
<li class="toctree-l2"><a class="reference internal" href="Quirks.html#forgetting-to-use-reload-to-see-changes-to-your-typeclasses">Forgetting to use <code class="docutils literal notranslate"><span class="pre">reload</span></code> to see changes to your typeclasses</a></li>
<li class="toctree-l2"><a class="reference internal" href="Quirks.html#web-admin-to-create-new-account">Web admin to create new Account</a></li>
<li class="toctree-l2"><a class="reference internal" href="Quirks.html#mutable-attributes-and-their-connection-to-the-database">Mutable attributes and their connection to the database</a></li>
<li class="toctree-l2"><a class="reference internal" href="Quirks.html#commands-are-matched-by-name-or-alias">Commands are matched by name <em>or</em> alias</a></li>
<li class="toctree-l2"><a class="reference internal" href="Quirks.html#objects-turning-to-defaultobject">Objects turning to <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="Quirks.html#overriding-of-magic-methods">Overriding of magic methods</a></li>
<li class="toctree-l2"><a class="reference internal" href="Quirks.html#things-to-remember-about-the-flat-api">Things to remember about the flat API</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="Changelog.html">Changelog</a><ul>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#evennia-1-0">Evennia 1.0</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#evennia-0-9-5">Evennia 0.9.5</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#evennia-0-9">Evennia 0.9</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#evennia-0-8">Evennia 0.8</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="Changelog.html#overview-changelogs">Overview-Changelogs</a><ul>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#sept-2017">Sept 2017:</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#feb-2017">Feb 2017:</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#dec-2016">Dec 2016:</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#may-2016">May 2016:</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#feb-2016">Feb 2016:</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#sept-2015">Sept 2015:</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#feb-2015">Feb 2015:</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#sept-2014">Sept 2014:</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#jan-2014">Jan 2014:</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#nov-2013">Nov 2013:</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#may-2013">May 2013:</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#oct-2012">Oct 2012:</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#march-2012">March 2012:</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#nov-2011">Nov 2011:</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#aug-2011">Aug 2011:</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#may-2011">May 2011:</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#aug-2010">Aug 2010:</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#may-2010">May 2010:</a></li>
<li class="toctree-l2"><a class="reference internal" href="Changelog.html#april-2010">April 2010:</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="Changelog.html#older">Older</a></li>
</ul>
</div>
</section>
<section id="third-party-integrations">
<h2>Third-party integrations<a class="headerlink" href="#third-party-integrations" title="Permalink to this headline"></a></h2>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="Continuous-Integration.html">Continuous Integration</a><ul>
<li class="toctree-l2"><a class="reference internal" href="Continuous-Integration.html#what-is-continuous-integration-ci">What is Continuous Integration (CI)?</a></li>
<li class="toctree-l2"><a class="reference internal" href="Continuous-Integration.html#list-of-continuous-integration-tools">List of continuous integration tools</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="Setting-up-PyCharm.html">Setting up PyCharm with Evennia</a><ul>
<li class="toctree-l2"><a class="reference internal" href="Setting-up-PyCharm.html#setting-up-the-project-interpreter">Setting up the project interpreter</a></li>
<li class="toctree-l2"><a class="reference internal" href="Setting-up-PyCharm.html#attaching-pycharm-debugger-to-evennia">Attaching PyCharm debugger to Evennia</a></li>
<li class="toctree-l2"><a class="reference internal" href="Setting-up-PyCharm.html#setting-up-an-evennia-run-configuration">Setting up an Evennia run configuration</a></li>
<li class="toctree-l2"><a class="reference internal" href="Setting-up-PyCharm.html#alternative-run-configuration-utilizing-logfiles-as-source-of-data">Alternative run configuration - utilizing logfiles as source of data</a></li>
</ul>
</li>
</ul>
</div>
</section>
</section>
</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="right" >
<a href="Version-Control.html" title="Version Control"
>next</a> |</li>
<li class="right" >
<a href="../Concepts/Web-Features.html" title="Web Features"
>previous</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-this"><a href="">Coding and development help</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>

View file

@ -0,0 +1,326 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Continuous Integration - TeamCity (linux) &#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" />
<link rel="next" title="Setting up PyCharm with Evennia" href="Setting-up-PyCharm.html" />
<link rel="prev" title="Continuous integration with Travis" href="Continuous-Integration-Travis.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="right" >
<a href="Setting-up-PyCharm.html" title="Setting up PyCharm with Evennia"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="Continuous-Integration-Travis.html" title="Continuous integration with Travis"
accesskey="P">previous</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="Coding-Overview.html" >Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-2"><a href="Continuous-Integration.html" accesskey="U">Continuous Integration</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Continuous Integration - TeamCity (linux)</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="document">
<div class="documentwrapper">
<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><a href="../index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Continuous Integration - TeamCity (linux)</a><ul>
<li><a class="reference internal" href="#prerequisites">Prerequisites</a></li>
<li><a class="reference internal" href="#a-quick-overview">A Quick Overview</a></li>
<li><a class="reference internal" href="#template-setup">Template Setup</a><ul>
<li><a class="reference internal" href="#creating-the-project">Creating the Project</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="Continuous-Integration-Travis.html"
title="previous chapter">Continuous integration with Travis</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="Setting-up-PyCharm.html"
title="next chapter">Setting up PyCharm with Evennia</a></p>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Coding/Continuous-Integration-TeamCity.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com">Home page</a> </li>
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
<h3>Versions</h3>
<ul>
<li><a href="Continuous-Integration-TeamCity.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
</ul>
</div>
</div>
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="continuous-integration-teamcity-linux">
<h1>Continuous Integration - TeamCity (linux)<a class="headerlink" href="#continuous-integration-teamcity-linux" title="Permalink to this headline"></a></h1>
<p>This sets up a TeamCity build integration environment on Linux.</p>
<section id="prerequisites">
<h2>Prerequisites<a class="headerlink" href="#prerequisites" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li><p>Follow <a class="reference external" href="https://www.jetbrains.com/teamcity/">TeamCity</a> s in-depth
<a class="reference external" href="https://confluence.jetbrains.com/display/TCD8/Installing+and+Configuring+the+TeamCity+Server">Setup Guide</a>.</p></li>
<li><p>You need to use <a class="reference internal" href="Version-Control.html"><span class="doc std std-doc">Version Control</span></a>.</p></li>
</ul>
<p>After meeting the preparation steps for your specific environment, log on to your teamcity interface
at <code class="docutils literal notranslate"><span class="pre">http://&lt;your</span> <span class="pre">server&gt;:8111/</span></code>.</p>
<p>Create a new project named “Evennia” and in it construct a new template called <code class="docutils literal notranslate"><span class="pre">continuous-integration</span></code>.</p>
</section>
<section id="a-quick-overview">
<h2>A Quick Overview<a class="headerlink" href="#a-quick-overview" title="Permalink to this headline"></a></h2>
<p><em>Templates</em> are fancy objects in TeamCity that allow an administrator to define build steps that are
shared between one or more build projects. Assigning a VCS Root (Source Control) is unnecessary at
this stage, primarily youll be worrying about the build steps and your default parameters (both
visible on the tabs to the left.)</p>
</section>
<section id="template-setup">
<h2>Template Setup<a class="headerlink" href="#template-setup" title="Permalink to this headline"></a></h2>
<p>In this template, youll be outlining the steps necessary to build your specific game. (A number of
sample scripts are provided under this section below!) Click Build Steps and prepare your general
flow. For this example, we will be doing a few basic example steps:</p>
<ul class="simple">
<li><p>Transforming the <a class="reference external" href="http://Settings.py">Settings.py</a> file - We do this to update ports or other information that make your production
environment unique from your development environment.</p></li>
<li><p>Making migrations and migrating the game database.</p></li>
<li><p>Publishing the game files.</p></li>
<li><p>Reloading the server.</p></li>
</ul>
<p>For each step well being use the “Command Line Runner” (a fancy name for a shell script executor).</p>
<p>Create a build step with the name: “Transform Configuration” and add the script:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span>
<span class="c1"># Replaces the game configuration with one </span>
<span class="c1"># appropriate for this deployment.</span>
<span class="nv">CONFIG</span><span class="o">=</span><span class="s2">&quot;%system.teamcity.build.checkoutDir%/server/conf/settings.py&quot;</span>
<span class="nv">MYCONF</span><span class="o">=</span><span class="s2">&quot;%system.teamcity.build.checkoutDir%/server/conf/my.cnf&quot;</span>
sed -e <span class="s1">&#39;s/TELNET_PORTS = [4000]/TELNET_PORTS = [%game.ports%]/g&#39;</span> <span class="s2">&quot;</span><span class="nv">$CONFIG</span><span class="s2">&quot;</span> &gt; <span class="s2">&quot;</span><span class="nv">$CONFIG</span><span class="s2">&quot;</span>.tmp <span class="o">&amp;&amp;</span> mv
<span class="s2">&quot;</span><span class="nv">$CONFIG</span><span class="s2">&quot;</span>.tmp <span class="s2">&quot;</span><span class="nv">$CONFIG</span><span class="s2">&quot;</span>
sed -e <span class="s1">&#39;s/WEBSERVER_PORTS = [(4001, 4002)]/WEBSERVER_PORTS = [%game.webports%]/g&#39;</span> <span class="s2">&quot;</span><span class="nv">$CONFIG</span><span class="s2">&quot;</span> &gt;
<span class="s2">&quot;</span><span class="nv">$CONFIG</span><span class="s2">&quot;</span>.tmp <span class="o">&amp;&amp;</span> mv <span class="s2">&quot;</span><span class="nv">$CONFIG</span><span class="s2">&quot;</span>.tmp <span class="s2">&quot;</span><span class="nv">$CONFIG</span><span class="s2">&quot;</span>
</pre></div>
</div>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="c1"># settings.py MySQL DB configuration</span>
<span class="nb">echo</span> Configuring Game Database...
<span class="nb">echo</span> <span class="s2">&quot;&quot;</span> &gt;&gt; <span class="s2">&quot;</span><span class="nv">$CONFIG</span><span class="s2">&quot;</span>
<span class="nb">echo</span> <span class="s2">&quot;######################################################################&quot;</span> &gt;&gt; <span class="s2">&quot;</span><span class="nv">$CONFIG</span><span class="s2">&quot;</span>
<span class="nb">echo</span> <span class="s2">&quot;# MySQL Database Configuration&quot;</span> &gt;&gt; <span class="s2">&quot;</span><span class="nv">$CONFIG</span><span class="s2">&quot;</span>
<span class="nb">echo</span> <span class="s2">&quot;######################################################################&quot;</span> &gt;&gt; <span class="s2">&quot;</span><span class="nv">$CONFIG</span><span class="s2">&quot;</span>
<span class="nb">echo</span> <span class="s2">&quot;DATABASES = {&quot;</span> &gt;&gt; <span class="s2">&quot;</span><span class="nv">$CONFIG</span><span class="s2">&quot;</span>
<span class="nb">echo</span> <span class="s2">&quot; &#39;default&#39;: {&quot;</span> &gt;&gt; <span class="s2">&quot;</span><span class="nv">$CONFIG</span><span class="s2">&quot;</span>
<span class="nb">echo</span> <span class="s2">&quot; &#39;ENGINE&#39;: &#39;django.db.backends.mysql&#39;,&quot;</span> &gt;&gt; <span class="s2">&quot;</span><span class="nv">$CONFIG</span><span class="s2">&quot;</span>
<span class="nb">echo</span> <span class="s2">&quot; &#39;OPTIONS&#39;: {&quot;</span> &gt;&gt; <span class="s2">&quot;</span><span class="nv">$CONFIG</span><span class="s2">&quot;</span>
<span class="nb">echo</span> <span class="s2">&quot; &#39;read_default_file&#39;: &#39;server/conf/my.cnf&#39;,&quot;</span> &gt;&gt; <span class="s2">&quot;</span><span class="nv">$CONFIG</span><span class="s2">&quot;</span>
<span class="nb">echo</span> <span class="s2">&quot; },&quot;</span> &gt;&gt; <span class="s2">&quot;</span><span class="nv">$CONFIG</span><span class="s2">&quot;</span>
<span class="nb">echo</span> <span class="s2">&quot; }&quot;</span> &gt;&gt; <span class="s2">&quot;</span><span class="nv">$CONFIG</span><span class="s2">&quot;</span>
<span class="nb">echo</span> <span class="s2">&quot;}&quot;</span> &gt;&gt; <span class="s2">&quot;</span><span class="nv">$CONFIG</span><span class="s2">&quot;</span>
<span class="c1"># Create the My.CNF file.</span>
<span class="nb">echo</span> <span class="s2">&quot;[client]&quot;</span> &gt;&gt; <span class="s2">&quot;</span><span class="nv">$MYCONF</span><span class="s2">&quot;</span>
<span class="nb">echo</span> <span class="s2">&quot;database = %mysql.db%&quot;</span> &gt;&gt; <span class="s2">&quot;</span><span class="nv">$MYCONF</span><span class="s2">&quot;</span>
<span class="nb">echo</span> <span class="s2">&quot;user = %mysql.user%&quot;</span> &gt;&gt; <span class="s2">&quot;</span><span class="nv">$MYCONF</span><span class="s2">&quot;</span>
<span class="nb">echo</span> <span class="s2">&quot;password = %mysql.pass%&quot;</span> &gt;&gt; <span class="s2">&quot;</span><span class="nv">$MYCONF</span><span class="s2">&quot;</span>
<span class="nb">echo</span> <span class="s2">&quot;default-character-set = utf8&quot;</span> &gt;&gt; <span class="s2">&quot;</span><span class="nv">$MYCONF</span><span class="s2">&quot;</span>
</pre></div>
</div>
<p>If you look at the parameters side of the page after saving this script, youll notice that some new
parameters have been populated for you. This is because weve included new teamcity configuration
parameters that are populated when the build itself is ran. When creating projects that inherit this
template, well be able to fill in or override those parameters for project-specific configuration.</p>
<p>Go ahead and create another build step called “Make Database Migration”
If youre using Sqlite3 for your game (default database), its prudent to change working directory on this
step to your game dir.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span>
<span class="c1"># Update the DB migration</span>
<span class="nv">LOGDIR</span><span class="o">=</span><span class="s2">&quot;server/logs&quot;</span>
. %evenv.dir%/bin/activate
<span class="c1"># Check that the logs directory exists.</span>
<span class="k">if</span> <span class="o">[</span> ! -d <span class="s2">&quot;</span><span class="nv">$LOGDIR</span><span class="s2">&quot;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
<span class="c1"># Control will enter here if $LOGDIR doesn&#39;t exist.</span>
mkdir <span class="s2">&quot;</span><span class="nv">$LOGDIR</span><span class="s2">&quot;</span>
<span class="k">fi</span>
evennia makemigrations
</pre></div>
</div>
<p>Create yet another build step, this time named: “Execute Database Migration”:
If youre using Sqlite3 for your game (default database), its prudent to change working directory on this
step to your game dir.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span>
<span class="c1"># Apply the database migration.</span>
<span class="nv">LOGDIR</span><span class="o">=</span><span class="s2">&quot;server/logs&quot;</span>
. %evenv.dir%/bin/activate
<span class="c1"># Check that the logs directory exists.</span>
<span class="k">if</span> <span class="o">[</span> ! -d <span class="s2">&quot;</span><span class="nv">$LOGDIR</span><span class="s2">&quot;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
<span class="c1"># Control will enter here if $LOGDIR doesn&#39;t exist.</span>
mkdir <span class="s2">&quot;</span><span class="nv">$LOGDIR</span><span class="s2">&quot;</span>
<span class="k">fi</span>
evennia migrate
</pre></div>
</div>
<p>Our next build step is where we actually publish our build. Up until now, all work on game has been
done in a work directory on TeamCitys build agent. From that directory we will now copy our files
to where our game actually exists on the local server.</p>
<p>Create a new build step called “Publish Build”. If youre using SQlite3 on your game, be sure to order this step ABOVE
the Database Migration steps. The build order will matter!</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span>
<span class="c1"># Publishes the build to the proper build directory.</span>
<span class="nv">DIRECTORY</span><span class="o">=</span><span class="s2">&quot;&lt;game_dir&gt;&quot;</span>
<span class="k">if</span> <span class="o">[</span> ! -d <span class="s2">&quot;</span><span class="nv">$DIRECTORY</span><span class="s2">&quot;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
<span class="c1"># Control will enter here if $DIRECTORY doesn&#39;t exist.</span>
mkdir <span class="s2">&quot;</span><span class="nv">$DIRECTORY</span><span class="s2">&quot;</span>
<span class="k">fi</span>
<span class="c1"># Copy all the files.</span>
cp -ruv %teamcity.build.checkoutDir%/* <span class="s2">&quot;</span><span class="nv">$DIRECTORY</span><span class="s2">&quot;</span>
chmod -R <span class="m">775</span> <span class="s2">&quot;</span><span class="nv">$DIRECTORY</span><span class="s2">&quot;</span>
</pre></div>
</div>
<p>Finally the last script will reload our game for us.</p>
<p>Create a new script called “Reload Game”:
The working directory on this build step will be: <code class="docutils literal notranslate"><span class="pre">%game.dir%</span></code></p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span>
<span class="c1"># Apply the database migration.</span>
<span class="nv">LOGDIR</span><span class="o">=</span><span class="s2">&quot;server/logs&quot;</span>
<span class="nv">PIDDIR</span><span class="o">=</span><span class="s2">&quot;server/server.pid&quot;</span>
. %evenv.dir%/bin/activate
<span class="c1"># Check that the logs directory exists.</span>
<span class="k">if</span> <span class="o">[</span> ! -d <span class="s2">&quot;</span><span class="nv">$LOGDIR</span><span class="s2">&quot;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
<span class="c1"># Control will enter here if $LOGDIR doesn&#39;t exist.</span>
mkdir <span class="s2">&quot;</span><span class="nv">$LOGDIR</span><span class="s2">&quot;</span>
<span class="k">fi</span>
<span class="c1"># Check that the server is running.</span>
<span class="k">if</span> <span class="o">[</span> -d <span class="s2">&quot;</span><span class="nv">$PIDDIR</span><span class="s2">&quot;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
<span class="c1"># Control will enter here if the game is running.</span>
evennia reload
<span class="k">fi</span>
</pre></div>
</div>
<p>Now the template is ready for use! It would be useful this time to revisit the parameters page and
set the evenv parameter to the directory where your virtualenv exists: IE “/srv/mush/evenv”.</p>
<section id="creating-the-project">
<h3>Creating the Project<a class="headerlink" href="#creating-the-project" title="Permalink to this headline"></a></h3>
<p>Now its time for the last few steps to set up a CI environment.</p>
<ul class="simple">
<li><p>Return to the Evennia Project overview/administration page.</p></li>
<li><p>Create a new Sub-Project called “Production”. This will be the category that holds our actual game.</p></li>
<li><p>Create a new Build Configuration in Production with the name of your MUSH. Base this configuration off of the
continuous-integration template we made earlier.</p></li>
<li><p>In the build configuration, enter VCS roots and create a new VCS root that points to the
branch/version control that you are using.</p></li>
<li><p>Go to the parameters page and fill in the undefined parameters for your specific configuration.</p></li>
<li><p>If you wish for the CI to run every time a commit is made, go to the VCS triggers and add one for
“On Every Commit”.</p></li>
</ul>
<p>And youre done! At this point, you can return to the project overview page and queue a new build
for your game. If everything was set up correctly, the build will complete successfully. Additional
build steps could be added or removed at this point, adding some features like Unit Testing or more!</p>
</section>
</section>
</section>
</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="right" >
<a href="Setting-up-PyCharm.html" title="Setting up PyCharm with Evennia"
>next</a> |</li>
<li class="right" >
<a href="Continuous-Integration-Travis.html" title="Continuous integration with Travis"
>previous</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="Coding-Overview.html" >Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-2"><a href="Continuous-Integration.html" >Continuous Integration</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Continuous Integration - TeamCity (linux)</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>

View file

@ -0,0 +1,166 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Continuous integration with Travis &#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" />
<link rel="next" title="Continuous Integration - TeamCity (linux)" href="Continuous-Integration-TeamCity.html" />
<link rel="prev" title="Continuous Integration" href="Continuous-Integration.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="right" >
<a href="Continuous-Integration-TeamCity.html" title="Continuous Integration - TeamCity (linux)"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="Continuous-Integration.html" title="Continuous Integration"
accesskey="P">previous</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="Coding-Overview.html" >Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-2"><a href="Continuous-Integration.html" accesskey="U">Continuous Integration</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Continuous integration with Travis</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="document">
<div class="documentwrapper">
<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>
<h4>Previous topic</h4>
<p class="topless"><a href="Continuous-Integration.html"
title="previous chapter">Continuous Integration</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="Continuous-Integration-TeamCity.html"
title="next chapter">Continuous Integration - TeamCity (linux)</a></p>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Coding/Continuous-Integration-Travis.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com">Home page</a> </li>
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
<h3>Versions</h3>
<ul>
<li><a href="Continuous-Integration-Travis.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
</ul>
</div>
</div>
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="continuous-integration-with-travis">
<h1>Continuous integration with Travis<a class="headerlink" href="#continuous-integration-with-travis" title="Permalink to this headline"></a></h1>
<p><a class="reference external" href="https://travis-ci.org/">Travis CI</a> is an online service for checking, validating and potentially
deploying code automatically. It can check that every commit is building successfully after every
commit to its Github repository.</p>
<p>If your game is open source on Github you may use Travis for free.
See [the Travis docs](<a class="reference external" href="https://docs.travis-ci.com/user/getting-">https://docs.travis-ci.com/user/getting-</a> started/) for how to get started.</p>
<p>After logging in you will get to point Travis to your repository on github. One further thing you
need to set up yourself is a Travis config file named <code class="docutils literal notranslate"><span class="pre">.travis.yml</span></code> (note the initial period <code class="docutils literal notranslate"><span class="pre">.</span></code>).
This should be created in the root of your game directory. The idea with this file is that it
describes what Travis needs to import and build in order to create an instance of Evennia from
scratch and then run validation tests on it. Here is an example:</p>
<div class="highlight-yaml notranslate"><div class="highlight"><pre><span></span><span class="nt">language</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">python</span><span class="w"></span>
<span class="nt">python</span><span class="p">:</span><span class="w"></span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="s">&quot;3.10&quot;</span><span class="w"></span>
<span class="nt">install</span><span class="p">:</span><span class="w"></span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">git clone https://github.com/evennia/evennia.git</span><span class="w"></span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">cd evennia</span><span class="w"></span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">pip install -e .</span><span class="w"></span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">cd $TRAVIS_BUILD_DIR</span><span class="w"></span>
<span class="nt">script</span><span class="p">:</span><span class="w"></span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">evennia migrate</span><span class="w"></span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">evennia test --settings settings.py .</span><span class="w"></span>
</pre></div>
</div>
<p>This will tell travis how to download Evennia, install it, set up a database and then run
your own test suite (inside the game dir). Use <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">test</span> <span class="pre">evennia</span></code> if you also want to
run the Evennia full test suite.</p>
<p>You need to add this file to git (<code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">add</span> <span class="pre">.travis.yml</span></code>) and then commit your changes before Travis
will be able to see it.</p>
<p>For properly testing your game you of course also need to write unittests.
The <a class="reference internal" href="Unit-Testing.html"><span class="doc std std-doc">Unit testing</span></a> doc page gives some ideas on how to set those up for Evennia.
You should be able to refer to that for making tests fitting your game.</p>
</section>
</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="right" >
<a href="Continuous-Integration-TeamCity.html" title="Continuous Integration - TeamCity (linux)"
>next</a> |</li>
<li class="right" >
<a href="Continuous-Integration.html" title="Continuous Integration"
>previous</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="Coding-Overview.html" >Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-2"><a href="Continuous-Integration.html" >Continuous Integration</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Continuous integration with Travis</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>

View file

@ -0,0 +1,173 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Continuous Integration &#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" />
<link rel="next" title="Continuous integration with Travis" href="Continuous-Integration-Travis.html" />
<link rel="prev" title="Changelog" href="Changelog.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="right" >
<a href="Continuous-Integration-Travis.html" title="Continuous integration with Travis"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="Changelog.html" title="Changelog"
accesskey="P">previous</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="Coding-Overview.html" accesskey="U">Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Continuous Integration</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="document">
<div class="documentwrapper">
<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><a href="../index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Continuous Integration</a><ul>
<li><a class="reference internal" href="#what-is-continuous-integration-ci">What is Continuous Integration (CI)?</a></li>
<li><a class="reference internal" href="#list-of-continuous-integration-tools">List of continuous integration tools</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="Changelog.html"
title="previous chapter">Changelog</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="Continuous-Integration-Travis.html"
title="next chapter">Continuous integration with Travis</a></p>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Coding/Continuous-Integration.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com">Home page</a> </li>
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
<h3>Versions</h3>
<ul>
<li><a href="Continuous-Integration.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
</ul>
</div>
</div>
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="continuous-integration">
<h1>Continuous Integration<a class="headerlink" href="#continuous-integration" title="Permalink to this headline"></a></h1>
<p>One of the advantages of Evennia over traditional MU* development systems is that Evennia can
integrate into enterprise-level integration environments and source control.</p>
<section id="what-is-continuous-integration-ci">
<h2>What is Continuous Integration (CI)?<a class="headerlink" href="#what-is-continuous-integration-ci" title="Permalink to this headline"></a></h2>
<p><a class="reference external" href="https://www.thoughtworks.com/continuous-integration">Continuous Integration (CI)</a> is a development
practice that requires developers to integrate code into a shared repository.
Each check-in is then verified by an automated build, allowing teams to detect problems early. This
can be set up to safely deploy data to a production server only after tests have passed, for example.</p>
<p>For Evennia, continuous integration allows an automated build process to:</p>
<ul class="simple">
<li><p>Pull down a latest build from Source Control.</p></li>
<li><p>Run migrations on the backing SQL database.</p></li>
<li><p>Automate additional unique tasks for that project.</p></li>
<li><p>Run unit tests.</p></li>
<li><p>Publish those files to the server directory</p></li>
<li><p>Reload the game.</p></li>
</ul>
</section>
<section id="list-of-continuous-integration-tools">
<h2>List of continuous integration tools<a class="headerlink" href="#list-of-continuous-integration-tools" title="Permalink to this headline"></a></h2>
<p>There are a lot of tools and services providing CI functionality. Here are a few that people have used
with Evennia:</p>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="Continuous-Integration-Travis.html">Continuous integration with Travis</a></li>
<li class="toctree-l1"><a class="reference internal" href="Continuous-Integration-TeamCity.html">Continuous Integration - TeamCity (linux)</a></li>
</ul>
</div>
<p><a class="reference external" href="https://www.atlassian.com/continuous-delivery/continuous-integration/tools">This is an overview of other tools</a>
(external link).</p>
</section>
</section>
</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="right" >
<a href="Continuous-Integration-Travis.html" title="Continuous integration with Travis"
>next</a> |</li>
<li class="right" >
<a href="Changelog.html" title="Changelog"
>previous</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="Coding-Overview.html" >Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Continuous Integration</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>

View file

@ -0,0 +1,429 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Debugging &#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" />
<link rel="next" title="Unit Testing" href="Unit-Testing.html" />
<link rel="prev" title="Coding Introduction" href="Coding-Introduction.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="right" >
<a href="Unit-Testing.html" title="Unit Testing"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="Coding-Introduction.html" title="Coding Introduction"
accesskey="P">previous</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="Coding-Overview.html" accesskey="U">Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Debugging</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="document">
<div class="documentwrapper">
<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><a href="../index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Debugging</a><ul>
<li><a class="reference internal" href="#debugging-evennia">Debugging Evennia</a></li>
<li><a class="reference internal" href="#a-simple-example-using-pdb">A simple example using pdb</a><ul>
<li><a class="reference internal" href="#listing-surrounding-lines-of-code">Listing surrounding lines of code</a></li>
<li><a class="reference internal" href="#examining-variables">Examining variables</a></li>
<li><a class="reference internal" href="#executing-the-current-line">Executing the current line</a></li>
<li><a class="reference internal" href="#letting-the-program-run">Letting the program run</a></li>
<li><a class="reference internal" href="#stepping-through-a-function">Stepping through a function</a></li>
</ul>
</li>
<li><a class="reference internal" href="#cheat-sheet-of-pdb-pudb-commands">Cheat-sheet of pdb/pudb commands</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="Coding-Introduction.html"
title="previous chapter">Coding Introduction</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="Unit-Testing.html"
title="next chapter">Unit Testing</a></p>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Coding/Debugging.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com">Home page</a> </li>
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
<h3>Versions</h3>
<ul>
<li><a href="Debugging.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
</ul>
</div>
</div>
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="debugging">
<h1>Debugging<a class="headerlink" href="#debugging" title="Permalink to this headline"></a></h1>
<p>Sometimes, an error is not trivial to resolve. A few simple <code class="docutils literal notranslate"><span class="pre">print</span></code> statements is not enough to find
the cause of the issue. Running a <em>debugger</em> can then be very helpful and save a lot of time.
Debugging
means running Evennia under control of a special <em>debugger</em> program. This allows you to stop the
action at a given point, view the current state and step forward through the program to see how its
logic works.</p>
<p>Evennia natively supports these debuggers:</p>
<ul class="simple">
<li><p><a class="reference external" href="https://docs.python.org/2/library/pdb.html">Pdb</a> is a part of the Python distribution and
available out-of-the-box.</p></li>
<li><p><a class="reference external" href="https://pypi.org/project/pudb/">PuDB</a> is a third-party debugger that has a slightly more
graphical, curses-based user interface than pdb. It is installed with <code class="docutils literal notranslate"><span class="pre">pip</span> <span class="pre">install</span> <span class="pre">pudb</span></code>.</p></li>
</ul>
<section id="debugging-evennia">
<h2>Debugging Evennia<a class="headerlink" href="#debugging-evennia" title="Permalink to this headline"></a></h2>
<p>To run Evennia with the debugger, follow these steps:</p>
<ol>
<li><p>Find the point in the code where you want to have more insight. Add the following line at that
point.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">set_trace</span><span class="p">;</span><span class="n">set_trace</span><span class="p">()</span>
</pre></div>
</div>
</li>
<li><p>(Re-)start Evennia in interactive (foreground) mode with <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">istart</span></code>. This is important -
without this step the debugger will not start correctly - it will start in this interactive
terminal.</p></li>
<li><p>Perform the steps that will trigger the line where you added the <code class="docutils literal notranslate"><span class="pre">set_trace()</span></code> call. The debugger
will start in the terminal from which Evennia was interactively started.</p></li>
</ol>
<p>The <code class="docutils literal notranslate"><span class="pre">evennia.set_trace</span></code> function takes the following arguments:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">evennia</span><span class="o">.</span><span class="n">set_trace</span><span class="p">(</span><span class="n">debugger</span><span class="o">=</span><span class="s1">&#39;auto&#39;</span><span class="p">,</span> <span class="n">term_size</span><span class="o">=</span><span class="p">(</span><span class="mi">140</span><span class="p">,</span> <span class="mi">40</span><span class="p">))</span>
</pre></div>
</div>
<p>Here, <code class="docutils literal notranslate"><span class="pre">debugger</span></code> is one of <code class="docutils literal notranslate"><span class="pre">pdb</span></code>, <code class="docutils literal notranslate"><span class="pre">pudb</span></code> or <code class="docutils literal notranslate"><span class="pre">auto</span></code>. If <code class="docutils literal notranslate"><span class="pre">auto</span></code>, use <code class="docutils literal notranslate"><span class="pre">pudb</span></code> if available, otherwise
use <code class="docutils literal notranslate"><span class="pre">pdb</span></code>. The <code class="docutils literal notranslate"><span class="pre">term_size</span></code> tuple sets the viewport size for <code class="docutils literal notranslate"><span class="pre">pudb</span></code> only (its ignored by <code class="docutils literal notranslate"><span class="pre">pdb</span></code>).</p>
</section>
<section id="a-simple-example-using-pdb">
<h2>A simple example using pdb<a class="headerlink" href="#a-simple-example-using-pdb" title="Permalink to this headline"></a></h2>
<p>The debugger is useful in different cases, but to begin with, lets see it working in a command.
Add the following test command (which has a range of deliberate errors) and also add it to your
default cmdset. Then restart Evennia in interactive mode with <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">istart</span></code>.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># In file commands/command.py</span>
<span class="k">class</span> <span class="nc">CmdTest</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> A test command just to test pdb.</span>
<span class="sd"> Usage:</span>
<span class="sd"> test</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;test&quot;</span>
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">set_trace</span><span class="p">;</span> <span class="n">set_trace</span><span class="p">()</span> <span class="c1"># &lt;--- start of debugger</span>
<span class="n">obj</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">args</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="s2">&quot;You&#39;ve found </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">obj</span><span class="o">.</span><span class="n">get_display_name</span><span class="p">()))</span>
</pre></div>
</div>
<p>If you type <code class="docutils literal notranslate"><span class="pre">test</span></code> in your game, everything will freeze. You wont get any feedback from the game,
and you wont be able to enter any command (nor anyone else). Its because the debugger has started
in your console, and you will find it here. Below is an example with <code class="docutils literal notranslate"><span class="pre">pdb</span></code>.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">...</span>
<span class="o">&gt;</span> <span class="o">.../</span><span class="n">mygame</span><span class="o">/</span><span class="n">commands</span><span class="o">/</span><span class="n">command</span><span class="o">.</span><span class="n">py</span><span class="p">(</span><span class="mi">79</span><span class="p">)</span><span class="n">func</span><span class="p">()</span>
<span class="o">-&gt;</span> <span class="n">obj</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">)</span>
<span class="p">(</span><span class="n">Pdb</span><span class="p">)</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">pdb</span></code> notes where it has stopped execution and, what line is about to be executed (in our case, <code class="docutils literal notranslate"><span class="pre">obj</span> <span class="pre">=</span> <span class="pre">self.search(self.args)</span></code>), and ask what you would like to do.</p>
<section id="listing-surrounding-lines-of-code">
<h3>Listing surrounding lines of code<a class="headerlink" href="#listing-surrounding-lines-of-code" title="Permalink to this headline"></a></h3>
<p>When you have the <code class="docutils literal notranslate"><span class="pre">pdb</span></code> prompt <code class="docutils literal notranslate"><span class="pre">(Pdb)</span></code>, you can type in different commands to explore the code. The
first one you should know is <code class="docutils literal notranslate"><span class="pre">list</span></code> (you can type <code class="docutils literal notranslate"><span class="pre">l</span></code> for short):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">Pdb</span><span class="p">)</span> <span class="n">l</span>
<span class="mi">43</span>
<span class="mi">44</span> <span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;test&quot;</span>
<span class="mi">45</span>
<span class="mi">46</span> <span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="mi">47</span> <span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">set_trace</span><span class="p">;</span> <span class="n">set_trace</span><span class="p">()</span> <span class="c1"># &lt;--- start of debugger</span>
<span class="mi">48</span> <span class="o">-&gt;</span> <span class="n">obj</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">)</span>
<span class="mi">49</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;You&#39;ve found </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">obj</span><span class="o">.</span><span class="n">get_display_name</span><span class="p">()))</span>
<span class="mi">50</span>
<span class="mi">51</span> <span class="c1"># -------------------------------------------------------------</span>
<span class="mi">52</span> <span class="c1">#</span>
<span class="mi">53</span> <span class="c1"># The default commands inherit from</span>
<span class="p">(</span><span class="n">Pdb</span><span class="p">)</span>
</pre></div>
</div>
<p>Okay, this didnt do anything spectacular, but when you become more confident with <code class="docutils literal notranslate"><span class="pre">pdb</span></code> and find
yourself in lots of different files, you sometimes need to see whats around in code. Notice that
there is a little arrow (<code class="docutils literal notranslate"><span class="pre">-&gt;</span></code>) before the line that is about to be executed.</p>
<p>This is important: <strong>about to be</strong>, not <strong>has just been</strong>. You need to tell <code class="docutils literal notranslate"><span class="pre">pdb</span></code> to go on (well
soon see how).</p>
</section>
<section id="examining-variables">
<h3>Examining variables<a class="headerlink" href="#examining-variables" title="Permalink to this headline"></a></h3>
<p><code class="docutils literal notranslate"><span class="pre">pdb</span></code> allows you to examine variables (or really, to run any Python instruction). It is very useful
to know the values of variables at a specific line. To see a variable, just type its name (as if
you were in the Python interpreter:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">Pdb</span><span class="p">)</span> <span class="bp">self</span>
<span class="o">&lt;</span><span class="n">commands</span><span class="o">.</span><span class="n">command</span><span class="o">.</span><span class="n">CmdTest</span> <span class="nb">object</span> <span class="n">at</span> <span class="mh">0x045A0990</span><span class="o">&gt;</span>
<span class="p">(</span><span class="n">Pdb</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</span>
<span class="sa">u</span><span class="s1">&#39;&#39;</span>
<span class="p">(</span><span class="n">Pdb</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span>
<span class="o">&lt;</span><span class="n">Character</span><span class="p">:</span> <span class="n">XXX</span><span class="o">&gt;</span>
<span class="p">(</span><span class="n">Pdb</span><span class="p">)</span>
</pre></div>
</div>
<p>If you try to see the variable <code class="docutils literal notranslate"><span class="pre">obj</span></code>, youll get an error:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">Pdb</span><span class="p">)</span> <span class="n">obj</span>
<span class="o">***</span> <span class="ne">NameError</span><span class="p">:</span> <span class="n">name</span> <span class="s1">&#39;obj&#39;</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">defined</span>
<span class="p">(</span><span class="n">Pdb</span><span class="p">)</span>
</pre></div>
</div>
<p>That figures, since at this point, we havent created the variable yet.</p>
<blockquote>
<div><p>Examining variable in this way is quite powerful. You can even run Python code and keep on
executing, which can help to check that your fix is actually working when you have identified an
error. If you have variable names that will conflict with <code class="docutils literal notranslate"><span class="pre">pdb</span></code> commands (like a <code class="docutils literal notranslate"><span class="pre">list</span></code>
variable), you can prefix your variable with <code class="docutils literal notranslate"><span class="pre">!</span></code>, to tell <code class="docutils literal notranslate"><span class="pre">pdb</span></code> that what follows is Python code.</p>
</div></blockquote>
</section>
<section id="executing-the-current-line">
<h3>Executing the current line<a class="headerlink" href="#executing-the-current-line" title="Permalink to this headline"></a></h3>
<p>Its time we asked <code class="docutils literal notranslate"><span class="pre">pdb</span></code> to execute the current line. To do so, use the <code class="docutils literal notranslate"><span class="pre">next</span></code> command. You can
shorten it by just typing <code class="docutils literal notranslate"><span class="pre">n</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">Pdb</span><span class="p">)</span> <span class="n">n</span>
<span class="ne">AttributeError</span><span class="p">:</span> <span class="s2">&quot;&#39;CmdTest&#39; object has no attribute &#39;search&#39;&quot;</span>
<span class="o">&gt;</span> <span class="o">.../</span><span class="n">mygame</span><span class="o">/</span><span class="n">commands</span><span class="o">/</span><span class="n">command</span><span class="o">.</span><span class="n">py</span><span class="p">(</span><span class="mi">79</span><span class="p">)</span><span class="n">func</span><span class="p">()</span>
<span class="o">-&gt;</span> <span class="n">obj</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">)</span>
<span class="p">(</span><span class="n">Pdb</span><span class="p">)</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">Pdb</span></code> is complaining that you try to call the <code class="docutils literal notranslate"><span class="pre">search</span></code> method on a command… whereas theres no
<code class="docutils literal notranslate"><span class="pre">search</span></code> method on commands. The character executing the command is in <code class="docutils literal notranslate"><span class="pre">self.caller</span></code>, so we might
change our line:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">obj</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="letting-the-program-run">
<h3>Letting the program run<a class="headerlink" href="#letting-the-program-run" title="Permalink to this headline"></a></h3>
<p><code class="docutils literal notranslate"><span class="pre">pdb</span></code> is waiting to execute the same instruction… it provoked an error but its ready to try
again, just in case. We have fixed it in theory, but we need to reload, so we need to enter a
command. To tell <code class="docutils literal notranslate"><span class="pre">pdb</span></code> to terminate and keep on running the program, use the <code class="docutils literal notranslate"><span class="pre">continue</span></code> (or <code class="docutils literal notranslate"><span class="pre">c</span></code>)
command:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">Pdb</span><span class="p">)</span> <span class="n">c</span>
<span class="o">...</span>
</pre></div>
</div>
<p>You see an error being caught, thats the error we have fixed… or hope to have. Lets reload the
game and try again. You need to run <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">istart</span></code> again and then run <code class="docutils literal notranslate"><span class="pre">test</span></code> to get into the
command again.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="o">.../</span><span class="n">mygame</span><span class="o">/</span><span class="n">commands</span><span class="o">/</span><span class="n">command</span><span class="o">.</span><span class="n">py</span><span class="p">(</span><span class="mi">79</span><span class="p">)</span><span class="n">func</span><span class="p">()</span>
<span class="o">-&gt;</span> <span class="n">obj</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">)</span>
<span class="p">(</span><span class="n">Pdb</span><span class="p">)</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">pdb</span></code> is about to run the line again.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">Pdb</span><span class="p">)</span> <span class="n">n</span>
<span class="o">&gt;</span> <span class="o">.../</span><span class="n">mygame</span><span class="o">/</span><span class="n">commands</span><span class="o">/</span><span class="n">command</span><span class="o">.</span><span class="n">py</span><span class="p">(</span><span class="mi">80</span><span class="p">)</span><span class="n">func</span><span class="p">()</span>
<span class="o">-&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;You&#39;ve found </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">obj</span><span class="o">.</span><span class="n">get_display_name</span><span class="p">()))</span>
<span class="p">(</span><span class="n">Pdb</span><span class="p">)</span>
</pre></div>
</div>
<p>This time the line ran without error. Lets see what is in the <code class="docutils literal notranslate"><span class="pre">obj</span></code> variable:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">Pdb</span><span class="p">)</span> <span class="n">obj</span>
<span class="p">(</span><span class="n">Pdb</span><span class="p">)</span> <span class="nb">print</span> <span class="n">obj</span>
<span class="kc">None</span>
<span class="p">(</span><span class="n">Pdb</span><span class="p">)</span>
</pre></div>
</div>
<p>We have entered the <code class="docutils literal notranslate"><span class="pre">test</span></code> command without parameter, so no object could be found in the search
(<code class="docutils literal notranslate"><span class="pre">self.args</span></code> is an empty string).</p>
<p>Lets allow the command to continue and try to use an object name as parameter (although, we should
fix that bug too, it would be better):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">Pdb</span><span class="p">)</span> <span class="n">c</span>
<span class="o">...</span>
</pre></div>
</div>
<p>Notice that youll have an error in the game this time. Lets try with a valid parameter. I have
another character, <code class="docutils literal notranslate"><span class="pre">barkeep</span></code>, in this room:</p>
<p><code class="docutils literal notranslate"><span class="pre">test</span> <span class="pre">barkeep</span></code></p>
<p>And again, the command freezes, and we have the debugger opened in the console.</p>
<p>Lets execute this line right away:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&gt;</span> <span class="o">.../</span><span class="n">mygame</span><span class="o">/</span><span class="n">commands</span><span class="o">/</span><span class="n">command</span><span class="o">.</span><span class="n">py</span><span class="p">(</span><span class="mi">79</span><span class="p">)</span><span class="n">func</span><span class="p">()</span>
<span class="o">-&gt;</span> <span class="n">obj</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">)</span>
<span class="p">(</span><span class="n">Pdb</span><span class="p">)</span> <span class="n">n</span>
<span class="o">&gt;</span> <span class="o">.../</span><span class="n">mygame</span><span class="o">/</span><span class="n">commands</span><span class="o">/</span><span class="n">command</span><span class="o">.</span><span class="n">py</span><span class="p">(</span><span class="mi">80</span><span class="p">)</span><span class="n">func</span><span class="p">()</span>
<span class="o">-&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;You&#39;ve found </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">obj</span><span class="o">.</span><span class="n">get_display_name</span><span class="p">()))</span>
<span class="p">(</span><span class="n">Pdb</span><span class="p">)</span> <span class="n">obj</span>
<span class="o">&lt;</span><span class="n">Character</span><span class="p">:</span> <span class="n">barkeep</span><span class="o">&gt;</span>
<span class="p">(</span><span class="n">Pdb</span><span class="p">)</span>
</pre></div>
</div>
<p>At least this time we have found the object. Lets process…</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">Pdb</span><span class="p">)</span> <span class="n">n</span>
<span class="ne">TypeError</span><span class="p">:</span> <span class="s1">&#39;get_display_name() takes exactly 2 arguments (1 given)&#39;</span>
<span class="o">&gt;</span> <span class="o">.../</span><span class="n">mygame</span><span class="o">/</span><span class="n">commands</span><span class="o">/</span><span class="n">command</span><span class="o">.</span><span class="n">py</span><span class="p">(</span><span class="mi">80</span><span class="p">)</span><span class="n">func</span><span class="p">()</span>
<span class="o">-&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;You&#39;ve found </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">obj</span><span class="o">.</span><span class="n">get_display_name</span><span class="p">()))</span>
<span class="p">(</span><span class="n">Pdb</span><span class="p">)</span>
</pre></div>
</div>
<p>As an exercise, fix this error, reload and run the debugger again. Nothing better than some
experimenting!</p>
<p>Your debugging will often follow the same strategy:</p>
<ol class="simple">
<li><p>Receive an error you dont understand.</p></li>
<li><p>Put a breaking point <strong>BEFORE</strong> the error occurs.</p></li>
<li><p>Run the code again and see the debugger open.</p></li>
<li><p>Run the program line by line,examining variables, checking the logic of instructions.</p></li>
<li><p>Continue and try again, each step a bit further toward the truth and the working feature.</p></li>
</ol>
</section>
<section id="stepping-through-a-function">
<h3>Stepping through a function<a class="headerlink" href="#stepping-through-a-function" title="Permalink to this headline"></a></h3>
<p><code class="docutils literal notranslate"><span class="pre">n</span></code> is useful, but it will avoid stepping inside of functions if it can. But most of the time, when
we have an error we dont understand, its because we use functions or methods in a way that wasnt
intended by the developer of the API. Perhaps using wrong arguments, or calling the function in a
situation that would cause a bug. When we have a line in the debugger that calls a function or
method, we can “step” to examine it further. For instance, in the previous example, when <code class="docutils literal notranslate"><span class="pre">pdb</span></code> was
about to execute <code class="docutils literal notranslate"><span class="pre">obj</span> <span class="pre">=</span> <span class="pre">self.caller.search(self.args)</span></code>, we may want to see what happens inside of
the <code class="docutils literal notranslate"><span class="pre">search</span></code> method.</p>
<p>To do so, use the <code class="docutils literal notranslate"><span class="pre">step</span></code> (or <code class="docutils literal notranslate"><span class="pre">s</span></code>) command. This command will show you the definition of the
function/method and you can then use <code class="docutils literal notranslate"><span class="pre">n</span></code> as before to see it line-by-line. In our little example,
stepping through a function or method isnt that useful, but when you have an impressive set of
commands, functions and so on, it might really be handy to examine some feature and make sure they
operate as planned.</p>
</section>
</section>
<section id="cheat-sheet-of-pdb-pudb-commands">
<h2>Cheat-sheet of pdb/pudb commands<a class="headerlink" href="#cheat-sheet-of-pdb-pudb-commands" title="Permalink to this headline"></a></h2>
<p>PuDB and Pdb share the same commands. The only real difference is how its presented. The <code class="docutils literal notranslate"><span class="pre">look</span></code>
command is not needed much in <code class="docutils literal notranslate"><span class="pre">pudb</span></code> since it displays the code directly in its user interface.</p>
<table class="colwidths-auto docutils align-default">
<thead>
<tr class="row-odd"><th class="head"><p>Pdb/PuDB command</p></th>
<th class="head"><p>To do what</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p>list (or l)</p></td>
<td><p>List the lines around the point of execution (not needed for <code class="docutils literal notranslate"><span class="pre">pudb</span></code>, it will show</p></td>
</tr>
<tr class="row-odd"><td><p>this directly).</p></td>
<td><p></p></td>
</tr>
<tr class="row-even"><td><p>print (or p)</p></td>
<td><p>Display one or several variables.</p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">!</span></code></p></td>
<td><p>Run Python code (using a <code class="docutils literal notranslate"><span class="pre">!</span></code> is often optional).</p></td>
</tr>
<tr class="row-even"><td><p>continue (or c)</p></td>
<td><p>Continue execution and terminate the debugger for this time.</p></td>
</tr>
<tr class="row-odd"><td><p>next (or n)</p></td>
<td><p>Execute the current line and goes to the next one.</p></td>
</tr>
<tr class="row-even"><td><p>step (or s)</p></td>
<td><p>Step inside of a function or method to examine it.</p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">&lt;RETURN&gt;</span></code></p></td>
<td><p>Repeat the last command (dont type <code class="docutils literal notranslate"><span class="pre">n</span></code> repeatedly, just type it once and then press</p></td>
</tr>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">&lt;RETURN&gt;</span></code> to repeat it).</p></td>
<td><p></p></td>
</tr>
</tbody>
</table>
<p>If you want to learn more about debugging with Pdb, you will find an <a class="reference external" href="https://pymotw.com/3/pdb/">interesting tutorial on that
topic here</a>.</p>
</section>
</section>
</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="right" >
<a href="Unit-Testing.html" title="Unit Testing"
>next</a> |</li>
<li class="right" >
<a href="Coding-Introduction.html" title="Coding Introduction"
>previous</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="Coding-Overview.html" >Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Debugging</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>

View file

@ -0,0 +1,389 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Profiling &#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" />
<link rel="next" title="Quirks" href="Quirks.html" />
<link rel="prev" title="Unit Testing" href="Unit-Testing.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="right" >
<a href="Quirks.html" title="Quirks"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="Unit-Testing.html" title="Unit Testing"
accesskey="P">previous</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="Coding-Overview.html" accesskey="U">Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Profiling</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="document">
<div class="documentwrapper">
<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><a href="../index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Profiling</a><ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#simple-timer-tests">Simple timer tests</a></li>
<li><a class="reference internal" href="#using-cprofile">Using cProfile</a><ul>
<li><a class="reference internal" href="#analyzing-the-profile">Analyzing the profile</a></li>
</ul>
</li>
<li><a class="reference internal" href="#the-dummyrunner">The Dummyrunner</a><ul>
<li><a class="reference internal" href="#dummyrunner-hints">Dummyrunner hints</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="Unit-Testing.html"
title="previous chapter">Unit Testing</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="Quirks.html"
title="next chapter">Quirks</a></p>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Coding/Profiling.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com">Home page</a> </li>
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
<h3>Versions</h3>
<ul>
<li><a href="Profiling.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
</ul>
</div>
</div>
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="profiling">
<h1>Profiling<a class="headerlink" href="#profiling" title="Permalink to this headline"></a></h1>
<p><em>This is considered an advanced topic mainly of interest to server developers.</em></p>
<section id="introduction">
<h2>Introduction<a class="headerlink" href="#introduction" title="Permalink to this headline"></a></h2>
<p>Sometimes it can be useful to try to determine just how efficient a particular
piece of code is, or to figure out if one could speed up things more than they
are. There are many ways to test the performance of Python and the running
server.</p>
<p>Before digging into this section, remember Donald Knuths
<a class="reference external" href="https://en.wikipedia.org/wiki/Program_optimization#When_to_optimize">words of wisdom</a>:</p>
<blockquote>
<div><p><em>[…]about 97% of the time: Premature optimization is the root of all evil</em>.</p>
</div></blockquote>
<p>That is, dont start to try to optimize your code until you have actually
identified a need to do so. This means your code must actually be working before
you start to consider optimization. Optimization will also often make your code
more complex and harder to read. Consider readability and maintainability and
you may find that a small gain in speed is just not worth it.</p>
</section>
<section id="simple-timer-tests">
<h2>Simple timer tests<a class="headerlink" href="#simple-timer-tests" title="Permalink to this headline"></a></h2>
<p>Pythons <code class="docutils literal notranslate"><span class="pre">timeit</span></code> module is very good for testing small things. For example, in
order to test if it is faster to use a <code class="docutils literal notranslate"><span class="pre">for</span></code> loop or a list comprehension you
could use the following code:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="kn">import</span> <span class="nn">timeit</span>
<span class="c1"># Time to do 1000000 for loops</span>
<span class="n">timeit</span><span class="o">.</span><span class="n">timeit</span><span class="p">(</span><span class="s2">&quot;for i in range(100):</span><span class="se">\n</span><span class="s2"> a.append(i)&quot;</span><span class="p">,</span> <span class="n">setup</span><span class="o">=</span><span class="s2">&quot;a = []&quot;</span><span class="p">)</span>
<span class="o">&lt;&lt;&lt;</span> <span class="mf">10.70982813835144</span>
<span class="c1"># Time to do 1000000 list comprehensions</span>
<span class="n">timeit</span><span class="o">.</span><span class="n">timeit</span><span class="p">(</span><span class="s2">&quot;a = [i for i in range(100)]&quot;</span><span class="p">)</span>
<span class="o">&lt;&lt;&lt;</span> <span class="mf">5.358283996582031</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">setup</span></code> keyword is used to set up things that should not be included in the
time measurement, like <code class="docutils literal notranslate"><span class="pre">a</span> <span class="pre">=</span> <span class="pre">[]</span></code> in the first call.</p>
<p>By default the <code class="docutils literal notranslate"><span class="pre">timeit</span></code> function will re-run the given test 1000000 times and
returns the <em>total time</em> to do so (so <em>not</em> the average per test). A hint is to
not use this default for testing something that includes database writes - for
that you may want to use a lower number of repeats (say 100 or 1000) using the
<code class="docutils literal notranslate"><span class="pre">number=100</span></code> keyword.</p>
</section>
<section id="using-cprofile">
<h2>Using cProfile<a class="headerlink" href="#using-cprofile" title="Permalink to this headline"></a></h2>
<p>Python comes with its own profiler, named cProfile (this is for cPython, no
tests have been done with <code class="docutils literal notranslate"><span class="pre">pypy</span></code> at this point). Due to the way Evennias
processes are handled, there is no point in using the normal way to start the
profiler (<code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-m</span> <span class="pre">cProfile</span> <span class="pre">evennia.py</span></code>). Instead you start the profiler
through the launcher:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia --profiler start
</pre></div>
</div>
<p>This will start Evennia with the Server component running (in daemon mode) under
cProfile. You could instead try <code class="docutils literal notranslate"><span class="pre">--profile</span></code> with the <code class="docutils literal notranslate"><span class="pre">portal</span></code> argument to
profile the Portal (you would then need to
<a class="reference internal" href="../Setup/Start-Stop-Reload.html"><span class="doc std std-doc">start the Server separately</span></a>).</p>
<p>Please note that while the profiler is running, your process will use a lot more
memory than usual. Memory usage is even likely to climb over time. So dont
leave it running perpetually but monitor it carefully (for example using the
<code class="docutils literal notranslate"><span class="pre">top</span></code> command on Linux or the Task Managers memory display on Windows).</p>
<p>Once you have run the server for a while, you need to stop it so the profiler
can give its report. Do <em>not</em> kill the program from your task manager or by
sending it a kill signal - this will most likely also mess with the profiler.
Instead either use <code class="docutils literal notranslate"><span class="pre">evennia.py</span> <span class="pre">stop</span></code> or (which may be even better), use
<code class="docutils literal notranslate"><span class="pre">&#64;shutdown</span></code> from inside the game.</p>
<p>Once the server has fully shut down (this may be a lot slower than usual) you
will find that profiler has created a new file <code class="docutils literal notranslate"><span class="pre">mygame/server/logs/server.prof</span></code>.</p>
<section id="analyzing-the-profile">
<h3>Analyzing the profile<a class="headerlink" href="#analyzing-the-profile" title="Permalink to this headline"></a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">server.prof</span></code> file is a binary file. There are many ways to analyze and
display its contents, all of which has only been tested in Linux (If you are a
Windows/Mac user, let us know what works).</p>
<p>You can look at the contents of the profile file with Pythons in-built <code class="docutils literal notranslate"><span class="pre">pstats</span></code>
module in the evennia shell (its recommended you install <code class="docutils literal notranslate"><span class="pre">ipython</span></code> with <code class="docutils literal notranslate"><span class="pre">pip</span> <span class="pre">install</span> <span class="pre">ipython</span></code> in your virtualenv first, for prettier output):</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia shell
</pre></div>
</div>
<p>Then in the shell</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">pstats</span>
<span class="kn">from</span> <span class="nn">pstats</span> <span class="kn">import</span> <span class="n">SortKey</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">pstats</span><span class="o">.</span><span class="n">Stats</span><span class="p">(</span><span class="s1">&#39;server/log/server.prof&#39;</span><span class="p">)</span>
<span class="n">p</span><span class="o">.</span><span class="n">strip_dirs</span><span class="p">()</span><span class="o">.</span><span class="n">sort_stats</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">print_stats</span><span class="p">()</span>
</pre></div>
</div>
<p>See the
<a class="reference external" href="https://docs.python.org/3/library/profile.html#instant-user-s-manual">Python profiling documentation</a>
for more information.</p>
<p>You can also visualize the data in various ways.</p>
<ul class="simple">
<li><p><a class="reference external" href="https://pypi.org/project/RunSnakeRun/">Runsnake</a> visualizes the profile to
give a good overview. Install with <code class="docutils literal notranslate"><span class="pre">pip</span> <span class="pre">install</span> <span class="pre">runsnakerun</span></code>. Note that this
may require a C compiler and be quite slow to install.</p></li>
<li><p>For more detailed listing of usage time, you can use
<a class="reference external" href="http://kcachegrind.sourceforge.net/html/Home.html">KCachegrind</a>. To make
KCachegrind work with Python profiles you also need the wrapper script
<a class="reference external" href="https://pypi.python.org/pypi/pyprof2calltree/">pyprof2calltree</a>. You can get
<code class="docutils literal notranslate"><span class="pre">pyprof2calltree</span></code> via <code class="docutils literal notranslate"><span class="pre">pip</span></code> whereas KCacheGrind is something you need to get
via your package manager or their homepage.</p></li>
</ul>
<p>How to analyze and interpret profiling data is not a trivial issue and depends
on what you are profiling for. Evennia being an asynchronous server can also
confuse profiling. Ask on the mailing list if you need help and be ready to be
able to supply your <code class="docutils literal notranslate"><span class="pre">server.prof</span></code> file for comparison, along with the exact
conditions under which it was obtained.</p>
</section>
</section>
<section id="the-dummyrunner">
<h2>The Dummyrunner<a class="headerlink" href="#the-dummyrunner" title="Permalink to this headline"></a></h2>
<p>It is difficult to test “actual” game performance without having players in your
game. For this reason Evennia comes with the <em>Dummyrunner</em> system. The
Dummyrunner is a stress-testing system: a separate program that logs into your
game with simulated players (aka “bots” or “dummies”). Once connected, these
dummies will semi-randomly perform various tasks from a list of possible
actions. Use <code class="docutils literal notranslate"><span class="pre">Ctrl-C</span></code> to stop the Dummyrunner.</p>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>You should not run the Dummyrunner on a production database. It
will spawn many objects and also needs to run with general permissions.
</pre></div>
</div>
<p>This is the recommended process for using the dummy runner:</p>
</div>
<ol>
<li><p>Stop your server completely with <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">stop</span></code>.</p></li>
<li><p>At <em>the end</em> of your <code class="docutils literal notranslate"><span class="pre">mygame/server/conf.settings.py</span></code> file, add the line</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> from evennia.server.profiling.settings_mixin import *
</pre></div>
</div>
<p>This will override your settings and disable Evennias rate limiters and
DoS-protections, which would otherwise block mass-connecting clients from
one IP. Notably, it will also change to a different (faster) password hasher.</p>
</li>
<li><p>(recommended): Build a new database. If you use default Sqlite3 and want to
keep your existing database, just rename <code class="docutils literal notranslate"><span class="pre">mygame/server/evennia.db3</span></code> to
<code class="docutils literal notranslate"><span class="pre">mygame/server/evennia.db3_backup</span></code> and run <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">migrate</span></code> and <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">start</span></code> to create a new superuser as usual.</p></li>
<li><p>(recommended) Log into the game as your superuser. This is just so you
can manually check response. If you kept an old database, you will <em>not</em>
be able to connect with an <em>existing</em> user since the password hasher changed!</p></li>
<li><p>Start the dummyrunner with 10 dummy users from the terminal with</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> evennia --dummyrunner 10
</pre></div>
</div>
<p>Use <code class="docutils literal notranslate"><span class="pre">Ctrl-C</span></code> (or <code class="docutils literal notranslate"><span class="pre">Cmd-C</span></code>) to stop it.</p>
</li>
</ol>
<p>If you want to see what the dummies are actually doing you can run with a single
dummy:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia --dummyrunner 1
</pre></div>
</div>
<p>The inputs/outputs from the dummy will then be printed. By default the runner
uses the looker profile, which just logs in and sends the look command
over and over. To change the settings, copy the file
<code class="docutils literal notranslate"><span class="pre">evennia/server/profiling/dummyrunner_settings.py</span></code> to your <code class="docutils literal notranslate"><span class="pre">mygame/server/conf/</span></code>
directory, then add this line to your settings file to use it in the new
location:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>DUMMYRUNNER_SETTINGS_MODULE = &quot;server/conf/dummyrunner_settings.py&quot;
</pre></div>
</div>
<p>The dummyrunner settings file is a python code module in its own right - it
defines the actions available to the dummies. These are just tuples of command
strings (like “look here”) for the dummy to send to the server along with a
probability of them happening. The dummyrunner looks for a global variable
<code class="docutils literal notranslate"><span class="pre">ACTIONS</span></code>, a list of tuples, where the first two elements define the
commands for logging in/out of the server.</p>
<p>Below is a simplified minimal setup (the default settings file adds a lot more
functionality and info):</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># minimal dummyrunner setup file</span>
<span class="c1"># Time between each dummyrunner &quot;tick&quot;, in seconds. Each dummy will be called</span>
<span class="c1"># with this frequency.</span>
<span class="n">TIMESTEP</span> <span class="o">=</span> <span class="mi">1</span>
<span class="c1"># Chance of a dummy actually performing an action on a given tick. This</span>
<span class="c1"># spreads out usage randomly, like it would be in reality.</span>
<span class="n">CHANCE_OF_ACTION</span> <span class="o">=</span> <span class="mf">0.5</span>
<span class="c1"># Chance of a currently unlogged-in dummy performing its login action every</span>
<span class="c1"># tick. This emulates not all accounts logging in at exactly the same time.</span>
<span class="n">CHANCE_OF_LOGIN</span> <span class="o">=</span> <span class="mf">0.01</span>
<span class="c1"># Which telnet port to connect to. If set to None, uses the first default</span>
<span class="c1"># telnet port of the running server.</span>
<span class="n">TELNET_PORT</span> <span class="o">=</span> <span class="kc">None</span>
<span class="c1"># actions</span>
<span class="k">def</span> <span class="nf">c_login</span><span class="p">(</span><span class="n">client</span><span class="p">):</span>
<span class="n">name</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;Character-</span><span class="si">{</span><span class="n">client</span><span class="o">.</span><span class="n">gid</span><span class="si">}</span><span class="s2">&quot;</span>
<span class="n">pwd</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;23fwsf23sdfw23wef23&quot;</span>
<span class="k">return</span> <span class="p">(</span>
<span class="sa">f</span><span class="s2">&quot;create </span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">pwd</span><span class="si">}</span><span class="s2">&quot;</span>
<span class="sa">f</span><span class="s2">&quot;connect </span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">pwd</span><span class="si">}</span><span class="s2">&quot;</span>
<span class="p">)</span>
<span class="k">def</span> <span class="nf">c_logout</span><span class="p">(</span><span class="n">client</span><span class="p">):</span>
<span class="k">return</span> <span class="p">(</span><span class="s2">&quot;quit&quot;</span><span class="p">,</span> <span class="p">)</span>
<span class="k">def</span> <span class="nf">c_look</span><span class="p">(</span><span class="n">client</span><span class="p">):</span>
<span class="k">return</span> <span class="p">(</span><span class="s2">&quot;look here&quot;</span><span class="p">,</span> <span class="s2">&quot;look me&quot;</span><span class="p">)</span>
<span class="c1"># this is read by dummyrunner.</span>
<span class="n">ACTIONS</span> <span class="o">=</span> <span class="p">(</span>
<span class="n">c_login</span><span class="p">,</span>
<span class="n">c_logout</span><span class="p">,</span>
<span class="p">(</span><span class="mf">1.0</span><span class="p">,</span> <span class="n">c_look</span><span class="p">)</span> <span class="c1"># (probability, command-generator)</span>
<span class="p">)</span>
</pre></div>
</div>
<p>At the bottom of the default file are a few default profiles you can test out
by just setting the <code class="docutils literal notranslate"><span class="pre">PROFILE</span></code> variable to one of the options.</p>
<section id="dummyrunner-hints">
<h3>Dummyrunner hints<a class="headerlink" href="#dummyrunner-hints" title="Permalink to this headline"></a></h3>
<ul class="simple">
<li><p>Dont start with too many dummies. The Dummyrunner taxes the server much more
than real users tend to do. Start with 10-100 to begin with.</p></li>
<li><p>Stress-testing can be fun, but also consider what a realistic number of
users would be for your game.</p></li>
<li><p>Note in the dummyrunner output how many commands/s are being sent to the
server by all dummies. This is usually a lot higher than what youd
realistically expect to see from the same number of users.</p></li>
<li><p>The default settings sets up a lag measure to measaure the round-about
message time. It updates with an average every 30 seconds. It can be worth to
have this running for a small number of dummies in one terminal before adding
more by starting another dummyrunner in another terminal - the first one will
act as a measure of how lag changes with different loads. Also verify the
lag-times by entering commands manually in-game.</p></li>
<li><p>Check the CPU usage of your server using <code class="docutils literal notranslate"><span class="pre">top/htop</span></code> (linux). In-game, use the
<code class="docutils literal notranslate"><span class="pre">server</span></code> command.</p></li>
<li><p>You can run the server with <code class="docutils literal notranslate"><span class="pre">--profiler</span> <span class="pre">start</span></code> to test it with dummies. Note
that the profiler will itself affect server performance, especially memory
consumption.</p></li>
<li><p>Generally, the dummyrunner system makes for a decent test of general
performance; but it is of course hard to actually mimic human user behavior.
For this, actual real-game testing is required.</p></li>
</ul>
</section>
</section>
</section>
</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="right" >
<a href="Quirks.html" title="Quirks"
>next</a> |</li>
<li class="right" >
<a href="Unit-Testing.html" title="Unit Testing"
>previous</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="Coding-Overview.html" >Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Profiling</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>

View file

@ -0,0 +1,272 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Quirks &#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" />
<link rel="next" title="Changelog" href="Changelog.html" />
<link rel="prev" title="Profiling" href="Profiling.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="right" >
<a href="Changelog.html" title="Changelog"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="Profiling.html" title="Profiling"
accesskey="P">previous</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="Coding-Overview.html" accesskey="U">Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Quirks</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="document">
<div class="documentwrapper">
<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><a href="../index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Quirks</a><ul>
<li><a class="reference internal" href="#forgetting-to-use-reload-to-see-changes-to-your-typeclasses">Forgetting to use <code class="docutils literal notranslate"><span class="pre">reload</span></code> to see changes to your typeclasses</a></li>
<li><a class="reference internal" href="#web-admin-to-create-new-account">Web admin to create new Account</a></li>
<li><a class="reference internal" href="#mutable-attributes-and-their-connection-to-the-database">Mutable attributes and their connection to the database</a></li>
<li><a class="reference internal" href="#commands-are-matched-by-name-or-alias">Commands are matched by name <em>or</em> alias</a></li>
<li><a class="reference internal" href="#objects-turning-to-defaultobject">Objects turning to <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code></a></li>
<li><a class="reference internal" href="#overriding-of-magic-methods">Overriding of magic methods</a></li>
<li><a class="reference internal" href="#things-to-remember-about-the-flat-api">Things to remember about the flat API</a><ul>
<li><a class="reference internal" href="#to-remember-when-importing-from-evennia">To remember when importing from <code class="docutils literal notranslate"><span class="pre">evennia</span></code></a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="Profiling.html"
title="previous chapter">Profiling</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="Changelog.html"
title="next chapter">Changelog</a></p>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Coding/Quirks.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com">Home page</a> </li>
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
<h3>Versions</h3>
<ul>
<li><a href="Quirks.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
</ul>
</div>
</div>
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="quirks">
<h1>Quirks<a class="headerlink" href="#quirks" title="Permalink to this headline"></a></h1>
<p>This is a list of various quirks or common stumbling blocks that people often ask about or report
when using (or trying to use) Evennia. They are not bugs.</p>
<section id="forgetting-to-use-reload-to-see-changes-to-your-typeclasses">
<h2>Forgetting to use <code class="docutils literal notranslate"><span class="pre">reload</span></code> to see changes to your typeclasses<a class="headerlink" href="#forgetting-to-use-reload-to-see-changes-to-your-typeclasses" title="Permalink to this headline"></a></h2>
<p>Firstly: Reloading the server is a safe and usually quick operation which will <em>not</em> disconnect any
accounts.</p>
<p>New users tend to forget this step. When editing source code (such as when tweaking typeclasses and
commands or adding new commands to command sets) you need to either use the in-game <code class="docutils literal notranslate"><span class="pre">&#64;reload</span></code>
command or, from the command line do <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">evennia.py</span> <span class="pre">reload</span></code> before you see your changes.</p>
</section>
<section id="web-admin-to-create-new-account">
<h2>Web admin to create new Account<a class="headerlink" href="#web-admin-to-create-new-account" title="Permalink to this headline"></a></h2>
<p>If you use the default login system and are trying to use the Web admin to create a new Player
account, you need to consider which <code class="docutils literal notranslate"><span class="pre">MULTIACCOUNT_MODE</span></code> you are in. If you are in
<code class="docutils literal notranslate"><span class="pre">MULTIACCOUNT_MODE</span></code> <code class="docutils literal notranslate"><span class="pre">0</span></code> or <code class="docutils literal notranslate"><span class="pre">1</span></code>, the login system expects each Account to also have a Character
object named the same as the Account - there is no character creation screen by default. If using
the normal mud login screen, a Character with the same name is automatically created and connected
to your Account. From the web interface you must do this manually.</p>
<p>So, when creating the Account, make sure to also create the Character <em>from the same form</em> as you
create the Account from. This should set everything up for you. Otherwise you need to manually set
the “account” property on the Character and the “character” property on the Account to point to each
other. You must also set the lockstring of the Character to allow the Account to “puppet” this
particular character.</p>
</section>
<section id="mutable-attributes-and-their-connection-to-the-database">
<h2>Mutable attributes and their connection to the database<a class="headerlink" href="#mutable-attributes-and-their-connection-to-the-database" title="Permalink to this headline"></a></h2>
<p>When storing a mutable object (usually a list or a dictionary) in an Attribute</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="nb">object</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">mylist</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span>
</pre></div>
</div>
<p>you should know that the connection to the database is retained also if you later extract that
Attribute into another variable (what is stored and retrieved is actually a <code class="docutils literal notranslate"><span class="pre">PackedList</span></code> or a
<code class="docutils literal notranslate"><span class="pre">PackedDict</span></code> that works just like their namesakes except they save themselves to the database when
changed). So if you do</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="n">alist</span> <span class="o">=</span> <span class="nb">object</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">mylist</span>
<span class="n">alist</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
</pre></div>
</div>
<p>this updates the database behind the scenes, so both <code class="docutils literal notranslate"><span class="pre">alist</span></code> and <code class="docutils literal notranslate"><span class="pre">object.db.mylist</span></code> are now
<code class="docutils literal notranslate"><span class="pre">[1,2,3,4]</span></code></p>
<p>If you dont want this, Evennia provides a way to stably disconnect the mutable from the database by
use of <code class="docutils literal notranslate"><span class="pre">evennia.utils.dbserialize.deserialize</span></code>:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="kn">from</span> <span class="nn">evennia.utils.dbserialize</span> <span class="kn">import</span> <span class="n">deserialize</span>
<span class="n">blist</span> <span class="o">=</span> <span class="n">deserialize</span><span class="p">(</span><span class="nb">object</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">mylist</span><span class="p">)</span>
<span class="n">blist</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
</pre></div>
</div>
<p>The property <code class="docutils literal notranslate"><span class="pre">blist</span></code> is now <code class="docutils literal notranslate"><span class="pre">[1,2,3,4]</span></code> whereas <code class="docutils literal notranslate"><span class="pre">object.db.mylist</span></code> remains unchanged. If you want to
update the database youd need to explicitly re-assign the updated data to the <code class="docutils literal notranslate"><span class="pre">mylist</span></code> Attribute.</p>
</section>
<section id="commands-are-matched-by-name-or-alias">
<h2>Commands are matched by name <em>or</em> alias<a class="headerlink" href="#commands-are-matched-by-name-or-alias" title="Permalink to this headline"></a></h2>
<p>When merging <a class="reference internal" href="../Components/Commands.html"><span class="doc std std-doc">command sets</span></a> its important to remember that command objects are identified
<em>both</em> by key <em>or</em> alias. So if you have a command with a key <code class="docutils literal notranslate"><span class="pre">look</span></code> and an alias <code class="docutils literal notranslate"><span class="pre">ls</span></code>, introducing
another command with a key <code class="docutils literal notranslate"><span class="pre">ls</span></code> will be assumed by the system to be <em>identical</em> to the first one.
This usually means merging cmdsets will overload one of them depending on priority. Whereas this is
logical once you know how command objects are handled, it may be confusing if you are just looking
at the command strings thinking they are parsed as-is.</p>
</section>
<section id="objects-turning-to-defaultobject">
<h2>Objects turning to <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code><a class="headerlink" href="#objects-turning-to-defaultobject" title="Permalink to this headline"></a></h2>
<p>A common confusing error for new developers is finding that one or more objects in-game are suddenly
of the type <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> rather than the typeclass you wanted it to be. This happens when you
introduce a critical Syntax error to the module holding your custom class. Since such a module is
not valid Python, Evennia cant load it at all to get to the typeclasses within. To keep on running,
Evennia will solve this by printing the full traceback to the terminal/console and temporarily fall
back to the safe <code class="docutils literal notranslate"><span class="pre">DefaultObject</span></code> until you fix the problem and reload. Most errors of this kind will
be caught by any good text editors. Keep an eye on the terminal/console during a reload to catch
such errors - you may have to scroll up if your window is small.</p>
</section>
<section id="overriding-of-magic-methods">
<h2>Overriding of magic methods<a class="headerlink" href="#overriding-of-magic-methods" title="Permalink to this headline"></a></h2>
<p>Python implements a system of <a class="reference external" href="https://docs.python.org/3/reference/datamodel.html#emulating-container-types">magic
methods</a>, usually
prefixed and suffixed by double-underscores (<code class="docutils literal notranslate"><span class="pre">__example__</span></code>) that allow object instances to have
certain operations performed on them without needing to do things like turn them into strings or
numbers first for example, is <code class="docutils literal notranslate"><span class="pre">obj1</span></code> greater than or equal to <code class="docutils literal notranslate"><span class="pre">obj2</span></code>?</p>
<p>Neither object is a number, but given <code class="docutils literal notranslate"><span class="pre">obj1.size</span> <span class="pre">==</span> <span class="pre">&quot;small&quot;</span></code> and <code class="docutils literal notranslate"><span class="pre">obj2.size</span> <span class="pre">==</span> <span class="pre">&quot;large&quot;</span></code>, how might
one compare these two arbitrary English adjective strings to figure out which is greater than the
other? By defining the <code class="docutils literal notranslate"><span class="pre">__ge__</span></code> (greater than or equal to) magic method on the object class in which
you figure out which word has greater significance, perhaps through use of a mapping table
(<code class="docutils literal notranslate"><span class="pre">{'small':0,</span> <span class="pre">'large':10}</span></code>) or other lookup and comparing the numeric values of each.</p>
<p>Evennia extensively makes use of magic methods on typeclasses to do things like initialize objects,
check object existence or iterate over objects in an inventory or container. If you override or
interfere with the return values from the methods Evennia expects to be both present and working, it
can result in very inconsistent and hard-to-diagnose errors.</p>
<p>The moral of the story it can be dangerous to tinker with magic methods on typeclassed objects.
Try to avoid doing so.</p>
</section>
<section id="things-to-remember-about-the-flat-api">
<h2>Things to remember about the flat API<a class="headerlink" href="#things-to-remember-about-the-flat-api" title="Permalink to this headline"></a></h2>
<p>The flat API is a series of shortcuts on the <code class="docutils literal notranslate"><span class="pre">evennia</span></code> main library root (defined in
<code class="docutils literal notranslate"><span class="pre">evennia/__init__.py</span></code>). Its componentas are documented <a class="reference internal" href="../Evennia-API.html"><span class="doc std std-doc">as part of the auto-documentation</span></a>.</p>
<section id="to-remember-when-importing-from-evennia">
<h3>To remember when importing from <code class="docutils literal notranslate"><span class="pre">evennia</span></code><a class="headerlink" href="#to-remember-when-importing-from-evennia" title="Permalink to this headline"></a></h3>
<p>Properties on the root of the <code class="docutils literal notranslate"><span class="pre">evennia</span></code> package are <em>not</em> modules in their own right. They are just
shortcut properties stored in the <code class="docutils literal notranslate"><span class="pre">evennia/__init__.py</span></code> module. That means that you cannot use dot-
notation to <code class="docutils literal notranslate"><span class="pre">import</span></code> nested module-names over <code class="docutils literal notranslate"><span class="pre">evennia</span></code>. The rule of thumb is that you cannot use
<code class="docutils literal notranslate"><span class="pre">import</span></code> for more than one level down. Hence you can do</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="kn">import</span> <span class="nn">evennia</span>
<span class="nb">print</span><span class="p">(</span><span class="n">evennia</span><span class="o">.</span><span class="n">default_cmds</span><span class="o">.</span><span class="n">CmdLook</span><span class="p">)</span>
</pre></div>
</div>
<p>or import one level down</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">default_cmds</span>
<span class="nb">print</span><span class="p">(</span><span class="n">default_cmds</span><span class="o">.</span><span class="n">CmdLook</span><span class="p">)</span>
</pre></div>
</div>
<p>but you <em>cannot</em> import two levels down</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="kn">from</span> <span class="nn">evennia.default_cmds</span> <span class="kn">import</span> <span class="n">CmdLook</span> <span class="c1"># error!</span>
</pre></div>
</div>
<p>This will give you an <code class="docutils literal notranslate"><span class="pre">ImportError</span></code> telling you that the module <code class="docutils literal notranslate"><span class="pre">default_cmds</span></code> cannot be found -
this is becasue <code class="docutils literal notranslate"><span class="pre">default_cmds</span></code> is just a <em>variable</em> stored in <code class="docutils literal notranslate"><span class="pre">evennia.__init__.py</span></code>; this cannot be
imported from. If you really want full control over which level of package you import you can always
bypass the root package and import directly from from the real location. For example
<code class="docutils literal notranslate"><span class="pre">evennia.DefaultObject</span></code> is a shortcut to <code class="docutils literal notranslate"><span class="pre">evennia.objects.objects.DefaultObject</span></code>. Using this full
path will have the import mechanism work normally. See <code class="docutils literal notranslate"><span class="pre">evennia/__init__.py</span></code> to see where the
package imports from.</p>
</section>
</section>
</section>
</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="right" >
<a href="Changelog.html" title="Changelog"
>next</a> |</li>
<li class="right" >
<a href="Profiling.html" title="Profiling"
>previous</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="Coding-Overview.html" >Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Quirks</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>

View file

@ -0,0 +1,257 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Setting up PyCharm with Evennia &#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" />
<link rel="next" title="Contribs" href="../Contribs/Contribs-Overview.html" />
<link rel="prev" title="Continuous Integration - TeamCity (linux)" href="Continuous-Integration-TeamCity.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="right" >
<a href="../Contribs/Contribs-Overview.html" title="Contribs"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="Continuous-Integration-TeamCity.html" title="Continuous Integration - TeamCity (linux)"
accesskey="P">previous</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="Coding-Overview.html" accesskey="U">Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Setting up PyCharm with Evennia</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="document">
<div class="documentwrapper">
<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><a href="../index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Setting up PyCharm with Evennia</a><ul>
<li><a class="reference internal" href="#setting-up-the-project-interpreter">Setting up the project interpreter</a></li>
<li><a class="reference internal" href="#attaching-pycharm-debugger-to-evennia">Attaching PyCharm debugger to Evennia</a></li>
<li><a class="reference internal" href="#setting-up-an-evennia-run-configuration">Setting up an Evennia run configuration</a></li>
<li><a class="reference internal" href="#alternative-run-configuration-utilizing-logfiles-as-source-of-data">Alternative run configuration - utilizing logfiles as source of data</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="Continuous-Integration-TeamCity.html"
title="previous chapter">Continuous Integration - TeamCity (linux)</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="../Contribs/Contribs-Overview.html"
title="next chapter">Contribs</a></p>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Coding/Setting-up-PyCharm.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com">Home page</a> </li>
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
<h3>Versions</h3>
<ul>
<li><a href="Setting-up-PyCharm.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
</ul>
</div>
</div>
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="setting-up-pycharm-with-evennia">
<h1>Setting up PyCharm with Evennia<a class="headerlink" href="#setting-up-pycharm-with-evennia" title="Permalink to this headline"></a></h1>
<p><a class="reference external" href="https://www.jetbrains.com/pycharm/">PyCharm</a> is a Python developers IDE from Jetbrains available
for Windows, Mac and Linux. It is a commercial product but offer free trials, a scaled-down
community edition and also generous licenses for OSS projects like Evennia.</p>
<blockquote>
<div><p>This page was originally tested on Windows (so use Windows-style path examples), but should work
the same for all platforms.</p>
</div></blockquote>
<p>First, install Evennia on your local machine with [[Getting Started]]. If youre new to PyCharm,
loading your project is as easy as selecting the <code class="docutils literal notranslate"><span class="pre">Open</span></code> option when PyCharm starts, and browsing to
your game folder (the one created with <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">--init</span></code>). We refer to it as <code class="docutils literal notranslate"><span class="pre">mygame</span></code> here.</p>
<p>If you want to be able to examine evennias core code or the scripts inside your virtualenv, youll
need to add them to your project too:</p>
<ol class="simple">
<li><p>Go to <code class="docutils literal notranslate"><span class="pre">File</span> <span class="pre">&gt;</span> <span class="pre">Open...</span></code></p></li>
<li><p>Select the folder (i.e. the <code class="docutils literal notranslate"><span class="pre">evennia</span></code> root)</p></li>
<li><p>Select “Open in current window” and “Add to currently opened projects”</p></li>
</ol>
<section id="setting-up-the-project-interpreter">
<h2>Setting up the project interpreter<a class="headerlink" href="#setting-up-the-project-interpreter" title="Permalink to this headline"></a></h2>
<p>Its a good idea to do this before attempting anything further. The rest of this page assumes your
project is already configured in PyCharm.</p>
<ol class="simple">
<li><p>Go to <code class="docutils literal notranslate"><span class="pre">File</span> <span class="pre">&gt;</span> <span class="pre">Settings...</span> <span class="pre">&gt;</span> <span class="pre">Project:</span> <span class="pre">\&lt;mygame\&gt;</span> <span class="pre">&gt;</span> <span class="pre">Project</span> <span class="pre">Interpreter</span></code></p></li>
<li><p>Click the Gear symbol <code class="docutils literal notranslate"><span class="pre">&gt;</span> <span class="pre">Add</span> <span class="pre">local</span></code></p></li>
<li><p>Navigate to your <code class="docutils literal notranslate"><span class="pre">evenv/scripts</span> <span class="pre">directory</span></code>, and select Python.exe</p></li>
</ol>
<p>Enjoy seeing all your imports checked properly, setting breakpoints, and live variable watching!</p>
</section>
<section id="attaching-pycharm-debugger-to-evennia">
<h2>Attaching PyCharm debugger to Evennia<a class="headerlink" href="#attaching-pycharm-debugger-to-evennia" title="Permalink to this headline"></a></h2>
<ol class="simple">
<li><p>Launch Evennia in your preferred way (usually from a console/terminal)</p></li>
<li><p>Open your project in PyCharm</p></li>
<li><p>In the PyCharm menu, select <code class="docutils literal notranslate"><span class="pre">Run</span> <span class="pre">&gt;</span> <span class="pre">Attach</span> <span class="pre">to</span> <span class="pre">Local</span> <span class="pre">Process...</span></code></p></li>
<li><p>From the list, pick the <code class="docutils literal notranslate"><span class="pre">twistd</span></code> process with the <code class="docutils literal notranslate"><span class="pre">server.py</span></code> parameter (Example: <code class="docutils literal notranslate"><span class="pre">twistd.exe</span> <span class="pre">--nodaemon</span> <span class="pre">--logfile=\&lt;mygame\&gt;\server\logs\server.log</span> <span class="pre">--python=\&lt;evennia</span> <span class="pre">repo\&gt;\evennia\server\server.py</span></code>)</p></li>
</ol>
<p>Of course you can attach to the <code class="docutils literal notranslate"><span class="pre">portal</span></code> process as well. If you want to debug the Evennia launcher
or runner for some reason (or just learn how they work!), see Run Configuration below.</p>
<blockquote>
<div><p>NOTE: Whenever you reload Evennia, the old Server process will die and a new one start. So when
you restart you have to detach from the old and then reattach to the new process that was created.</p>
</div></blockquote>
<blockquote>
<div><p>To make the process less tedious you can apply a filter in settings to show only the <a class="reference external" href="http://server.py">server.py</a>
process in the list. To do that navigate to: <code class="docutils literal notranslate"><span class="pre">Settings/Preferences</span> <span class="pre">|</span> <span class="pre">Build,</span> <span class="pre">Execution,</span> <span class="pre">Deployment</span> <span class="pre">|</span> <span class="pre">Python</span> <span class="pre">Debugger</span></code> and then in <code class="docutils literal notranslate"><span class="pre">Attach</span> <span class="pre">to</span> <span class="pre">process</span></code> field put in: <code class="docutils literal notranslate"><span class="pre">twistd.exe&quot;</span> <span class="pre">--nodaemon</span></code>. This is an
example for windows, I dont have a working mac/linux box.
<img alt="Example process filter configuration" src="https://i.imgur.com/vkSheR8.png" /></p>
</div></blockquote>
</section>
<section id="setting-up-an-evennia-run-configuration">
<h2>Setting up an Evennia run configuration<a class="headerlink" href="#setting-up-an-evennia-run-configuration" title="Permalink to this headline"></a></h2>
<p>This configuration allows you to launch Evennia from inside PyCharm. Besides convenience, it also
allows suspending and debugging the evennia_launcher or evennia_runner at points earlier than you
could by running them externally and attaching. In fact by the time the server and/or portal are
running the launcher will have exited already.</p>
<ol class="simple">
<li><p>Go to <code class="docutils literal notranslate"><span class="pre">Run</span> <span class="pre">&gt;</span> <span class="pre">Edit</span> <span class="pre">Configutations...</span></code></p></li>
<li><p>Click the plus-symbol to add a new configuration and choose Python</p></li>
<li><p>Add the script: <code class="docutils literal notranslate"><span class="pre">\&lt;yourrepo\&gt;\evenv\Scripts\evennia_launcher.py</span></code> (substitute your virtualenv if
its not named <code class="docutils literal notranslate"><span class="pre">evenv</span></code>)</p></li>
<li><p>Set script parameters to: <code class="docutils literal notranslate"><span class="pre">start</span> <span class="pre">-l</span></code> (-l enables console logging)</p></li>
<li><p>Ensure the chosen interpreter is from your virtualenv</p></li>
<li><p>Set Working directory to your <code class="docutils literal notranslate"><span class="pre">mygame</span></code> folder (not evenv nor evennia)</p></li>
<li><p>You can refer to the PyCharm documentation for general info, but youll want to set at least a
config name (like “MyMUD start” or similar).</p></li>
</ol>
<p>Now set up a “stop” configuration by following the same steps as above, but set your Script
parameters to: stop (and name the configuration appropriately).</p>
<p>A dropdown box holding your new configurations should appear next to your PyCharm run button.
Select MyMUD start and press the debug icon to begin debugging. Depending on how far you let the
program run, you may need to run your “MyMUD stop” config to actually stop the server, before youll
be able start it again.</p>
</section>
<section id="alternative-run-configuration-utilizing-logfiles-as-source-of-data">
<h2>Alternative run configuration - utilizing logfiles as source of data<a class="headerlink" href="#alternative-run-configuration-utilizing-logfiles-as-source-of-data" title="Permalink to this headline"></a></h2>
<p>This configuration takes a bit different approach as instead of focusing on getting the data back
through logfiles. Reason for that is this way you can easily separate data streams, for example you
rarely want to follow both server and portal at the same time, and this will allow it. This will
also make sure to stop the evennia before starting it, essentially working as reload command (it
will also include instructions how to disable that part of functionality). We will start by defining
a configuration that will stop evennia. This assumes that <code class="docutils literal notranslate"><span class="pre">upfire</span></code> is your pycharm project name, and
also the game name, hence the <code class="docutils literal notranslate"><span class="pre">upfire/upfire</span></code> path.</p>
<ol class="simple">
<li><p>Go to <code class="docutils literal notranslate"><span class="pre">Run</span> <span class="pre">&gt;</span> <span class="pre">Edit</span> <span class="pre">Configutations...</span></code>\</p></li>
<li><p>Click the plus-symbol to add a new configuration and choose the python interpreter to use (should
be project default)</p></li>
<li><p>Name the configuration as “stop evennia” and fill rest of the fields accordingly to the image:
<img alt="Stop run configuration" src="https://i.imgur.com/gbkXhlG.png" /></p></li>
<li><p>Press <code class="docutils literal notranslate"><span class="pre">Apply</span></code></p></li>
</ol>
<p>Now we will define the start/reload command that will make sure that evennia is not running already,
and then start the server in one go.</p>
<ol class="simple">
<li><p>Go to <code class="docutils literal notranslate"><span class="pre">Run</span> <span class="pre">&gt;</span> <span class="pre">Edit</span> <span class="pre">Configutations...</span></code>\</p></li>
<li><p>Click the plus-symbol to add a new configuration and choose the python interpreter to use (should
be project default)</p></li>
<li><p>Name the configuration as “start evennia” and fill rest of the fields accordingly to the image:
<img alt="Start run configuration" src="https://i.imgur.com/5YEjeHq.png" /></p></li>
<li><p>Navigate to the <code class="docutils literal notranslate"><span class="pre">Logs</span></code> tab and add the log files you would like to follow. The picture shows
adding <code class="docutils literal notranslate"><span class="pre">portal.log</span></code> which will show itself in <code class="docutils literal notranslate"><span class="pre">portal</span></code> tab when running:
<img alt="Configuring logs following" src="https://i.imgur.com/gWYuOWl.png" /></p></li>
<li><p>Skip the following steps if you dont want the launcher to stop evennia before starting.</p></li>
<li><p>Head back to <code class="docutils literal notranslate"><span class="pre">Configuration</span></code> tab and press the <code class="docutils literal notranslate"><span class="pre">+</span></code> sign at the bottom, under <code class="docutils literal notranslate"><span class="pre">Before</span> <span class="pre">launch....</span></code>
and select <code class="docutils literal notranslate"><span class="pre">Run</span> <span class="pre">another</span> <span class="pre">configuration</span></code> from the submenu that will pop up.</p></li>
<li><p>Click <code class="docutils literal notranslate"><span class="pre">stop</span> <span class="pre">evennia</span></code> and make sure that its added to the list like on the image above.</p></li>
<li><p>Click <code class="docutils literal notranslate"><span class="pre">Apply</span></code> and close the run configuration window.</p></li>
</ol>
<p>You are now ready to go, and if you will fire up <code class="docutils literal notranslate"><span class="pre">start</span> <span class="pre">evennia</span></code> configuration you should see
following in the bottom panel:
<img alt="Example of running alternative configuration" src="https://i.imgur.com/nTfpC04.png" />
and you can click through the tabs to check appropriate logs, or even the console output as it is
still running in interactive mode.</p>
</section>
</section>
</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="right" >
<a href="../Contribs/Contribs-Overview.html" title="Contribs"
>next</a> |</li>
<li class="right" >
<a href="Continuous-Integration-TeamCity.html" title="Continuous Integration - TeamCity (linux)"
>previous</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="Coding-Overview.html" >Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Setting up PyCharm with Evennia</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>

View file

@ -0,0 +1,448 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Unit Testing &#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" />
<link rel="next" title="Profiling" href="Profiling.html" />
<link rel="prev" title="Debugging" href="Debugging.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="right" >
<a href="Profiling.html" title="Profiling"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="Debugging.html" title="Debugging"
accesskey="P">previous</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="Coding-Overview.html" accesskey="U">Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Unit Testing</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="document">
<div class="documentwrapper">
<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><a href="../index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Unit Testing</a><ul>
<li><a class="reference internal" href="#running-the-evennia-test-suite">Running the Evennia test suite</a></li>
<li><a class="reference internal" href="#running-tests-for-your-game-dir">Running tests for your game dir</a></li>
<li><a class="reference internal" href="#writing-new-tests">Writing new tests</a></li>
<li><a class="reference internal" href="#using-the-evennia-testing-classes">Using the Evennia testing classes</a><ul>
<li><a class="reference internal" href="#classes-for-testing-your-game-dir">Classes for testing your game dir</a></li>
<li><a class="reference internal" href="#classes-for-testing-evennia-core">Classes for testing Evennia core</a></li>
</ul>
</li>
<li><a class="reference internal" href="#unit-testing-contribs-with-custom-models">Unit testing contribs with custom models</a></li>
<li><a class="reference internal" href="#a-note-on-making-the-test-runner-faster">A note on making the test runner faster</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="Debugging.html"
title="previous chapter">Debugging</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="Profiling.html"
title="next chapter">Profiling</a></p>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Coding/Unit-Testing.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com">Home page</a> </li>
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
<h3>Versions</h3>
<ul>
<li><a href="Unit-Testing.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
</ul>
</div>
</div>
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="unit-testing">
<h1>Unit Testing<a class="headerlink" href="#unit-testing" title="Permalink to this headline"></a></h1>
<p><em>Unit testing</em> means testing components of a program in isolation from each other to make sure every
part works on its own before using it with others. Extensive testing helps avoid new updates causing
unexpected side effects as well as alleviates general code rot (a more comprehensive wikipedia
article on unit testing can be found <a class="reference external" href="https://en.wikipedia.org/wiki/Unit_test">here</a>).</p>
<p>A typical unit test set calls some function or method with a given input, looks at the result and
makes sure that this result looks as expected. Rather than having lots of stand-alone test programs,
Evennia makes use of a central <em>test runner</em>. This is a program that gathers all available tests all
over the Evennia source code (called <em>test suites</em>) and runs them all in one go. Errors and
tracebacks are reported.</p>
<p>By default Evennia only tests itself. But you can also add your own tests to your game code and have
Evennia run those for you.</p>
<section id="running-the-evennia-test-suite">
<h2>Running the Evennia test suite<a class="headerlink" href="#running-the-evennia-test-suite" title="Permalink to this headline"></a></h2>
<p>To run the full Evennia test suite, go to your game folder and issue the command</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia test evennia
</pre></div>
</div>
<p>This will run all the evennia tests using the default settings. You could also run only a subset of
all tests by specifying a subpackage of the library:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia test evennia.commands.default
</pre></div>
</div>
<p>A temporary database will be instantiated to manage the tests. If everything works out you will see
how many tests were run and how long it took. If something went wrong you will get error messages.
If you contribute to Evennia, this is a useful sanity check to see you havent introduced an
unexpected bug.</p>
</section>
<section id="running-tests-for-your-game-dir">
<h2>Running tests for your game dir<a class="headerlink" href="#running-tests-for-your-game-dir" title="Permalink to this headline"></a></h2>
<p>If you have implemented your own tests for your game you can run them from your game dir
with</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia test --settings settings.py .
</pre></div>
</div>
<p>The period (<code class="docutils literal notranslate"><span class="pre">.</span></code>) means to run all tests found in the current directory and all subdirectories. You
could also specify, say, <code class="docutils literal notranslate"><span class="pre">typeclasses</span></code> or <code class="docutils literal notranslate"><span class="pre">world</span></code> if you wanted to just run tests in those subdirs.</p>
<p>An important thing to note is that those tests will all be run using the <em>default Evennia settings</em>.
To run the tests with your own settings file you must use the <code class="docutils literal notranslate"><span class="pre">--settings</span></code> option:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia test --settings settings.py .
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">--settings</span></code> option of Evennia takes a file name in the <code class="docutils literal notranslate"><span class="pre">mygame/server/conf</span></code> folder. It is
normally used to swap settings files for testing and development. In combination with <code class="docutils literal notranslate"><span class="pre">test</span></code>, it
forces Evennia to use this settings file over the default one.</p>
<p>You can also test specific things by giving their path</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia test --settings settings.py .world.tests.YourTest
</pre></div>
</div>
</section>
<section id="writing-new-tests">
<h2>Writing new tests<a class="headerlink" href="#writing-new-tests" title="Permalink to this headline"></a></h2>
<p>Evennias test suite makes use of Django unit test system, which in turn relies on Pythons
<em>unittest</em> module.</p>
<p>To make the test runner find the tests, they must be put in a module named <code class="docutils literal notranslate"><span class="pre">test*.py</span></code> (so <code class="docutils literal notranslate"><span class="pre">test.py</span></code>,
<code class="docutils literal notranslate"><span class="pre">tests.py</span></code> etc). Such a test module will be found wherever it is in the package. It can be a good
idea to look at some of Evennias <code class="docutils literal notranslate"><span class="pre">tests.py</span></code> modules to see how they look.</p>
<p>Inside the module you need to put a class inheriting (at any distance) from <code class="docutils literal notranslate"><span class="pre">unittest.TestCase</span></code>. Each
method on that class that starts with <code class="docutils literal notranslate"><span class="pre">test_</span></code> will be run separately as a unit test. There
are two special, optional methods <code class="docutils literal notranslate"><span class="pre">setUp</span></code> and <code class="docutils literal notranslate"><span class="pre">tearDown</span></code> that will (if you define them) run before
<em>every</em> test. This can be useful for setting up and deleting things.</p>
<p>To actually test things, you use special <code class="docutils literal notranslate"><span class="pre">assert...</span></code> methods on the class. Most common on is
<code class="docutils literal notranslate"><span class="pre">assertEqual</span></code>, which makes sure a result is what you expect it to be.</p>
<p>Heres an example of the principle. Lets assume you put this in <code class="docutils literal notranslate"><span class="pre">mygame/world/tests.py</span></code>
and want to test a function in <code class="docutils literal notranslate"><span class="pre">mygame/world/myfunctions.py</span></code></p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1"># in a module tests.py somewhere i your game dir</span>
<span class="kn">import</span> <span class="nn">unittest</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">create_object</span>
<span class="c1"># the function we want to test</span>
<span class="kn">from</span> <span class="nn">.myfunctions</span> <span class="kn">import</span> <span class="n">myfunc</span>
<span class="k">class</span> <span class="nc">TestObj</span><span class="p">(</span><span class="n">unittest</span><span class="o">.</span><span class="n">TestCase</span><span class="p">):</span>
<span class="s2">&quot;This tests a function myfunc.&quot;</span>
<span class="k">def</span> <span class="nf">setUp</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;done before every of the test_ * methods below&quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">obj</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">(</span><span class="s2">&quot;mytestobject&quot;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">tearDown</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;done after every test_* method below &quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">obj</span><span class="o">.</span><span class="n">delete</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">test_return_value</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;test method. Makes sure return value is as expected.&quot;&quot;&quot;</span>
<span class="n">actual_return</span> <span class="o">=</span> <span class="n">myfunc</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">obj</span><span class="p">)</span>
<span class="n">expected_return</span> <span class="o">=</span> <span class="s2">&quot;This is the good object &#39;mytestobject&#39;.&quot;</span>
<span class="c1"># test</span>
<span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">expected_return</span><span class="p">,</span> <span class="n">actual_return</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_alternative_call</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;test method. Calls with a keyword argument.&quot;&quot;&quot;</span>
<span class="n">actual_return</span> <span class="o">=</span> <span class="n">myfunc</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">obj</span><span class="p">,</span> <span class="n">bad</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="n">expected_return</span> <span class="o">=</span> <span class="s2">&quot;This is the baaad object &#39;mytestobject&#39;.&quot;</span>
<span class="c1"># test</span>
<span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">expected_return</span><span class="p">,</span> <span class="n">actual_return</span><span class="p">)</span>
</pre></div>
</div>
<p>To test this, run</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia test --settings settings.py .
</pre></div>
</div>
<p>to run the entire test module</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia test --settings setings.py .world.tests
</pre></div>
</div>
<p>or a specific class:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia test --settings settings.py .world.tests.TestObj
</pre></div>
</div>
<p>You can also run a specific test:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia test --settings settings.py .world.tests.TestObj.test_alternative_call
</pre></div>
</div>
<p>You might also want to read the <a class="reference external" href="https://docs.python.org/library/unittest.html">Python documentation for the unittest module</a>.</p>
</section>
<section id="using-the-evennia-testing-classes">
<h2>Using the Evennia testing classes<a class="headerlink" href="#using-the-evennia-testing-classes" title="Permalink to this headline"></a></h2>
<p>Evennia offers many custom testing classes that helps with testing Evennia features.
They are all found in <a class="reference internal" href="../api/evennia.utils.test_resources.html#evennia-utils-test-resources"><span class="std std-ref">evennia.utils.test_resources</span></a>. Note that
these classes implement the <code class="docutils literal notranslate"><span class="pre">setUp</span></code> and <code class="docutils literal notranslate"><span class="pre">tearDown</span></code> already, so if you want to add stuff in them
yourself you should remember to use e.g. <code class="docutils literal notranslate"><span class="pre">super().setUp()</span></code> in your code.</p>
<section id="classes-for-testing-your-game-dir">
<h3>Classes for testing your game dir<a class="headerlink" href="#classes-for-testing-your-game-dir" title="Permalink to this headline"></a></h3>
<p>These all use whatever setting you pass to them and works well for testing code in your game dir.</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">EvenniaTest</span></code> - this sets up a full object environment for your test. All the created entities
can be accesses as properties on the class:</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">.account</span></code> - A fake <a class="reference internal" href="../api/evennia.accounts.accounts.html#evennia.accounts.accounts.DefaultAccount" title="evennia.accounts.accounts.DefaultAccount"><span class="xref myst py py-class">Account</span></a> named “TestAccount”.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">.account2</span></code> - Another account named “TestAccount2”</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">char1</span></code> - A <a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultCharacter" title="evennia.objects.objects.DefaultCharacter"><span class="xref myst py py-class">Character</span></a> linked to <code class="docutils literal notranslate"><span class="pre">.account</span></code>, named <code class="docutils literal notranslate"><span class="pre">Char</span></code>.
This has Developer permissions but is not a superuser.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">.char2</span></code> - Another character linked to <code class="docutils literal notranslate"><span class="pre">account</span></code>, named <code class="docutils literal notranslate"><span class="pre">Char2</span></code>. This has base permissions (player).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">.obj1</span></code> - A regular <a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultObject" title="evennia.objects.objects.DefaultObject"><span class="xref myst py py-class">Object</span></a> named “Obj”.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">.obj2</span></code> - Another object named “Obj2”.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">.room1</span></code> - A <a class="reference internal" href="../api/evennia.objects.objects.html#evennia.objects.objects.DefaultRoom" title="evennia.objects.objects.DefaultRoom"><span class="xref myst py py-class">Room</span></a> named “Room”. Both characters and both
objects are located inside this room. It has a description of “room_desc”.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">.room2</span></code> - Another room named “Room2”. It is empty and has no set description.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">.exit</span></code> - An exit named “out” that leads from <code class="docutils literal notranslate"><span class="pre">.room1</span></code> to <code class="docutils literal notranslate"><span class="pre">.room2</span></code>.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">.script</span></code> - A <a class="reference internal" href="../api/evennia.scripts.scripts.html#evennia.scripts.scripts.DefaultScript" title="evennia.scripts.scripts.DefaultScript"><span class="xref myst py py-class">Script</span></a> named “Script”. Its an inert script
without a timing component.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">.session</span></code> - A fake <a class="reference internal" href="../api/evennia.server.serversession.html#evennia.server.serversession.ServerSession" title="evennia.server.serversession.ServerSession"><span class="xref myst py py-class">Session</span></a> that mimics a player
connecting to the game. It is used by <code class="docutils literal notranslate"><span class="pre">.account1</span></code> and has a sessid of 1.</p></li>
</ul>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">EvenniaCommandTest</span></code> - has the same environment like <code class="docutils literal notranslate"><span class="pre">EvenniaTest</span></code> but also adds a special
<a class="reference internal" href="../api/evennia.utils.test_resources.html#evennia.utils.test_resources.EvenniaCommandTestMixin.call" title="evennia.utils.test_resources.EvenniaCommandTestMixin.call"><span class="xref myst py py-meth">.call()</span></a> method specifically for
testing Evennia <a class="reference internal" href="../Components/Commands.html"><span class="doc std std-doc">Commands</span></a>. It allows you to compare what the command <em>actually</em>
returns to the player with what you expect. Read the <code class="docutils literal notranslate"><span class="pre">call</span></code> api doc for more info.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">EvenniaTestCase</span></code> - This is identical to the regular Python <code class="docutils literal notranslate"><span class="pre">TestCase</span></code> class, its
just there for naming symmetry with <code class="docutils literal notranslate"><span class="pre">BaseEvenniaTestCase</span></code> below.</p></li>
</ul>
<p>Heres an example of using <code class="docutils literal notranslate"><span class="pre">EvenniaTest</span></code></p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># in a test module</span>
<span class="kn">from</span> <span class="nn">evennia.utils.test_resources</span> <span class="kn">import</span> <span class="n">EvenniaTest</span>
<span class="k">class</span> <span class="nc">TestObject</span><span class="p">(</span><span class="n">EvenniaTest</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Remember that the testing class creates char1 and char2 inside room1 ...&quot;&quot;&quot;</span>
<span class="k">def</span> <span class="nf">test_object_search_character</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Check that char1 can search for char2 by name&quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">char1</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">char2</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">char2</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_location_search</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Check so that char1 can find the current location by name&quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">char1</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">char1</span><span class="o">.</span><span class="n">location</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">char1</span><span class="o">.</span><span class="n">location</span><span class="p">)</span>
<span class="c1"># ...</span>
</pre></div>
</div>
<p>This example tests a custom command.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="kn">from</span> <span class="nn">evennia.commands.default.tests</span> <span class="kn">import</span> <span class="n">EvenniaCommandTest</span>
<span class="kn">from</span> <span class="nn">commands</span> <span class="kn">import</span> <span class="n">command</span> <span class="k">as</span> <span class="n">mycommand</span>
<span class="k">class</span> <span class="nc">TestSet</span><span class="p">(</span><span class="n">EvenniaCommandTest</span><span class="p">):</span>
<span class="s2">&quot;tests the look command by simple call, using Char2 as a target&quot;</span>
<span class="k">def</span> <span class="nf">test_mycmd_char</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="n">mycommand</span><span class="o">.</span><span class="n">CmdMyLook</span><span class="p">(),</span> <span class="s2">&quot;Char2&quot;</span><span class="p">,</span> <span class="s2">&quot;Char2(#7)&quot;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_mycmd_room</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="s2">&quot;tests the look command by simple call, with target as room&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="n">mycommand</span><span class="o">.</span><span class="n">CmdMyLook</span><span class="p">(),</span> <span class="s2">&quot;Room&quot;</span><span class="p">,</span>
<span class="s2">&quot;Room(#1)</span><span class="se">\n</span><span class="s2">room_desc</span><span class="se">\n</span><span class="s2">Exits: out(#3)</span><span class="se">\n</span><span class="s2">&quot;</span>
<span class="s2">&quot;You see: Obj(#4), Obj2(#5), Char2(#7)&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>When using <code class="docutils literal notranslate"><span class="pre">.call</span></code>, you dont need to specify the entire string; you can just give the beginning
of it and if it matches, thats enough. Use <code class="docutils literal notranslate"><span class="pre">\n</span></code> to denote line breaks and (this is a special for
the <code class="docutils literal notranslate"><span class="pre">.call</span></code> helper), <code class="docutils literal notranslate"><span class="pre">||</span></code> to indicate multiple uses of <code class="docutils literal notranslate"><span class="pre">.msg()</span></code> in the Command. The <code class="docutils literal notranslate"><span class="pre">.call</span></code> helper
has a lot of arguments for mimicing different ways of calling a Command, so make sure to
<a class="reference internal" href="../api/evennia.utils.test_resources.html#evennia.utils.test_resources.EvenniaCommandTestMixin.call" title="evennia.utils.test_resources.EvenniaCommandTestMixin.call"><span class="xref myst py py-meth">read the API docs for .call()</span></a>.</p>
</section>
<section id="classes-for-testing-evennia-core">
<h3>Classes for testing Evennia core<a class="headerlink" href="#classes-for-testing-evennia-core" title="Permalink to this headline"></a></h3>
<p>These are used for testing Evennia itself. They provide the same resources as the classes
above but enforce Evennias default settings found in <code class="docutils literal notranslate"><span class="pre">evennia/settings_default.py</span></code>, ignoring
any settings changes in your game dir.</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">BaseEvenniaTest</span></code> - all the default objects above but with enforced default settings</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">BaseEvenniaCommandTest</span></code> - for testing Commands, but with enforced default settings</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">BaseEvenniaTestCase</span></code> - no default objects, only enforced default settings</p></li>
</ul>
<p>There are also two special mixin classes. These are uses in the classes above, but may also
be useful if you want to mix your own testing classes:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">EvenniaTestMixin</span></code> - A class mixin that creates all test environment objects.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">EvenniaCommandMixin</span></code> - A class mixin that adds the <code class="docutils literal notranslate"><span class="pre">.call()</span></code> Command-tester helper.</p></li>
</ul>
<p>If you want to help out writing unittests for Evennia, take a look at Evennias <a class="reference external" href="https://coveralls.io/github/evennia/evennia">coveralls.io
page</a>. There you see which modules have any form of
test coverage and which does not. All help is appreciated!</p>
</section>
</section>
<section id="unit-testing-contribs-with-custom-models">
<h2>Unit testing contribs with custom models<a class="headerlink" href="#unit-testing-contribs-with-custom-models" title="Permalink to this headline"></a></h2>
<p>A special case is if you were to create a contribution to go to the <code class="docutils literal notranslate"><span class="pre">evennia/contrib</span></code> folder that
uses its <a class="reference internal" href="../Concepts/New-Models.html"><span class="doc std std-doc">own database models</span></a>. The problem with this is that Evennia (and Django) will
only recognize models in <code class="docutils literal notranslate"><span class="pre">settings.INSTALLED_APPS</span></code>. If a user wants to use your contrib, they will
be required to add your models to their settings file. But since contribs are optional you cannot
add the model to Evennias central <code class="docutils literal notranslate"><span class="pre">settings_default.py</span></code> file - this would always create your
optional models regardless of if the user wants them. But at the same time a contribution is a part
of the Evennia distribution and its unit tests should be run with all other Evennia tests using
<code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">test</span> <span class="pre">evennia</span></code>.</p>
<p>The way to do this is to only temporarily add your models to the <code class="docutils literal notranslate"><span class="pre">INSTALLED_APPS</span></code> directory when the
test runs. here is an example of how to do it.</p>
<blockquote>
<div><p>Note that this solution, derived from this [stackexchange
answer](<a class="reference external" href="http://stackoverflow.com/questions/502916/django-how-to-create-a-model-dynamically-just-for-">http://stackoverflow.com/questions/502916/django-how-to-create-a-model-dynamically-just-for-</a>
testing#503435) is currently untested! Please report your findings.</p>
</div></blockquote>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># a file contrib/mycontrib/tests.py</span>
<span class="kn">from</span> <span class="nn">django.conf</span> <span class="kn">import</span> <span class="n">settings</span>
<span class="kn">import</span> <span class="nn">django</span>
<span class="kn">from</span> <span class="nn">evennia.utils.test_resources</span> <span class="kn">import</span> <span class="n">BaseEvenniaTest</span>
<span class="n">OLD_DEFAULT_SETTINGS</span> <span class="o">=</span> <span class="n">settings</span><span class="o">.</span><span class="n">INSTALLED_APPS</span>
<span class="n">DEFAULT_SETTINGS</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span>
<span class="n">INSTALLED_APPS</span><span class="o">=</span><span class="p">(</span>
<span class="s1">&#39;contrib.mycontrib.tests&#39;</span><span class="p">,</span>
<span class="p">),</span>
<span class="n">DATABASES</span><span class="o">=</span><span class="p">{</span>
<span class="s2">&quot;default&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="s2">&quot;ENGINE&quot;</span><span class="p">:</span> <span class="s2">&quot;django.db.backends.sqlite3&quot;</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="n">SILENCED_SYSTEM_CHECKS</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;1_7.W001&quot;</span><span class="p">],</span>
<span class="p">)</span>
<span class="k">class</span> <span class="nc">TestMyModel</span><span class="p">(</span><span class="n">BaseEvenniaTest</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">setUp</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">settings</span><span class="o">.</span><span class="n">configured</span><span class="p">:</span>
<span class="n">settings</span><span class="o">.</span><span class="n">configure</span><span class="p">(</span><span class="o">**</span><span class="n">DEFAULT_SETTINGS</span><span class="p">)</span>
<span class="n">django</span><span class="o">.</span><span class="n">setup</span><span class="p">()</span>
<span class="kn">from</span> <span class="nn">django.core.management</span> <span class="kn">import</span> <span class="n">call_command</span>
<span class="kn">from</span> <span class="nn">django.db.models</span> <span class="kn">import</span> <span class="n">loading</span>
<span class="n">loading</span><span class="o">.</span><span class="n">cache</span><span class="o">.</span><span class="n">loaded</span> <span class="o">=</span> <span class="kc">False</span>
<span class="n">call_command</span><span class="p">(</span><span class="s1">&#39;syncdb&#39;</span><span class="p">,</span> <span class="n">verbosity</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">tearDown</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">settings</span><span class="o">.</span><span class="n">configure</span><span class="p">(</span><span class="o">**</span><span class="n">OLD_DEFAULT_SETTINGS</span><span class="p">)</span>
<span class="n">django</span><span class="o">.</span><span class="n">setup</span><span class="p">()</span>
<span class="kn">from</span> <span class="nn">django.core.management</span> <span class="kn">import</span> <span class="n">call_command</span>
<span class="kn">from</span> <span class="nn">django.db.models</span> <span class="kn">import</span> <span class="n">loading</span>
<span class="n">loading</span><span class="o">.</span><span class="n">cache</span><span class="o">.</span><span class="n">loaded</span> <span class="o">=</span> <span class="kc">False</span>
<span class="n">call_command</span><span class="p">(</span><span class="s1">&#39;syncdb&#39;</span><span class="p">,</span> <span class="n">verbosity</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
<span class="c1"># test cases below ...</span>
<span class="k">def</span> <span class="nf">test_case</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="c1"># test case here</span>
</pre></div>
</div>
</section>
<section id="a-note-on-making-the-test-runner-faster">
<h2>A note on making the test runner faster<a class="headerlink" href="#a-note-on-making-the-test-runner-faster" title="Permalink to this headline"></a></h2>
<p>If you have custom models with a large number of migrations, creating the test database can take a
very long time. If you dont require migrations to run for your tests, you can disable them with the
django-test-without-migrations package. To install it, simply:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ pip install django-test-without-migrations
</pre></div>
</div>
<p>Then add it to your <code class="docutils literal notranslate"><span class="pre">INSTALLED_APPS</span></code> in your <code class="docutils literal notranslate"><span class="pre">server.conf.settings.py</span></code>:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">INSTALLED_APPS</span> <span class="o">=</span> <span class="p">(</span>
<span class="c1"># ...</span>
<span class="s1">&#39;test_without_migrations&#39;</span><span class="p">,</span>
<span class="p">)</span>
</pre></div>
</div>
<p>After doing so, you can then run tests without migrations by adding the <code class="docutils literal notranslate"><span class="pre">--nomigrations</span></code> argument:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">evennia</span> <span class="n">test</span> <span class="o">--</span><span class="n">settings</span> <span class="n">settings</span><span class="o">.</span><span class="n">py</span> <span class="o">--</span><span class="n">nomigrations</span> <span class="o">.</span>
</pre></div>
</div>
</section>
</section>
</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="right" >
<a href="Profiling.html" title="Profiling"
>next</a> |</li>
<li class="right" >
<a href="Debugging.html" title="Debugging"
>previous</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="Coding-Overview.html" >Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Unit Testing</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>

View file

@ -0,0 +1,271 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Updating Your Game &#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" />
<link rel="next" title="Coding Introduction" href="Coding-Introduction.html" />
<link rel="prev" title="Version Control" href="Version-Control.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="right" >
<a href="Coding-Introduction.html" title="Coding Introduction"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="Version-Control.html" title="Version Control"
accesskey="P">previous</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="Coding-Overview.html" accesskey="U">Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Updating Your Game</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="document">
<div class="documentwrapper">
<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><a href="../index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Updating Your Game</a><ul>
<li><a class="reference internal" href="#updating-with-the-latest-evennia-code-changes">Updating with the latest Evennia code changes</a></li>
<li><a class="reference internal" href="#upgrading-evennia-dependencies">Upgrading Evennia dependencies</a></li>
<li><a class="reference internal" href="#migrating-the-database-schema">Migrating the Database Schema</a></li>
<li><a class="reference internal" href="#resetting-your-database">Resetting your database</a></li>
<li><a class="reference internal" href="#more-about-schema-migrations">More about schema migrations</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="Version-Control.html"
title="previous chapter">Version Control</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="Coding-Introduction.html"
title="next chapter">Coding Introduction</a></p>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Coding/Updating-Your-Game.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com">Home page</a> </li>
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
<h3>Versions</h3>
<ul>
<li><a href="Updating-Your-Game.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
</ul>
</div>
</div>
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="updating-your-game">
<h1>Updating Your Game<a class="headerlink" href="#updating-your-game" title="Permalink to this headline"></a></h1>
<p>Fortunately, its extremely easy to keep your Evennia server up-to-date. If you havent already, see
the <a class="reference internal" href="../Setup/Installation.html"><span class="doc std std-doc">Getting Started guide</span></a> and get everything running.</p>
<section id="updating-with-the-latest-evennia-code-changes">
<h2>Updating with the latest Evennia code changes<a class="headerlink" href="#updating-with-the-latest-evennia-code-changes" title="Permalink to this headline"></a></h2>
<p>Very commonly we make changes to the Evennia code to improve things. There are many ways to get told
when to update: You can subscribe to the RSS feed or manually check up on the feeds from
<a class="reference external" href="https://www.evennia.com">https://www.evennia.com</a>. You can also simply fetch the latest regularly.</p>
<p>When youre wanting to apply updates, simply <code class="docutils literal notranslate"><span class="pre">cd</span></code> to your cloned <code class="docutils literal notranslate"><span class="pre">evennia</span></code> root directory and type:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> git pull
</pre></div>
</div>
<p>assuming youve got the command line client. If youre using a graphical client, you will probably
want to navigate to the <code class="docutils literal notranslate"><span class="pre">evennia</span></code> directory and either right click and find your clients pull
function, or use one of the menus (if applicable).</p>
<p>You can review the latest changes with</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> git log
</pre></div>
</div>
<p>or the equivalent in the graphical client. You can also see the latest changes online
<a class="reference external" href="https://github.com/evennia/evennia/blob/master/CHANGELOG.md">here</a>.</p>
<p>You will always need to do <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">reload</span></code> (or <code class="docutils literal notranslate"><span class="pre">reload</span></code> from -in-game) from your game-dir to have
the new code affect your game. If you want to be really sure you should run a full <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">reboot</span></code>
so that both Server and Portal can restart (this will disconnect everyone though, so if you know the
Portal has had no updates you dont have to do that).</p>
</section>
<section id="upgrading-evennia-dependencies">
<h2>Upgrading Evennia dependencies<a class="headerlink" href="#upgrading-evennia-dependencies" title="Permalink to this headline"></a></h2>
<p>On occasion we update the versions of third-party libraries Evennia depend on (or we may add a new
dependency). This will be announced on the mailing list/forum. If you run into errors when starting
Evennia, always make sure you have the latest versions of everything. In some cases, like for
Django, starting the server may also give warning saying that you are using a working, but too-old
version that should not be used in production.</p>
<p>Upgrading <code class="docutils literal notranslate"><span class="pre">evennia</span></code> will automatically fetch all the latest packages that it now need. First <code class="docutils literal notranslate"><span class="pre">cd</span></code> to
your cloned <code class="docutils literal notranslate"><span class="pre">evennia</span></code> folder. Make sure your <code class="docutils literal notranslate"><span class="pre">virtualenv</span></code> is active and use</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>pip install --upgrade -e .
</pre></div>
</div>
<p>Remember the period (<code class="docutils literal notranslate"><span class="pre">.</span></code>) at the end - that applies the upgrade to the current location (your
<code class="docutils literal notranslate"><span class="pre">evennia</span></code> dir).</p>
<blockquote>
<div><p>The <code class="docutils literal notranslate"><span class="pre">-e</span></code> means that we are <em>linking</em> the evennia sources rather than copying them into the
environment. This means we can most of the time just update the sources (with <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">pull</span></code>) and see
those changes directly applied to our installed <code class="docutils literal notranslate"><span class="pre">evennia</span></code> package. Without installing/upgrading the
package with <code class="docutils literal notranslate"><span class="pre">-e</span></code>, we would have to remember to upgrade the package every time we downloaded any new
source-code changes.</p>
</div></blockquote>
<p>Follow the upgrade output to make sure it finishes without errors. To check what packages are
currently available in your python environment after the upgrade, use</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>pip list
</pre></div>
</div>
<p>This will show you the version of all installed packages. The <code class="docutils literal notranslate"><span class="pre">evennia</span></code> package will also show the
location of its source code.</p>
</section>
<section id="migrating-the-database-schema">
<h2>Migrating the Database Schema<a class="headerlink" href="#migrating-the-database-schema" title="Permalink to this headline"></a></h2>
<p>Whenever we change the database layout of Evennia upstream (such as when we add new features) you
will need to <em>migrate</em> your existing database. When this happens it will be clearly noted in the
<code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">log</span></code> (it will say something to the effect of “Run migrations”). Database changes will also be
announced on the Evennia <a class="reference external" href="https://groups.google.com/forum/#%21forum/evennia">mailing list</a>.</p>
<p>When the database schema changes, you just go to your game folder and run</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> evennia migrate
</pre></div>
</div>
<blockquote>
<div><p>Hint: If the <code class="docutils literal notranslate"><span class="pre">evennia</span></code> command is not found, you most likely need to activate your
<a class="reference internal" href="../Glossary.html#virtualenv"><span class="std std-doc">virtualenv</span></a>.</p>
</div></blockquote>
</section>
<section id="resetting-your-database">
<h2>Resetting your database<a class="headerlink" href="#resetting-your-database" title="Permalink to this headline"></a></h2>
<p>Should you ever want to start over completely from scratch, there is no need to re-download Evennia
or anything like that. You just need to clear your database. Once you are done, you just rebuild it
from scratch by running</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia migrate
</pre></div>
</div>
<p>The first step in wiping your database is to stop Evennia completely with</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia stop
</pre></div>
</div>
<p>If you run the default <code class="docutils literal notranslate"><span class="pre">SQlite3</span></code> database (to change this you need to edit your <code class="docutils literal notranslate"><span class="pre">settings.py</span></code> file),
the database is actually just a normal file in <code class="docutils literal notranslate"><span class="pre">mygame/server/</span></code> called <code class="docutils literal notranslate"><span class="pre">evennia.db3</span></code>. <em>Simply delete
that file</em> - thats it. Now run <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">migrate</span></code> to recreate a new, fresh one.</p>
<p>If you run some other database system you can instead flush the database:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia flush
</pre></div>
</div>
<p>This will empty the database. However, it will not reset the internal counters of the database, so
you will start with higher dbref values. If this is okay, this is all you need.</p>
<p>Django also offers an easy way to start the databases own management should we want more direct
control:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> evennia dbshell
</pre></div>
</div>
<p>In e.g. MySQL you can then do something like this (assuming your MySQL database is named “Evennia”:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>mysql&gt; DROP DATABASE Evennia;
mysql&gt; exit
</pre></div>
</div>
<blockquote>
<div><p>NOTE: Under Windows OS, in order to access SQLite dbshell you need to <a class="reference external" href="https://www.sqlite.org/download.html">download the SQLite
command-line shell program</a>. Its a single executable file
(sqlite3.exe) that you should place in the root of either your MUD folder or Evennias (its the
same, in both cases Django will find it).</p>
</div></blockquote>
</section>
<section id="more-about-schema-migrations">
<h2>More about schema migrations<a class="headerlink" href="#more-about-schema-migrations" title="Permalink to this headline"></a></h2>
<p>If and when an Evennia update modifies the database <em>schema</em> (that is, the under-the-hood details as
to how data is stored in the database), you must update your existing database correspondingly to
match the change. If you dont, the updated Evennia will complain that it cannot read the database
properly. Whereas schema changes should become more and more rare as Evennia matures, it may still
happen from time to time.</p>
<p>One way one could handle this is to apply the changes manually to your database using the databases
command line. This often means adding/removing new tables or fields as well as possibly convert
existing data to match what the new Evennia version expects. It should be quite obvious that this
quickly becomes cumbersome and error-prone. If your database doesnt contain anything critical yet
its probably easiest to simply reset it and start over rather than to bother converting.</p>
<p>Enter <em>migrations</em>. Migrations keeps track of changes in the database schema and applies them
automatically for you. Basically, whenever the schema changes we distribute small files called
“migrations” with the source. Those tell the system exactly how to implement the change so you dont
have to do so manually. When a migration has been added we will tell you so on Evennias mailing
lists and in commit messages -
you then just run <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">migrate</span></code> to be up-to-date again.</p>
</section>
</section>
</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="right" >
<a href="Coding-Introduction.html" title="Coding Introduction"
>next</a> |</li>
<li class="right" >
<a href="Version-Control.html" title="Version Control"
>previous</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="Coding-Overview.html" >Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Updating Your Game</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>

View file

@ -0,0 +1,616 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>Version Control &#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" />
<link rel="next" title="Updating Your Game" href="Updating-Your-Game.html" />
<link rel="prev" title="Coding and development help" href="Coding-Overview.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="right" >
<a href="Updating-Your-Game.html" title="Updating Your Game"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="Coding-Overview.html" title="Coding and development help"
accesskey="P">previous</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="Coding-Overview.html" accesskey="U">Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Version Control</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="document">
<div class="documentwrapper">
<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><a href="../index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Version Control</a><ul>
<li><a class="reference internal" href="#setting-up-git">Setting up Git</a><ul>
<li><a class="reference internal" href="#step-1-install-git">Step 1: Install Git</a></li>
<li><a class="reference internal" href="#step-2-define-user-e-mail-settings-for-git">Step 2: Define user/e-mail Settings for Git</a></li>
</ul>
</li>
<li><a class="reference internal" href="#putting-your-game-folder-under-version-control">Putting your game folder under version control</a><ul>
<li><a class="reference internal" href="#tracking-files">Tracking files</a></li>
<li><a class="reference internal" href="#committing-your-code">Committing your Code</a></li>
<li><a class="reference internal" href="#changing-your-mind">Changing your mind</a></li>
<li><a class="reference internal" href="#pushing-your-code-online">Pushing your code online</a></li>
</ul>
</li>
<li><a class="reference internal" href="#forking-evennia">Forking Evennia</a><ul>
<li><a class="reference internal" href="#step-1-fork-the-evennia-master-repository">Step 1: Fork the evennia/master repository</a></li>
<li><a class="reference internal" href="#step-2-clone-your-online-fork-of-evennia">Step 2: Clone your online fork of Evennia</a></li>
<li><a class="reference internal" href="#step-3-configure-remotes">Step 3: Configure remotes</a></li>
</ul>
</li>
<li><a class="reference internal" href="#working-with-your-evennia-fork">Working with your Evennia fork</a><ul>
<li><a class="reference internal" href="#updating-to-latest-evennia">Updating to latest Evennia</a></li>
<li><a class="reference internal" href="#making-changes">Making changes</a></li>
</ul>
</li>
<li><a class="reference internal" href="#sharing-your-evennia-fixes-on-github">Sharing your Evennia fixes on Github</a><ul>
<li><a class="reference internal" href="#troubleshooting">Troubleshooting</a></li>
</ul>
</li>
<li><a class="reference internal" href="#making-an-evennia-pull-request">Making an Evennia Pull Request</a></li>
<li><a class="reference internal" href="#git-tips-and-tricks">GIT tips and tricks</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="Coding-Overview.html"
title="previous chapter">Coding and development help</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="Updating-Your-Game.html"
title="next chapter">Updating Your Game</a></p>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../_sources/Coding/Version-Control.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com">Home page</a> </li>
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
<h3>Versions</h3>
<ul>
<li><a href="Version-Control.html">1.0-dev (develop branch)</a></li>
<li><a href="../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
</ul>
</div>
</div>
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="version-control">
<h1>Version Control<a class="headerlink" href="#version-control" title="Permalink to this headline"></a></h1>
<p>Version control software allows you to track the changes you make to your code, as well as being
able to easily backtrack these changes, share your development efforts and more.</p>
<p>Its strongly recommended that you put your game code under version control. Version
control is also the way to contribue to Evennia itself.</p>
<p>For an introduction to the concept, start with the Wikipedia article
<a class="reference external" href="https://en.wikipedia.org/wiki/Version_control">here</a>. Evennia uses the version
control system <a class="reference external" href="https://git-scm.com/">Git</a> and this is what will be covered
henceforth. Note that this page primarily shows commands for Linux, but the
syntax should be the same for Windows and Mac.</p>
<p>For more help on using Git, please refer to the <a class="reference external" href="https://help.github.com/articles/set-up-git#platform-all">Official GitHub
documentation</a>.</p>
<section id="setting-up-git">
<h2>Setting up Git<a class="headerlink" href="#setting-up-git" title="Permalink to this headline"></a></h2>
<p>You can find expanded instructions for
installation <a class="reference external" href="https://git-scm.com/book/en/Getting-Started-Installing-Git">here</a>.</p>
<section id="step-1-install-git">
<h3>Step 1: Install Git<a class="headerlink" href="#step-1-install-git" title="Permalink to this headline"></a></h3>
<ul>
<li><p><strong>Fedora Linux</strong></p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> yum install git-core
</pre></div>
</div>
</li>
<li><p><strong>Debian Linux</strong> <em>(Ubuntu, Linux Mint, etc.)</em></p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> apt-get install git
</pre></div>
</div>
</li>
<li><p><strong>Windows</strong>: It is recommended to use <a class="reference external" href="https://gitforwindows.org/">Git for Windows</a>.</p></li>
<li><p><strong>Mac</strong>: Mac platforms offer two methods for installation, one via MacPorts, which you can find
out about <a class="reference external" href="https://git-scm.com/book/en/Getting-Started-Installing-Git#Installing-on-Mac">here</a>, or
you can use the <a class="reference external" href="https://sourceforge.net/projects/git-osx-installer/">Git OSX Installer</a>.</p></li>
</ul>
</section>
<section id="step-2-define-user-e-mail-settings-for-git">
<h3>Step 2: Define user/e-mail Settings for Git<a class="headerlink" href="#step-2-define-user-e-mail-settings-for-git" title="Permalink to this headline"></a></h3>
<p>To avoid a common issue later, you will need to set a couple of settings; first you will need to
tell Git your username, followed by your e-mail address, so that when you commit code later you will
be properly credited.</p>
<blockquote>
<div><p>Note that your commit information will be visible to everyone if you ever contribute to Evennia or
use an online service like github to host your code. So if you are not comfortable with using your
real, full name online, put a nickname here.</p>
</div></blockquote>
<ol>
<li><p>Set the default name for git to use when you commit:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> git config --global user.name &quot;Your Name Here&quot;
</pre></div>
</div>
</li>
<li><p>Set the default email for git to use when you commit:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> git config --global user.email &quot;your_email@example.com&quot;
</pre></div>
</div>
</li>
</ol>
</section>
</section>
<section id="putting-your-game-folder-under-version-control">
<h2>Putting your game folder under version control<a class="headerlink" href="#putting-your-game-folder-under-version-control" title="Permalink to this headline"></a></h2>
<blockquote>
<div><p>Note: The game folders version control is completely separate from Evennias repository.</p>
</div></blockquote>
<p>After you have set up your game you will have created a new folder to host your particular game
(lets call this folder <code class="docutils literal notranslate"><span class="pre">mygame</span></code> for now).</p>
<p>This folder is <em>not</em> under version control at this point.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git init mygame
</pre></div>
</div>
<p>Your mygame folder is now ready for version control! Add all the content and make a first
commit:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>cd mygame
git add *
git commit -a -m &quot;Initial commit&quot;
</pre></div>
</div>
<p>In turn these commands:</p>
<ul class="simple">
<li><p>Move us into the <code class="docutils literal notranslate"><span class="pre">mygame</span></code> folder</p></li>
<li><p>Tell <code class="docutils literal notranslate"><span class="pre">git</span></code> that everything <code class="docutils literal notranslate"><span class="pre">*</span></code> means everything) in this folder should be put
under version control.</p></li>
<li><p><em>Commit</em> all (<code class="docutils literal notranslate"><span class="pre">-a</span></code>) those newly added files to git and add a message <code class="docutils literal notranslate"><span class="pre">-m</span></code> so you remember
what you did at this point. Doing a commit is like saving a snapshot of the
current state of everything.</p></li>
</ul>
<p>Read on for details!</p>
<section id="tracking-files">
<h3>Tracking files<a class="headerlink" href="#tracking-files" title="Permalink to this headline"></a></h3>
<p>When working on your code or fix bugs in your local branches you may end up creating new files. If
you do you must tell Git to track them by using the add command.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git add &lt;filename&gt;
</pre></div>
</div>
<p>You only need to do this once per file.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git status
</pre></div>
</div>
<p>will show if you have any modified, added or otherwise changed files. Some
files, like database files, logs and temporary PID files are usually <em>not</em>
tracked in version control. These should either not show up or have a question
mark in front of them.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>You will notice that some files are not covered by your git version control,
notably your settings file (<code class="docutils literal notranslate"><span class="pre">mygame/server/conf/settings.py</span></code>) and your sqlite3
database file <code class="docutils literal notranslate"><span class="pre">mygame/server/evennia.db3</span></code>. What is auto-ignored by is controlled
by the hidden file <code class="docutils literal notranslate"><span class="pre">mygame/.gitignore</span></code>. Evennia creates this file as part of
the creation of your game directory. Everything matched in this file will be
ignored by git. If you want to, for example, include your settings file for
collaborators to access, remove that entry in <code class="docutils literal notranslate"><span class="pre">.gitignore</span></code>.</p>
</div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>You should <em>never</em> put your sqlite3 database file into git by removing its entry
in <code class="docutils literal notranslate"><span class="pre">.gitignore</span></code>. GIT is for backing up your code, not your database. That way
lies madness and a good chance youll confuse yourself so that after a few
commits and reverts dont know what is in your database or not. If you want to
backup your database, do so by simply copying the file on your hard drive to a
backup-name.</p>
</div>
</section>
<section id="committing-your-code">
<h3>Committing your Code<a class="headerlink" href="#committing-your-code" title="Permalink to this headline"></a></h3>
<p><em>Committing</em> your code means storing the current snapshot of your code within
git. This creates a “save point” or “history” of your development process. You
can later jump back and forth in your history, for example to figure out just
when a bug was introduced or see what results the code used to produce compared
to now. Or just wiping everything since the last commit, if you did something
stupid.</p>
<p>Its usually a good idea to commit your changes often. Committing is fast and
local only - you will never commit anything online at this point. To commit your
changes, use</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git commit --all
</pre></div>
</div>
<p>Also <code class="docutils literal notranslate"><span class="pre">-a</span></code> works. This will open a text editor for you to describe your change.
Be brief but informative in your message - youll appreciate it later. When you
save and close the editor, the commit will be saved. You can create the message
directly with</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git commit -a -m &quot;This fixes a bug in the combat code.&quot;
</pre></div>
</div>
</section>
<section id="changing-your-mind">
<h3>Changing your mind<a class="headerlink" href="#changing-your-mind" title="Permalink to this headline"></a></h3>
<p>If you have non-committed changes that you realize you want to throw away, you
check out the file you want - this will re-load it from the last committed
state:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git checkout &lt;file_to_revert&gt;
git checkout foo/bar/dummy.py
</pre></div>
</div>
<p>If you want to revert <em>all</em> changes you did since last commit, do</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git checkout .
</pre></div>
</div>
<p>(that is, add a single <code class="docutils literal notranslate"><span class="pre">.</span></code> at the end).</p>
</section>
<section id="pushing-your-code-online">
<h3>Pushing your code online<a class="headerlink" href="#pushing-your-code-online" title="Permalink to this headline"></a></h3>
<p>So far your code is only located on your private machine. A good idea is to back
it up online. The easiest way to do this is to push it to your own remote
repository on GitHub.</p>
<div class="admonition important">
<p class="admonition-title">Important</p>
<p>Just to avoid confusion, be aware that Githubs documentation has changed to
calling the primary branch main rather than master. While Evennia still
uses master branch (and this is what we refer to below), you can use either
name for your personal primary branch - they are equivalent.</p>
</div>
<ol class="simple">
<li><p>Make sure you have your game directory setup under git version control as
described in the previous section. Make sure to commit any changes you did.</p></li>
<li><p>Create a new, empty repository on Github. Github explains how
<a class="reference external" href="https://help.github.com/articles/create-a-repo/">here</a> (do <em>not</em> “Initialize
the repository with a README” or else youll create unrelated histories).</p></li>
<li><p>From your local game dir, do <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">remote</span> <span class="pre">add</span> <span class="pre">origin</span> <span class="pre">&lt;github</span> <span class="pre">URL&gt;</span></code> where
<code class="docutils literal notranslate"><span class="pre">&lt;github</span> <span class="pre">URL&gt;</span></code> is the URL to your online repo. This tells your game dir that
it should be pushing to the remote online dir.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">remote</span> <span class="pre">-v</span></code> to verify the online dir.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">push</span> <span class="pre">origin</span> <span class="pre">master</span></code> (or <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">push</span> <span class="pre">origin</span> <span class="pre">main</span></code>) now pushes your game dir
online so you can see it on <a class="reference external" href="http://github.com">github.com</a>.</p></li>
</ol>
<p>You can commit your work locally (<code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">commit</span> <span class="pre">--all</span> <span class="pre">-m</span> <span class="pre">&quot;Make</span> <span class="pre">a</span> <span class="pre">change</span> <span class="pre">that</span> <span class="pre">...&quot;</span></code>) as many times as you want. When you want to push those changes to your
online repo, you do <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">push</span></code>. You can also <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">clone</span> <span class="pre">&lt;url_to_online_repo&gt;</span></code>
from your online repo to somewhere else (like your production server) and
henceforth do <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">pull</span></code> to update that to the latest thing you pushed.</p>
<p>Note that GitHubs repos are, by default publicly visible by all. Creating a
publicly visible online clone might not be what you want for all parts of your
development process - you may prefer a more private venue when sharing your
revolutionary work with your team. If thats the case you can change your
repository to “Private” in the github settings. Then your code will only be
visible to those you specifically grant access.</p>
</section>
</section>
<section id="forking-evennia">
<h2>Forking Evennia<a class="headerlink" href="#forking-evennia" title="Permalink to this headline"></a></h2>
<p>This helps you set up an online <em>fork</em> of the main Evennia repository so you can
easily commit fixes and help with upstream development. You can do this step
also if you <em>didnt</em> put your game dir under version control like in the
previous section - the evennia repo and your game dir repo are completely
separate.</p>
<section id="step-1-fork-the-evennia-master-repository">
<h3>Step 1: Fork the evennia/master repository<a class="headerlink" href="#step-1-fork-the-evennia-master-repository" title="Permalink to this headline"></a></h3>
<blockquote>
<div><p>Before proceeding with the following step, make sure you have registered and
created an account on <a class="reference external" href="https://github.com/">GitHub.com</a>. This is necessary in order to create a fork
of Evennias master repository, and to push your commits to your fork either for
yourself or for contributing to
Evennia.</p>
</div></blockquote>
<p>A <em>fork</em> is a clone of the master repository that you can make your own commits
and changes to. At the top of <a class="reference external" href="https://github.com/evennia/evennia">this page</a>,
click the “Fork” button, as it appears below.
<img alt="" src="https://github-images.s3.amazonaws.com/help/bootcamp/Bootcamp-Fork.png" /></p>
</section>
<section id="step-2-clone-your-online-fork-of-evennia">
<h3>Step 2: Clone your online fork of Evennia<a class="headerlink" href="#step-2-clone-your-online-fork-of-evennia" title="Permalink to this headline"></a></h3>
<p>The fork only exists online as of yet. In a terminal, change your directory to
the folder you wish to develop in. From this directory run the following
command:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git clone https://github.com/yourusername/evennia.git
</pre></div>
</div>
<p>This will download your fork to your computer. It creates a new folder
<code class="docutils literal notranslate"><span class="pre">evennia/</span></code> at your current location.</p>
</section>
<section id="step-3-configure-remotes">
<h3>Step 3: Configure remotes<a class="headerlink" href="#step-3-configure-remotes" title="Permalink to this headline"></a></h3>
<p>Your Evennia-fork is now separate from upstream, official Evennia. You will
want to set it up so that you can easily sync our updates and changes to your
fork.</p>
<p>We do this by setting up a new <em>remote</em>. We actually already have one remote,
that is our own github form of Evennia. This got created when you cloned the
repo and defaults to being called <code class="docutils literal notranslate"><span class="pre">origin</span></code>.</p>
<p>We will now create a new remote called <code class="docutils literal notranslate"><span class="pre">upstream</span></code>.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>cd evennia
git remote add upstream https://github.com/evennia/evennia.git
</pre></div>
</div>
<p>This adds a remote to the main evennia repo.</p>
<p>If you also want to access Evennias <code class="docutils literal notranslate"><span class="pre">develop</span></code> branch (the bleeding edge
development) do the following:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git fetch upstream develop
git checkout develop
</pre></div>
</div>
<p>Use
git checkout master
git checkout develop</p>
<p>to switch between the branches. If you want to contribute a fix, ask first which
branch to use. Normally <code class="docutils literal notranslate"><span class="pre">master</span></code> is for bug fixes and <code class="docutils literal notranslate"><span class="pre">develop</span></code> is for new
features, but late in the development of a new Evennia version, all changes
often go into <code class="docutils literal notranslate"><span class="pre">develop</span></code>.</p>
</section>
</section>
<section id="working-with-your-evennia-fork">
<h2>Working with your Evennia fork<a class="headerlink" href="#working-with-your-evennia-fork" title="Permalink to this headline"></a></h2>
<p><em>Branches</em> are stand-alone editions of the same code. You make a commit to a
branch. Switching to a branch will change the code on-disk. You can easily
make a new branch off a parent branch, and then merge it back into the same
branch later (or throw it away). This is a very common way to work on new
features in safety and isolation.</p>
<section id="updating-to-latest-evennia">
<h3>Updating to latest Evennia<a class="headerlink" href="#updating-to-latest-evennia" title="Permalink to this headline"></a></h3>
<p>When Evennias official repository updates, first make sure to commit all your
changes to your branch and then checkout the “clean” master branch:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git checkout master
git pull upstream master
</pre></div>
</div>
<p>Or, if you are working against Evennias development branch:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git checkout develop
git pull upstream develop
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">pull</span></code> command will fetch all the changes from the “upstream” remote and
merge it into your local master/develop branch. It should now be a perfect copy
of the latest Evennia changes.</p>
</section>
<section id="making-changes">
<h3>Making changes<a class="headerlink" href="#making-changes" title="Permalink to this headline"></a></h3>
<p>As a rule of thumb you should <em>never</em> work directly in Evennias <code class="docutils literal notranslate"><span class="pre">master</span></code> or
<code class="docutils literal notranslate"><span class="pre">develop</span></code> branches. Instead you make a <em>new</em> branch off the branch you want
and change <em>that</em>.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git checkout master (or develop)
check checkout -b strange_bug
</pre></div>
</div>
<p>You now have a new branch <code class="docutils literal notranslate"><span class="pre">strange_bug</span></code> that is an exact replica of the branch you
had checked out when you created it. Here you can now make your own
modifications.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git branches
</pre></div>
</div>
<p>will show you which branches are available and which one you are currently
using. Use <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">checkout</span> <span class="pre">&lt;branch&gt;</span></code> to move between them, but remember to commit
your changes before you do.</p>
<p>You often want to make sure also your work-branch has the latest upstream
changes. To do this, you need to first update your copy of the
<code class="docutils literal notranslate"><span class="pre">master</span></code>/<code class="docutils literal notranslate"><span class="pre">develop</span></code> branch and then <em>merge</em> those changes into your work branch.
Make sure you have committed everything first!</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git commit -a -m &quot;My latest changes ...&quot; # on your strange_bug branch
git checkout master (or develop)
git pull upstream develop
git checkout strange_bug
git merge master (or develop)
</pre></div>
</div>
<p>If everything went well, your <code class="docutils literal notranslate"><span class="pre">strange_bug</span></code> branch will now have the latest version
of Evennia merged with whatever changes you have done.</p>
<p>Now work away on your code and commit with reasonable commit messages</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git commit -a -m &quot;Fixed the issue in ...&quot;
git commit -a -m &quot;Adding unit tests. This resolves #123.&quot;
</pre></div>
</div>
<p>Use</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git diff
</pre></div>
</div>
<p>to see what you changed since last commit, and</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git log
</pre></div>
</div>
<p>to see past commits (including those made by Evennia upstream, remember that
your branch is a copy of the upstream one, including its history!)</p>
</section>
</section>
<section id="sharing-your-evennia-fixes-on-github">
<h2>Sharing your Evennia fixes on Github<a class="headerlink" href="#sharing-your-evennia-fixes-on-github" title="Permalink to this headline"></a></h2>
<p>Up to this point your <code class="docutils literal notranslate"><span class="pre">strange_bug</span></code> branch only exists on your local computer. No
one else can see it. If you want a copy of this branch to also appear in your
online fork on GitHub, make sure to have checked out your “myfixes” branch and
then run the following:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git push -u origin strange_bug
</pre></div>
</div>
<p>You only need to do this once, the <code class="docutils literal notranslate"><span class="pre">-u</span></code> makes this the default push-location. In
the future, you can just push things online like this:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git push
</pre></div>
</div>
<section id="troubleshooting">
<h3>Troubleshooting<a class="headerlink" href="#troubleshooting" title="Permalink to this headline"></a></h3>
<p>If you hadnt setup a public key on GitHub or arent asked for a
username/password, you might get an error <code class="docutils literal notranslate"><span class="pre">403:</span> <span class="pre">Forbidden</span> <span class="pre">Access</span></code> at this stage.
In that case, some users have reported that the workaround is to create a file
<code class="docutils literal notranslate"><span class="pre">.netrc</span></code> under your home directory and add your github credentials there:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>machine github.com
login &lt;my_github_username&gt;
password &lt;my_github_password&gt;
</pre></div>
</div>
</section>
</section>
<section id="making-an-evennia-pull-request">
<h2>Making an Evennia Pull Request<a class="headerlink" href="#making-an-evennia-pull-request" title="Permalink to this headline"></a></h2>
<p>If you think that the fixes you did in your <code class="docutils literal notranslate"><span class="pre">strange_bug</span></code> branch should be a
part of the regular Evennia, you should create a <em>Pull Request</em> (PR). This is a
call for the Evennia maintainer to pull your change into an upstream branch.</p>
<blockquote>
<div><p>It is wise to make separate branches for every fix or series of fixes you want
to contribute.</p>
</div></blockquote>
<p>Assuming you have followed the instructions above and have pushed your changes
online, <a class="reference external" href="https://github.com/evennia/evennia/pulls">create a pull request</a> and
follow the instructions. Make sure to specifically select your <code class="docutils literal notranslate"><span class="pre">strange_bug</span></code>
branch to be the source of the merge and use the branch you based that branch
off (<code class="docutils literal notranslate"><span class="pre">master</span></code> or <code class="docutils literal notranslate"><span class="pre">develop</span></code>) as the target.</p>
<p>Evennia developers will then be able to examine your request and merge it if
its deemed suitable. They may also come back with feedback and request you do
some changes.</p>
<p>Once approved and merged, your change will now be available in the upstream
branch:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git checkout master (or develope)
git pull upstream master (or develop)
</pre></div>
</div>
<p>Since your changes are now in upstream, your local <code class="docutils literal notranslate"><span class="pre">strange_bug</span></code> branch is now
superfluous and should be deleted:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>git branch -D strange_bug
</pre></div>
</div>
<p>You can also safely delete your online <code class="docutils literal notranslate"><span class="pre">strange_bug</span></code> branch in your fork
(you can do this from the PR page on github).</p>
</section>
<section id="git-tips-and-tricks">
<h2>GIT tips and tricks<a class="headerlink" href="#git-tips-and-tricks" title="Permalink to this headline"></a></h2>
<p>Some of the GIT commands can feel a little long and clunky if you need to do them often. Luckily you
can create aliases for those. Here are some useful commands to run:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># git st</span>
<span class="c1"># - view brief status info</span>
<span class="n">git</span> <span class="n">config</span> <span class="o">--</span><span class="k">global</span> <span class="n">alias</span><span class="o">.</span><span class="n">st</span> <span class="s1">&#39;status -s&#39;</span>
</pre></div>
</div>
<p>Above, you only need to ever enter the <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">config</span> <span class="pre">...</span></code> command once - you have then added the new
alias. Afterwards, just do <code class="docutils literal notranslate"><span class="pre">git</span> <span class="pre">st</span></code> to get status info. All the examples below follow the same
template.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># git cl</span>
<span class="c1"># - clone a repository</span>
<span class="n">git</span> <span class="n">config</span> <span class="o">--</span><span class="k">global</span> <span class="n">alias</span><span class="o">.</span><span class="n">cl</span> <span class="n">clone</span>
</pre></div>
</div>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># git cma &quot;commit message&quot;</span>
<span class="c1"># - commit all changes without opening editor for message</span>
<span class="n">git</span> <span class="n">config</span> <span class="o">--</span><span class="k">global</span> <span class="n">alias</span><span class="o">.</span><span class="n">cma</span> <span class="s1">&#39;commit -a -m&#39;</span>
</pre></div>
</div>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># git ca</span>
<span class="c1"># - amend text to your latest commit message</span>
<span class="n">git</span> <span class="n">config</span> <span class="o">--</span><span class="k">global</span> <span class="n">alias</span><span class="o">.</span><span class="n">ca</span> <span class="s1">&#39;commit --amend&#39;</span>
</pre></div>
</div>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># git fl</span>
<span class="c1"># - file log; shows diffs of files in latest commits</span>
<span class="n">git</span> <span class="n">config</span> <span class="o">--</span><span class="k">global</span> <span class="n">alias</span><span class="o">.</span><span class="n">fl</span> <span class="s1">&#39;log -u&#39;</span>
</pre></div>
</div>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># git co [branchname]</span>
<span class="c1"># - checkout</span>
<span class="n">git</span> <span class="n">config</span> <span class="o">--</span><span class="k">global</span> <span class="n">alias</span><span class="o">.</span><span class="n">co</span> <span class="n">checkout</span>
</pre></div>
</div>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># git br &lt;branchname&gt;</span>
<span class="c1"># - create branch</span>
<span class="n">git</span> <span class="n">config</span> <span class="o">--</span><span class="k">global</span> <span class="n">alias</span><span class="o">.</span><span class="n">br</span> <span class="n">branch</span>
</pre></div>
</div>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># git ls</span>
<span class="c1"># - view log tree</span>
<span class="n">git</span> <span class="n">config</span> <span class="o">--</span><span class="k">global</span> <span class="n">alias</span><span class="o">.</span><span class="n">ls</span> <span class="s1">&#39;log --pretty=format:&quot;%C(green)%h\ %C(yellow)[</span><span class="si">%a</span><span class="s1">d]%Cred</span><span class="si">%d</span><span class="se">\</span>
<span class="s1">%Creset</span><span class="si">%s</span><span class="s1">%Cblue\ [</span><span class="si">%c</span><span class="s1">n]&quot; --decorate --date=relative --graph&#39;</span>
</pre></div>
</div>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># git diff</span>
<span class="c1"># - show current uncommitted changes</span>
<span class="n">git</span> <span class="n">config</span> <span class="o">--</span><span class="k">global</span> <span class="n">alias</span><span class="o">.</span><span class="n">diff</span> <span class="s1">&#39;diff --word-diff&#39;</span>
</pre></div>
</div>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># git grep &lt;query&gt;</span>
<span class="c1"># - search (grep) codebase for a search criterion</span>
<span class="n">git</span> <span class="n">config</span> <span class="o">--</span><span class="k">global</span> <span class="n">alias</span><span class="o">.</span><span class="n">grep</span> <span class="s1">&#39;grep -Ii&#39;</span>
</pre></div>
</div>
<p>To get a further feel for GIT there is also <a class="reference external" href="https://www.youtube.com/watch?v=1ffBJ4sVUb4#t=1m58s">a good YouTube talk about it</a> - its a bit long but it will help you understand the underlying ideas behind GIT
(which in turn makes it a lot more intuitive to use).</p>
</section>
</section>
</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="right" >
<a href="Updating-Your-Game.html" title="Updating Your Game"
>next</a> |</li>
<li class="right" >
<a href="Coding-Overview.html" title="Coding and development help"
>previous</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="Coding-Overview.html" >Coding and development help</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Version Control</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>