<divclass="code-block-caption"><spanclass="caption-text">In-code, using the .db wrapper</span><aclass="headerlink"href="#id2"title="Permalink to this code">¶</a></div>
<divclass="code-block-caption"><spanclass="caption-text">In-code, using the .attributes handler</span><aclass="headerlink"href="#id3"title="Permalink to this code">¶</a></div>
<divclass="code-block-caption"><spanclass="caption-text">In-code, using <codeclass="docutils literal notranslate"><spanclass="pre">AttributeProperty</span></code> at class level</span><aclass="headerlink"href="#id4"title="Permalink to this code">¶</a></div>
<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
<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 to avoid being surprised, also for experienced developers. Attributes can store <em>almost</em> everything
<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>) can (and usually do) have Attributes associated with them. There
<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. This allows for setting and getting Attributes that lack a <em>category</em> (having category <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>)</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 want to group your Attribute in a category, or don’t know the name of the Attribute beforehand, you can make use of
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</span></a>, available as <codeclass="docutils literal notranslate"><spanclass="pre">.attributes</span></code> on all typeclassed entities. 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>
<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> and can thus also be found via <codeclass="docutils literal notranslate"><spanclass="pre">.db</span></code>. <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> is considered a category of its own, so you won’t find <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>-category Attributes mixed with Attributes having categories.</p>
<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>
<p>The third way to set up an Attribute is to use 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 database Fields. Unlike using <codeclass="docutils literal notranslate"><spanclass="pre">.db</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">.attributes</span></code>, an <codeclass="docutils literal notranslate"><spanclass="pre">AttributeProperty</span></code> can’t be created on the fly, you must assign it in the class code.</p>
<p>When a new instance of the class is created, new <codeclass="docutils literal notranslate"><spanclass="pre">Attributes</span></code> will be created with the value and category given.</p>
<p>With <codeclass="docutils literal notranslate"><spanclass="pre">AttributeProperty</span></code>’s set up like this, one can access the underlying <codeclass="docutils literal notranslate"><spanclass="pre">Attribute</span></code> like a regular property on the created object:</p>
<spanclass="n">char</span><spanclass="o">.</span><spanclass="n">agility</span><spanclass="o">=</span><spanclass="mi">15</span><spanclass="c1"># assign a new value (category remains 'stat')</span>
<spanclass="n">char</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">sleepy</span><spanclass="c1"># returns None because autocreate=False (see below)</span>
<p>Be careful to not assign AttributeProperty’s to names of properties and methods already existing on the class, like ‘key’ or ‘at_object_creation’. That could lead to very confusing errors.</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">autocreate=False</span></code> (default is <codeclass="docutils literal notranslate"><spanclass="pre">True</span></code>) used for <codeclass="docutils literal notranslate"><spanclass="pre">sleepy</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">poisoned</span></code> is worth a closer explanation. When <codeclass="docutils literal notranslate"><spanclass="pre">False</span></code>, <em>no</em> Attribute will be auto-created for these AttributProperties unless they are <em>explicitly</em> set.
The advantage of not creating an Attribute is that the default value given to <codeclass="docutils literal notranslate"><spanclass="pre">AttributeProperty</span></code> is returned with no database access unless you change it. This also means that if you want to change the default later, all entities previously create will inherit the new default.
The drawback is that without a database precense you can’t find the Attribute via <codeclass="docutils literal notranslate"><spanclass="pre">.db</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">.attributes.get</span></code> (or by querying for it in other ways in the database):</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="n">char</span><spanclass="o">.</span><spanclass="n">sleepy</span><spanclass="c1"># returns False, no db access</span>
<spanclass="n">char</span><spanclass="o">.</span><spanclass="n">sleepy</span><spanclass="o">=</span><spanclass="kc">True</span><spanclass="c1"># now an Attribute is created</span>
<spanclass="n">char</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">sleepy</span><spanclass="c1"># now returns True!</span>
<spanclass="n">char</span><spanclass="o">.</span><spanclass="n">attributes</span><spanclass="o">.</span><spanclass="n">get</span><spanclass="p">(</span><spanclass="s2">"sleepy"</span><spanclass="p">)</span><spanclass="c1"># now returns True</span>
<spanclass="n">char</span><spanclass="o">.</span><spanclass="n">sleepy</span><spanclass="c1"># now returns True, involves db access</span>
<p>You can e.g. <codeclass="docutils literal notranslate"><spanclass="pre">del</span><spanclass="pre">char.strength</span></code> to set the value back to the default (the value defined
in the <codeclass="docutils literal notranslate"><spanclass="pre">AttributeProperty</span></code>).</p>
<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 API</span></a> for more details on how to create it with special options, like giving access-restrictions.</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="#id5"title="Permalink to this code">¶</a></div>
<divclass="code-block-caption"><spanclass="caption-text">Invalid, ‘hidden’ dbobject</span><aclass="headerlink"href="#id6"title="Permalink to this code">¶</a></div>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># example of storing an invalid, "hidden" dbobject in Attribute</span>
<spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">mydata</span><spanclass="o">=</span><spanclass="n">container</span><spanclass="c1"># will raise error!</span>
</pre></div>
</div>
</div>
<p>By adding two methods <codeclass="docutils literal notranslate"><spanclass="pre">__serialize_dbobjs__</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">__deserialize_dbobjs__</span></code> to the
object you want to save, you can pre-serialize and post-deserialize all ‘hidden’
objects before Evennia’s main serializer gets to work. Inside these methods, use Evennia’s
<aclass="reference internal"href="../api/evennia.utils.dbserialize.html#evennia.utils.dbserialize.dbserialize"title="evennia.utils.dbserialize.dbserialize"><spanclass="xref myst py py-func">evennia.utils.dbserialize.dbserialize</span></a> and
<aclass="reference internal"href="../api/evennia.utils.dbserialize.html#evennia.utils.dbserialize.dbunserialize"title="evennia.utils.dbserialize.dbunserialize"><spanclass="xref myst py py-func">dbunserialize</span></a> functions to safely
<divclass="code-block-caption"><spanclass="caption-text">Fixing an invalid ‘hidden’ dbobj for storing in Attribute</span><aclass="headerlink"href="#id7"title="Permalink to this code">¶</a></div>
<spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">mydata</span><spanclass="o">=</span><spanclass="n">container</span><spanclass="c1"># will now work fine!</span>
<div><p>Note the extra check in <codeclass="docutils literal notranslate"><spanclass="pre">__deserialize_dbobjs__</span></code> to make sure the thing you
are deserializing is a <codeclass="docutils literal notranslate"><spanclass="pre">bytes</span></code> object. This is needed because the Attribute’s
cache reruns deserializations in some situations when the data was already
once deserialized. If you see errors in the log saying
<codeclass="docutils literal notranslate"><spanclass="pre">Could</span><spanclass="pre">not</span><spanclass="pre">unpickle</span><spanclass="pre">data</span><spanclass="pre">for</span><spanclass="pre">storage:</span><spanclass="pre">...</span></code>, the reason is
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"># now also [1, 2, 3, 5]</span>
<p>When you extract your mutable Attribute data into a variable like <codeclass="docutils literal notranslate"><spanclass="pre">mylist</span></code>, think of it as getting a <em>snapshot</em>
of the variable. If you update the snapshot, it will save to the database, but this change <em>will not propagate to
any other snapshots you may have done previously</em>.</p>
<spanclass="nb">print</span><spanclass="p">(</span><spanclass="n">mylist1</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"># also updated to [1, 2, 3, 5]</span>
<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>, <codeclass="docutils literal notranslate"><spanclass="pre">dict</span></code> instead of <codeclass="docutils literal notranslate"><spanclass="pre">_SaverDict</span></code> and so on). If you update it, you need to
explicitly save it back to the Attribute for it to save.</p>
<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>
<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>
<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