<p><em>Attributes</em> allow you to to store arbitrary data on objects and make sure the data survives a
server reboot. An Attribute can store pretty much any
Python data structure and data type, like numbers, strings, lists, dicts etc. You can also
store (references to) database objects like characters and rooms.</p>
<ulclass="simple">
<li><p><aclass="reference internal"href="#what-types-of-data-can-i-save-in-an-attribute"><spanclass="std std-doc">What can be stored in an Attribute</span></a> is a must-read
also for experienced developers, to avoid getting surprised. Attributes can store <em>almost</em> everything
but you need to know the quirks.</p></li>
<li><p><aclass="reference internal"href="#in-memory-attributes-nattributes"><spanclass="std std-doc">NAttributes</span></a> are the in-memory, non-persistent
siblings of Attributes.</p></li>
<li><p><aclass="reference internal"href="#managing-attributes-in-game"><spanclass="std std-doc">Managing Attributes In-game</span></a> for in-game builder commands.</p></li>
</ul>
<sectionid="managing-attributes-in-code">
<h2>Managing Attributes in Code<aclass="headerlink"href="#managing-attributes-in-code"title="Permalink to this headline">¶</a></h2>
<p>Attributes are usually handled in code. All <aclass="reference internal"href="Typeclasses.html"><spanclass="doc std std-doc">Typeclassed</span></a> entities
<aclass="reference internal"href="Channels.html"><spanclass="doc std std-doc">Channels</span></a>) all can (and usually do) have Attributes associated with them. There
are three ways to manage Attributes, all of which can be mixed.</p>
<ulclass="simple">
<li><p><aclass="reference internal"href="#using-db"><spanclass="std std-doc">Using the <codeclass="docutils literal notranslate"><spanclass="pre">.db</span></code> property shortcut</span></a></p></li>
<li><p><aclass="reference internal"href="#using-attributeproperty"><spanclass="std std-doc">Using <codeclass="docutils literal notranslate"><spanclass="pre">AttributeProperty</span></code> for assigning Attributes in a way similar to Django fields</span></a></p></li>
</ul>
<sectionid="using-db">
<h3>Using .db<aclass="headerlink"href="#using-db"title="Permalink to this headline">¶</a></h3>
<p>The simplest way to get/set Attributes is to use the <codeclass="docutils literal notranslate"><spanclass="pre">.db</span></code> shortcut:</p>
<spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">self_reference</span><spanclass="o">=</span><spanclass="n">obj</span><spanclass="c1"># stores a reference to the obj</span>
<spanclass="c1"># (let's assume a rose exists in-game)</span>
<spanclass="n">rose</span><spanclass="o">=</span><spanclass="n">evennia</span><spanclass="o">.</span><spanclass="n">search_object</span><spanclass="p">(</span><spanclass="n">key</span><spanclass="o">=</span><spanclass="s2">"rose"</span><spanclass="p">)[</span><spanclass="mi">0</span><spanclass="p">]</span><spanclass="c1"># returns a list, grab 0th element</span>
<spanclass="n">myself</span><spanclass="o">=</span><spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">self_reference</span><spanclass="c1"># retrieve reference from db, get object back</span>
<p>Trying to access a non-existing Attribute will never lead to an <codeclass="docutils literal notranslate"><spanclass="pre">AttributeError</span></code>. Instead
you will get <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> back. The special <codeclass="docutils literal notranslate"><spanclass="pre">.db.all</span></code> will return a list of all Attributes on
the object. You can replace this with your own Attribute <codeclass="docutils literal notranslate"><spanclass="pre">all</span></code> if you want, it will replace the
default <codeclass="docutils literal notranslate"><spanclass="pre">all</span></code> functionality until you delete it again.</p>
</section>
<sectionid="using-attributes">
<h3>Using .attributes<aclass="headerlink"href="#using-attributes"title="Permalink to this headline">¶</a></h3>
<p>If you don’t know the name of the Attribute beforehand you can also use
the <codeclass="docutils literal notranslate"><spanclass="pre">AttributeHandler</span></code>, available as <codeclass="docutils literal notranslate"><spanclass="pre">.attributes</span></code>. With no extra keywords this is identical
to using the <codeclass="docutils literal notranslate"><spanclass="pre">.db</span></code> shortcut (<codeclass="docutils literal notranslate"><spanclass="pre">.db</span></code> is actually using the <codeclass="docutils literal notranslate"><spanclass="pre">AttributeHandler</span></code> internally):</p>
<spanclass="c1"># you can give space-separated Attribute-names (can't do that with .db)</span>
<spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">attributes</span><spanclass="o">.</span><spanclass="n">add</span><spanclass="p">(</span><spanclass="s2">"my game log"</span><spanclass="p">,</span><spanclass="s2">"long text about ..."</span><spanclass="p">)</span>
<p>With the <codeclass="docutils literal notranslate"><spanclass="pre">AttributeHandler</span></code> you can also give Attributes a <codeclass="docutils literal notranslate"><spanclass="pre">category</span></code>. By using a category you can
separate same-named Attributes on the same object which can help organization:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># store (let's say we have gold_necklace and ringmail_armor from before)</span>
<p>If you don’t specify a category, the Attribute’s <codeclass="docutils literal notranslate"><spanclass="pre">category</span></code> will be <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>. Note that
<codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> is also considered a category of its own, so you won’t find <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>-category Attributes mixed
with <codeclass="docutils literal notranslate"><spanclass="pre">Attributes</span></code> having categories.</p>
<blockquote>
<div><p>When using <codeclass="docutils literal notranslate"><spanclass="pre">.db</span></code>, you will always use the <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> category.</p>
</div></blockquote>
<p>Here are the methods of the <codeclass="docutils literal notranslate"><spanclass="pre">AttributeHandler</span></code>. See
the <aclass="reference internal"href="../api/evennia.typeclasses.attributes.html#evennia.typeclasses.attributes.AttributeHandler"title="evennia.typeclasses.attributes.AttributeHandler"><spanclass="xref myst py py-class">AttributeHandler API</span></a> for more details.</p>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">has(...)</span></code> - this checks if the object has an Attribute with this key. This is equivalent
to doing <codeclass="docutils literal notranslate"><spanclass="pre">obj.db.attrname</span></code> except you can also check for a specific `category.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">get(...)</span></code> - this retrieves the given Attribute. You can also provide a <codeclass="docutils literal notranslate"><spanclass="pre">default</span></code> value to return
if the Attribute is not defined (instead of None). By supplying an
<codeclass="docutils literal notranslate"><spanclass="pre">accessing_object</span></code> to the call one can also make sure to check permissions before modifying
anything. The <codeclass="docutils literal notranslate"><spanclass="pre">raise_exception</span></code> kwarg allows you to raise an <codeclass="docutils literal notranslate"><spanclass="pre">AttributeError</span></code> instead of returning
<codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> when you access a non-existing <codeclass="docutils literal notranslate"><spanclass="pre">Attribute</span></code>. The <codeclass="docutils literal notranslate"><spanclass="pre">strattr</span></code> kwarg tells the system to store
the Attribute as a raw string rather than to pickle it. While an optimization this should usually
not be used unless the Attribute is used for some particular, limited purpose.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">add(...)</span></code> - this adds a new Attribute to the object. An optional <aclass="reference internal"href="Locks.html"><spanclass="doc std std-doc">lockstring</span></a> can be
supplied here to restrict future access and also the call itself may be checked against locks.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">remove(...)</span></code> - Remove the given Attribute. This can optionally be made to check for permission
before performing the deletion. - <codeclass="docutils literal notranslate"><spanclass="pre">clear(...)</span></code> - removes all Attributes from object.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">all(category=None)</span></code> - returns all Attributes (of the given category) attached to this object.</p></li>
<h3>Using AttributeProperty<aclass="headerlink"href="#using-attributeproperty"title="Permalink to this headline">¶</a></h3>
<p>There is a third way to set up an Attribute, and that is by setting up an <codeclass="docutils literal notranslate"><spanclass="pre">AttributeProperty</span></code>. This
is done on the <em>class level</em> of your typeclass and allows you to treat Attributes a bit like Django
<p>These “Attribute-properties” will be made available to all instances of the class.</p>
<divclass="admonition important">
<pclass="admonition-title">Important</p>
<p>If you change the <codeclass="docutils literal notranslate"><spanclass="pre">default</span></code> of an <codeclass="docutils literal notranslate"><spanclass="pre">AttributeProperty</span></code> (and reload), it will
change the default for <em>all</em> instances of that class (it will not override
explicitly changed values).</p>
</div>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="n">char</span><spanclass="o">=</span><spanclass="n">evennia</span><spanclass="o">.</span><spanclass="n">search_object</span><spanclass="p">(</span><spanclass="n">Character</span><spanclass="p">,</span><spanclass="n">key</span><spanclass="o">=</span><spanclass="s2">"Bob"</span><spanclass="p">)[</span><spanclass="mi">0</span><spanclass="p">]</span><spanclass="c1"># returns list, get 0th element</span>
<spanclass="c1"># get defaults </span>
<spanclass="n">strength</span><spanclass="o">=</span><spanclass="n">char</span><spanclass="o">.</span><spanclass="n">strength</span><spanclass="c1"># will get the default value 10</span>
<spanclass="c1"># assign new values (this will create/update new Attributes)</span>
<spanclass="c1"># you can also do arithmetic etc </span>
<spanclass="n">char</span><spanclass="o">.</span><spanclass="n">magic</span><spanclass="o">+=</span><spanclass="mi">2</span><spanclass="c1"># char.magic is now 4</span>
<spanclass="c1"># check Attributes </span>
<spanclass="n">strength</span><spanclass="o">=</span><spanclass="n">char</span><spanclass="o">.</span><spanclass="n">strength</span><spanclass="c1"># this is now 12</span>
<spanclass="k">del</span><spanclass="n">char</span><spanclass="o">.</span><spanclass="n">strength</span><spanclass="c1"># wipes the Attribute</span>
<spanclass="n">strength</span><spanclass="o">=</span><spanclass="n">char</span><spanclass="o">.</span><spanclass="n">strengh</span><spanclass="c1"># back to the default (10) again</span>
</pre></div>
</div>
<p>See the <aclass="reference internal"href="../api/evennia.typeclasses.attributes.html#evennia.typeclasses.attributes.AttributeProperty"title="evennia.typeclasses.attributes.AttributeProperty"><spanclass="xref myst py py-class">AttributeProperty</span></a> docs for more
details on arguments.</p>
<p>An <codeclass="docutils literal notranslate"><spanclass="pre">AttributeProperty</span></code> will <em>not</em> create an <codeclass="docutils literal notranslate"><spanclass="pre">Attribute</span></code> by default. A new <codeclass="docutils literal notranslate"><spanclass="pre">Attribute</span></code> will be created
(or an existing one retrieved/updated) will happen differently depending on how the <codeclass="docutils literal notranslate"><spanclass="pre">autocreate</span></code>
<li><p>If <codeclass="docutils literal notranslate"><spanclass="pre">autocreate=False</span></code> (default), an <codeclass="docutils literal notranslate"><spanclass="pre">Attribute</span></code> will be created only if the field is explicitly
assigned a value (even if the value is the same as the default, such as <codeclass="docutils literal notranslate"><spanclass="pre">char.strength</span><spanclass="pre">=</span><spanclass="pre">10</span></code>).</p></li>
<li><p>If <codeclass="docutils literal notranslate"><spanclass="pre">autocreate=True</span></code>, an <codeclass="docutils literal notranslate"><spanclass="pre">Attribute</span></code> will be created as soon as the field is <em>accessed</em> in
any way (So both <codeclass="docutils literal notranslate"><spanclass="pre">strength</span><spanclass="pre">=</span><spanclass="pre">char.strength</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">char.strength</span><spanclass="pre">=</span><spanclass="pre">10</span></code> will both make sure that
an <codeclass="docutils literal notranslate"><spanclass="pre">Attribute</span></code> exists.</p></li>
<spanclass="n">valb</span><spanclass="o">=</span><spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">value_b</span><spanclass="c1"># return "bar" AND creates the Attribute (autocreate)</span>
<spanclass="c1"># the autocreate property will now be found </span>
<spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">value_a</span><spanclass="c1"># still not found </span>
<spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">value_b</span><spanclass="c1"># now returns "bar"</span>
<spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">value_a</span><spanclass="o">=</span><spanclass="mi">10</span><spanclass="c1"># will now create a new Attribute </span>
<spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">value_b</span><spanclass="o">=</span><spanclass="mi">12</span><spanclass="c1"># will update the existing Attribute </span>
<spanclass="c1"># both are now found as Attributes </span>
<spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">value_a</span><spanclass="c1"># now returns 10</span>
<spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">value_b</span><spanclass="c1"># now returns 12</span>
<p>If you always access your Attributes via the <codeclass="docutils literal notranslate"><spanclass="pre">AttributeProperty</span></code> this does not matter that much
(it’s also a bit of an optimization to not create an actual database <codeclass="docutils literal notranslate"><spanclass="pre">Attribute</span></code> unless the value changed).
But until an <codeclass="docutils literal notranslate"><spanclass="pre">Attribute</span></code> has been created, <codeclass="docutils literal notranslate"><spanclass="pre">AttributeProperty</span></code> fields will <em>not</em> show up with the
<codeclass="docutils literal notranslate"><spanclass="pre">examine</span></code> command or by using the <codeclass="docutils literal notranslate"><spanclass="pre">.db</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">.attributes</span></code> handlers - so this is a bit inconsistent.
If this is important, you need to ‘initialize’ them by accessing them at least once … something
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">strength</span><spanclass="c1"># by accessing it, the Attribute is auto-created</span>
<p>If you created your <codeclass="docutils literal notranslate"><spanclass="pre">AttributeProperty</span></code> with a <codeclass="docutils literal notranslate"><spanclass="pre">category</span></code>, you <em>must</em> specify the
category in <codeclass="docutils literal notranslate"><spanclass="pre">.attributes.get()</span></code> if you want to find it this way. Remember that
<codeclass="docutils literal notranslate"><spanclass="pre">.db</span></code> always uses a <codeclass="docutils literal notranslate"><spanclass="pre">category</span></code> of <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>.</p>
<p>The first <codeclass="docutils literal notranslate"><spanclass="pre">set</span></code>-example will store a new Attribute <codeclass="docutils literal notranslate"><spanclass="pre">foo</span></code> on the object <codeclass="docutils literal notranslate"><spanclass="pre">myobj</span></code> and give it the
value “bar”.
You can store numbers, booleans, strings, tuples, lists and dicts this way. But if
you store a list/tuple/dict they must be proper Python structures and may <em>only</em> contain strings
or numbers. If you try to insert an unsupported structure, the input will be converted to a
set myobj/mylist = ["foo", "bar", 2]
set myobj/mydict = {"a": 1, "b": 2, 3: 4}
set mypobj/mystring = [1, 2, foo] # foo is invalid Python (no quotes)
</pre></div>
</div>
<p>For the last line you’ll get a warning and the value instead will be saved as a string <codeclass="docutils literal notranslate"><spanclass="pre">"[1,</span><spanclass="pre">2,</span><spanclass="pre">foo]"</span></code>.</p>
</section>
<sectionid="locking-and-checking-attributes">
<h2>Locking and checking Attributes<aclass="headerlink"href="#locking-and-checking-attributes"title="Permalink to this headline">¶</a></h2>
<p>While the <codeclass="docutils literal notranslate"><spanclass="pre">set</span></code> command is limited to builders, individual Attributes are usually not
locked down. You may want to lock certain sensitive Attributes, in particular for games
where you allow player building. You can add such limitations by adding a <aclass="reference internal"href="Locks.html"><spanclass="doc std std-doc">lock string</span></a>
to your Attribute. A NAttribute have no locks.</p>
<p>You must use the <codeclass="docutils literal notranslate"><spanclass="pre">AttributeHandler</span></code> to assign the lockstring to the Attribute:</p>
<p>If you already have an Attribute and want to add a lock in-place you can do so
by having the <codeclass="docutils literal notranslate"><spanclass="pre">AttributeHandler</span></code> return the <codeclass="docutils literal notranslate"><spanclass="pre">Attribute</span></code> object itself (rather than
its value) and then assign the lock to it directly:</p>
<p>Note the <codeclass="docutils literal notranslate"><spanclass="pre">return_obj</span></code> keyword which makes sure to return the <codeclass="docutils literal notranslate"><spanclass="pre">Attribute</span></code> object so its LockHandler
could be accessed.</p>
<p>A lock is no good if nothing checks it – and by default Evennia does not check locks on Attributes.
To check the <codeclass="docutils literal notranslate"><spanclass="pre">lockstring</span></code> you provided, make sure you include <codeclass="docutils literal notranslate"><spanclass="pre">accessing_obj</span></code> and set
<codeclass="docutils literal notranslate"><spanclass="pre">default_access=False</span></code> as you make a <codeclass="docutils literal notranslate"><spanclass="pre">get</span></code> call.</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># in some command code where we want to limit</span>
<spanclass="c1"># setting of a given attribute name on an object</span>
<spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You cannot edit that Attribute!"</span><spanclass="p">)</span>
<spanclass="k">return</span>
<spanclass="c1"># edit the Attribute here</span>
</pre></div>
</div>
<p>The same keywords are available to use with <codeclass="docutils literal notranslate"><spanclass="pre">obj.attributes.set()</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">obj.attributes.remove()</span></code>,
those will check for the <codeclass="docutils literal notranslate"><spanclass="pre">attredit</span></code> lock type.</p>
<h2>What types of data can I save in an Attribute?<aclass="headerlink"href="#what-types-of-data-can-i-save-in-an-attribute"title="Permalink to this headline">¶</a></h2>
<div><p>The only exception is if you use the <codeclass="docutils literal notranslate"><spanclass="pre">strattr</span></code> keyword of the
<codeclass="docutils literal notranslate"><spanclass="pre">AttributeHandler</span></code> to save to the <codeclass="docutils literal notranslate"><spanclass="pre">strvalue</span></code> field of the Attribute. In that case you can <em>only</em> save
<em>strings</em> and those will not be pickled).</p>
<divclass="code-block-caption"><spanclass="caption-text">Valid assignments</span><aclass="headerlink"href="#id3"title="Permalink to this code">¶</a></div>
<divclass="code-block-caption"><spanclass="caption-text">Invalid, ‘hidden’ dbobject</span><aclass="headerlink"href="#id4"title="Permalink to this code">¶</a></div>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># example of an invalid, "hidden" dbobject</span>
<spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">invalid</span><spanclass="o">=</span><spanclass="n">container</span><spanclass="c1"># will cause error!</span>
like <codeclass="docutils literal notranslate"><spanclass="pre">OrderedDict((1,2),</span><spanclass="pre">("test",</span><spanclass="pre"><dbobj>))</span></code>.</p></li>
<li><p>All other iterables (i.e. entities with the <codeclass="docutils literal notranslate"><spanclass="pre">__iter__</span></code> method) will be converted to a <em>list</em>.
Since you can use any combination of the above iterables, this is generally not much of a
<p>Any entity listed in the <aclass="reference internal"href="#storing-single-objects"><spanclass="std std-doc">Single object</span></a> section above can be
<h3>Retrieving Mutable objects<aclass="headerlink"href="#retrieving-mutable-objects"title="Permalink to this headline">¶</a></h3>
<p>A side effect of the way Evennia stores Attributes is that <em>mutable</em> iterables (iterables that can
be modified in-place after they were created, which is everything except tuples) are handled by
custom objects called <codeclass="docutils literal notranslate"><spanclass="pre">_SaverList</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">_SaverDict</span></code> etc. These <codeclass="docutils literal notranslate"><spanclass="pre">_Saver...</span></code> classes behave just like the
normal variant except that they are aware of the database and saves to it whenever new data gets
assigned to them. This is what allows you to do things like <codeclass="docutils literal notranslate"><spanclass="pre">self.db.mylist[7]</span><spanclass="pre">=</span><spanclass="pre">val</span></code> and be sure
that the new version of list is saved. Without this you would have to load the list into a temporary
variable, change it and then re-assign it to the Attribute in order for it to save.</p>
<p>There is however an important thing to remember. If you retrieve your mutable iterable into another
variable, e.g. <codeclass="docutils literal notranslate"><spanclass="pre">mylist2</span><spanclass="pre">=</span><spanclass="pre">obj.db.mylist</span></code>, your new variable (<codeclass="docutils literal notranslate"><spanclass="pre">mylist2</span></code>) will <em>still</em> be a
<codeclass="docutils literal notranslate"><spanclass="pre">_SaverList</span></code>. This means it will continue to save itself to the database whenever it is updated!</p>
<spanclass="n">mylist</span><spanclass="p">[</span><spanclass="mi">3</span><spanclass="p">]</span><spanclass="o">=</span><spanclass="mi">5</span><spanclass="c1"># this will also update database</span>
<spanclass="nb">print</span><spanclass="p">(</span><spanclass="n">mylist</span><spanclass="p">)</span><spanclass="c1"># this is now [1,2,3,5]</span>
<spanclass="nb">print</span><spanclass="p">(</span><spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">mylist</span><spanclass="p">)</span><spanclass="c1"># this is also [1,2,3,5]</span>
<p>To “disconnect” your extracted mutable variable from the database you simply need to convert the
<codeclass="docutils literal notranslate"><spanclass="pre">_Saver...</span></code> iterable to a normal Python structure. So to convert a <codeclass="docutils literal notranslate"><spanclass="pre">_SaverList</span></code>, you use the
<codeclass="docutils literal notranslate"><spanclass="pre">list()</span></code> function, for a <codeclass="docutils literal notranslate"><spanclass="pre">_SaverDict</span></code> you use <codeclass="docutils literal notranslate"><spanclass="pre">dict()</span></code> and so on.</p>
<spanclass="n">mylist</span><spanclass="o">=</span><spanclass="nb">list</span><spanclass="p">(</span><spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">mylist</span><spanclass="p">)</span><spanclass="c1"># convert to normal list</span>
<spanclass="nb">print</span><spanclass="p">(</span><spanclass="n">mylist</span><spanclass="p">)</span><spanclass="c1"># this is now [1,2,3,5]</span>
<spanclass="nb">print</span><spanclass="p">(</span><spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">mylist</span><spanclass="p">)</span><spanclass="c1"># this is still [1,2,3,4]</span>
<p>A further problem comes with <em>nested mutables</em>, like a dict containing lists of dicts or something
like that. Each of these nested mutables would be <codeclass="docutils literal notranslate"><spanclass="pre">_Saver*</span></code> structures connected to the database and
disconnecting the outermost one of them would not disconnect those nested within. To make really
sure you disonnect a nested structure entirely from the database, Evennia provides a special
function <codeclass="docutils literal notranslate"><spanclass="pre">evennia.utils.dbserialize.deserialize</span></code>:</p>
<p>The result of this operation will be a structure only consisting of normal Python mutables (<codeclass="docutils literal notranslate"><spanclass="pre">list</span></code>
instead of <codeclass="docutils literal notranslate"><spanclass="pre">_SaverList</span></code> and so on).</p>
<p>Remember, this is only valid for <em>mutable</em> iterables.
<spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">mytup</span><spanclass="p">[</span><spanclass="mi">0</span><spanclass="p">]</span><spanclass="o">=</span><spanclass="mi">5</span><spanclass="c1"># this fails since tuples are immutable</span>
<spanclass="c1"># this works but will NOT update database since outermost is a tuple</span>
<spanclass="nb">print</span><spanclass="p">(</span><spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">mytup</span><spanclass="p">[</span><spanclass="mi">2</span><spanclass="p">][</span><spanclass="mi">1</span><spanclass="p">])</span><spanclass="c1"># this still returns 4, not 5</span>
<spanclass="n">mytup1</span><spanclass="o">=</span><spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">mytup</span><spanclass="c1"># mytup1 is already disconnected from database since outermost</span>
<spanclass="c1"># iterable is a tuple, so we can edit the internal list as we want</span>
<spanclass="c1"># without affecting the database.</span>
<h2>Properties of Attributes<aclass="headerlink"href="#properties-of-attributes"title="Permalink to this headline">¶</a></h2>
<p>An <codeclass="docutils literal notranslate"><spanclass="pre">Attribute</span></code> object is stored in the database. It has the following properties:</p>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> - the name of the Attribute. When doing e.g. <codeclass="docutils literal notranslate"><spanclass="pre">obj.db.attrname</span><spanclass="pre">=</span><spanclass="pre">value</span></code>, this property is set
to <codeclass="docutils literal notranslate"><spanclass="pre">attrname</span></code>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">value</span></code> - this is the value of the Attribute. This value can be anything which can be pickled -
objects, lists, numbers or what have you (see
<aclass="reference internal"href="#what-types-of-data-can-i-save-in-an-attribute"><spanclass="std std-doc">this section</span></a> for more info). In the
example
<codeclass="docutils literal notranslate"><spanclass="pre">obj.db.attrname</span><spanclass="pre">=</span><spanclass="pre">value</span></code>, the <codeclass="docutils literal notranslate"><spanclass="pre">value</span></code> is stored here.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">category</span></code> - this is an optional property that is set to None for most Attributes. Setting this
allows to use Attributes for different functionality. This is usually not needed unless you want
to use Attributes for very different functionality (<aclass="reference internal"href="Nicks.html"><spanclass="doc std std-doc">Nicks</span></a> is an example of using
Attributes in this way). To modify this property you need to use the <aclass="reference internal"href="#attributes"><spanclass="std std-doc">Attribute Handler</span></a></p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">strvalue</span></code> - this is a separate value field that only accepts strings. This severely limits the
data possible to store, but allows for easier database lookups. This property is usually not used
except when re-using Attributes for some other purpose (<aclass="reference internal"href="Nicks.html"><spanclass="doc std std-doc">Nicks</span></a> use it). It is only
accessible via the <aclass="reference internal"href="#attributes"><spanclass="std std-doc">Attribute Handler</span></a>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">attrtype</span></code> - this is used internally by Evennia to separate <aclass="reference internal"href="Nicks.html"><spanclass="doc std std-doc">Nicks</span></a>, from Attributes (Nicks
use Attributes behind the scenes).</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">model</span></code> - this is a <em>natural-key</em> describing the model this Attribute is attached to. This is on
the form <em>appname.modelclass</em>, like <codeclass="docutils literal notranslate"><spanclass="pre">objects.objectdb</span></code>. It is used by the Attribute and
NickHandler to quickly sort matches in the database. Neither this nor <codeclass="docutils literal notranslate"><spanclass="pre">attrtype</span></code> should normally
need to be modified.</p></li>
</ul>
<p>Non-database attributes are not stored in the database and have no equivalence
to <codeclass="docutils literal notranslate"><spanclass="pre">category</span></code> nor <codeclass="docutils literal notranslate"><spanclass="pre">strvalue</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">attrtype</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">model</span></code>.</p>
<h1>In-memory Attributes (NAttributes)<aclass="headerlink"href="#in-memory-attributes-nattributes"title="Permalink to this headline">¶</a></h1>
<p><em>NAttributes</em> (short of Non-database Attributes) mimic Attributes in most things except they
are <strong>non-persistent</strong> - they will <em>not</em> survive a server reload.</p>
<ulclass="simple">
<li><p>Instead of <codeclass="docutils literal notranslate"><spanclass="pre">.db</span></code> use <codeclass="docutils literal notranslate"><spanclass="pre">.ndb</span></code>.</p></li>
<li><p>Instead of <codeclass="docutils literal notranslate"><spanclass="pre">.attributes</span></code> use <codeclass="docutils literal notranslate"><spanclass="pre">.nattributes</span></code></p></li>
<li><p>Instead of <codeclass="docutils literal notranslate"><spanclass="pre">AttributeProperty</span></code>, use <codeclass="docutils literal notranslate"><spanclass="pre">NAttributeProperty</span></code>.</p></li>
<p>Differences between <codeclass="docutils literal notranslate"><spanclass="pre">Attributes</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">NAttributes</span></code>:</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">NAttribute</span></code>s are always wiped on a server reload.</p></li>
<li><p>They only exist in memory and never involve the database at all, making them faster to
access and edit than <codeclass="docutils literal notranslate"><spanclass="pre">Attribute</span></code>s.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">NAttribute</span></code>s can store <em>any</em> Python structure (and database object) without limit.</p></li>
<li><p>They can <em>not</em> be set with the standard <codeclass="docutils literal notranslate"><spanclass="pre">set</span></code> command (but they are visible with <codeclass="docutils literal notranslate"><spanclass="pre">examine</span></code>)</p></li>
</ul>
<p>There are some important reasons we recommend using <codeclass="docutils literal notranslate"><spanclass="pre">ndb</span></code> to store temporary data rather than
the simple alternative of just storing a variable directly on an object:</p>
<ulclass="simple">
<li><p>NAttributes are tracked by Evennia and will not be purged in various cache-cleanup operations
the server may do. So using them guarantees that they’ll remain available at least as long as
the server lives.</p></li>
<li><p>It’s a consistent style - <codeclass="docutils literal notranslate"><spanclass="pre">.db/.attributes</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">.ndb/.nattributes</span></code> makes for clean-looking code
where it’s clear how long-lived (or not) your data is to be.</p></li>
</ul>
<sectionid="persistent-vs-non-persistent">
<h2>Persistent vs non-persistent<aclass="headerlink"href="#persistent-vs-non-persistent"title="Permalink to this headline">¶</a></h2>
<p>So <em>persistent</em> data means that your data will survive a server reboot, whereas with
<em>non-persistent</em> data it will not …</p>
<p>… So why would you ever want to use non-persistent data? The answer is, you don’t have to. Most of
the time you really want to save as much as you possibly can. Non-persistent data is potentially
useful in a few situations though.</p>
<ulclass="simple">
<li><p>You are worried about database performance. Since Evennia caches Attributes very aggressively,
this is not an issue unless you are reading <em>and</em> writing to your Attribute very often (like many
times per second). Reading from an already cached Attribute is as fast as reading any Python
property. But even then this is not likely something to worry about: Apart from Evennia’s own
caching, modern database systems themselves also cache data very efficiently for speed. Our
default
database even runs completely in RAM if possible, alleviating much of the need to write to disk
during heavy loads.</p></li>
<li><p>A more valid reason for using non-persistent data is if you <em>want</em> to lose your state when logging
off. Maybe you are storing throw-away data that are re-initialized at server startup. Maybe you
are implementing some caching of your own. Or maybe you are testing a buggy <aclass="reference internal"href="Scripts.html"><spanclass="doc std std-doc">Script</span></a> that
does potentially harmful stuff to your character object. With non-persistent storage you can be
sure that whatever is messed up, it’s nothing a server reboot can’t clear up.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">NAttribute</span></code>s have no restrictions at all on what they can store, since they
don’t need to worry about being saved to the database - they work very well for temporary storage.</p></li>
<li><p>You want to implement a fully or partly <em>non-persistent world</em>. Who are we to argue with your