<h1>Attributes<aclass="headerlink"href="#attributes"title="Permalink to this headline">¶</a></h1>
<p>When performing actions in Evennia it is often important that you store data for later. If you write
a menu system, you have to keep track of the current location in the menu tree so that the player
can give correct subsequent commands. If you are writing a combat system, you might have a
combattant’s next roll get easier dependent on if their opponent failed. Your characters will
probably need to store roleplaying-attributes like strength and agility. And so on.</p>
<p><aclass="reference internal"href="Typeclasses.html"><spanclass="doc">Typeclassed</span></a> game entities (<aclass="reference internal"href="Accounts.html"><spanclass="doc">Accounts</span></a>, <aclass="reference internal"href="Objects.html"><spanclass="doc">Objects</span></a>,
<aclass="reference internal"href="Scripts.html"><spanclass="doc">Scripts</span></a> and <aclass="reference internal"href="Communications.html"><spanclass="doc">Channels</span></a>) always have <em>Attributes</em> associated with them.
Attributes are used to store any type of data ‘on’ such entities. This is different from storing
data in properties already defined on entities (such as <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">location</span></code>) - these have very
specific names and require very specific types of data (for example you couldn’t assign a python
<em>list</em> to the <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> property no matter how hard you tried). <codeclass="docutils literal notranslate"><spanclass="pre">Attributes</span></code> come into play when you
want to assign arbitrary data to arbitrary names.</p>
<h2>The .db and .ndb shortcuts<aclass="headerlink"href="#the-db-and-ndb-shortcuts"title="Permalink to this headline">¶</a></h2>
<p>To save persistent data on a Typeclassed object you normally use the <codeclass="docutils literal notranslate"><spanclass="pre">db</span></code> (DataBase) operator. Let’s
try to save some data to a <em>Rose</em> (an <aclass="reference internal"href="Objects.html"><spanclass="doc">Object</span></a>):</p>
<p>This looks like any normal Python assignment, but that <codeclass="docutils literal notranslate"><spanclass="pre">db</span></code> makes sure that an <em>Attribute</em> is
created behind the scenes and is stored in the database. Your rose will continue to have thorns
throughout the life of the server now, until you deliberately remove them.</p>
<p>To be sure to save <strong>non-persistently</strong>, i.e. to make sure NOT to create a database entry, you use
<codeclass="docutils literal notranslate"><spanclass="pre">ndb</span></code> (NonDataBase). It works in the same way:</p>
<p>Technically, <codeclass="docutils literal notranslate"><spanclass="pre">ndb</span></code> has nothing to do with <codeclass="docutils literal notranslate"><spanclass="pre">Attributes</span></code>, despite how similar they look. No
<codeclass="docutils literal notranslate"><spanclass="pre">Attribute</span></code> object is created behind the scenes when using <codeclass="docutils literal notranslate"><spanclass="pre">ndb</span></code>. In fact the database is not
invoked at all since we are not interested in persistence. There is however an important reason to
use <codeclass="docutils literal notranslate"><spanclass="pre">ndb</span></code> to store data rather than to just store variables direct on entities - <codeclass="docutils literal notranslate"><spanclass="pre">ndb</span></code>-stored data
is tracked by the server and will not be purged in various cache-cleanup operations Evennia may do
while it runs. Data stored on <codeclass="docutils literal notranslate"><spanclass="pre">ndb</span></code> (as well as <codeclass="docutils literal notranslate"><spanclass="pre">db</span></code>) will also be easily listed by example the
<p>You can also <codeclass="docutils literal notranslate"><spanclass="pre">del</span></code> properties on <codeclass="docutils literal notranslate"><spanclass="pre">db</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">ndb</span></code> as normal. This will for example delete an
<p>Both <codeclass="docutils literal notranslate"><spanclass="pre">db</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">ndb</span></code> defaults to offering an <codeclass="docutils literal notranslate"><spanclass="pre">all</span></code> property on themselves. This returns all
associated attributes or non-persistent properties.</p>
<p>If you use <codeclass="docutils literal notranslate"><spanclass="pre">all</span></code> as the name of an attribute, this will be used instead. Later deleting your custom
<codeclass="docutils literal notranslate"><spanclass="pre">all</span></code> will return the default behaviour.</p>
</div>
<divclass="section"id="the-attributehandler">
<h2>The AttributeHandler<aclass="headerlink"href="#the-attributehandler"title="Permalink to this headline">¶</a></h2>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">.db</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">.ndb</span></code> properties are very convenient but if you don’t know the name of the Attribute
beforehand they cannot be used. Behind the scenes <codeclass="docutils literal notranslate"><spanclass="pre">.db</span></code> actually accesses the <codeclass="docutils literal notranslate"><spanclass="pre">AttributeHandler</span></code>
which sits on typeclassed entities as the <codeclass="docutils literal notranslate"><spanclass="pre">.attributes</span></code> property. <codeclass="docutils literal notranslate"><spanclass="pre">.ndb</span></code> does the same for the
<p>The handlers have normal access methods that allow you to manage and retrieve <codeclass="docutils literal notranslate"><spanclass="pre">Attributes</span></code> and
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">has('attrname')</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>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">get(...)</span></code> - this retrieves the given Attribute. Normally the <codeclass="docutils literal notranslate"><spanclass="pre">value</span></code> property of the Attribute is
returned, but the method takes keywords for returning the Attribute object itself. 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.</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">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(...)</span></code> - returns all Attributes (of the given category) attached to this object.</p></li>
<p>See <aclass="reference external"href="Components/Attributes.html#locking-and-checking-attributes">this section</a> for more about locking down Attribute
<spanclass="k">print</span><spanclass="p">(</span><spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">test</span><spanclass="p">)</span><spanclass="c1"># prints "testvalue"</span>
<spanclass="k">print</span><spanclass="p">(</span><spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">attributes</span><spanclass="o">.</span><spanclass="n">all</span><spanclass="p">())</span><spanclass="c1"># prints [<AttributeObject>]</span>
<h2>Properties of Attributes<aclass="headerlink"href="#properties-of-attributes"title="Permalink to this headline">¶</a></h2>
<p>An Attribute object is stored in the database. It has the following properties:</p>
<ulclass="simple">
<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 -
<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">Nicks</span></a> is an example of using
in this way). To modify this property you need to use the <aclass="reference external"href="Components/Attributes.html#The_Attribute_Handler">Attribute
<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">Nicks</span></a> use it). It is only
<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">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 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>
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">Script</span></a> that
<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>
<blockquote>
<div><p>None of the following affects NAttributes, which does not invoke the database at all. There are no
restrictions to what can be stored in a NAttribute.</p>
</div></blockquote>
<p>The database doesn’t know anything about Python objects, so Evennia must <em>serialize</em> Attribute
values into a string representation in order to store it to the database. This is done using the
<codeclass="docutils literal notranslate"><spanclass="pre">pickle</span></code> module of Python (the only exception is if you use the <codeclass="docutils literal notranslate"><spanclass="pre">strattr</span></code> keyword of the
AttributeHandler to save to the <codeclass="docutils literal notranslate"><spanclass="pre">strvalue</span></code> field of the Attribute. In that case you can only save
<em>strings</em> which will not be pickled).</p>
<p>It’s important to note that when you access the data in an Attribute you are <em>always</em> de-serializing
it from the database representation every time. This is because we allow for storing
database-entities in Attributes too. If we cached it as its Python form, we might end up with
situations where the database entity was deleted since we last accessed the Attribute.
De-serializing data with a database-entity in it means querying the database for that object and
making sure it still exists (otherwise it will be set to <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>). Performance-wise this is usually
not a big deal. But if you are accessing the Attribute as part of some big loop or doing a large
amount of reads/writes you should first extract it to a temporary variable, operate on <em>that</em> and
then save the result back to the Attribute. If you are storing a more complex structure like a
<codeclass="docutils literal notranslate"><spanclass="pre">dict</span></code> or a <codeclass="docutils literal notranslate"><spanclass="pre">list</span></code> you should make sure to “disconnect” it from the database before looping over it,
<spanclass="n">obj</span><spanclass="o">.</span><spanclass="n">db</span><spanclass="o">.</span><spanclass="n">invalid</span><spanclass="o">=</span><spanclass="n">invalid</span><spanclass="c1"># will cause error!</span>
</pre></div>
</td></tr></table></div>
</div>
<divclass="section"id="storing-multiple-objects">
<h3>Storing multiple objects<aclass="headerlink"href="#storing-multiple-objects"title="Permalink to this headline">¶</a></h3>
<p>This means storing objects in a collection of some kind and are examples of <em>iterables</em>, pickle-able
entities you can loop over in a for-loop. Attribute-saving supports the following iterables:</p>
<ulclass="simple">
<li><p><aclass="reference external"href="https://docs.python.org/2/library/functions.html#tuple">Tuples</a>, like <codeclass="docutils literal notranslate"><spanclass="pre">(1,2,"test",</span><spanclass="pre"><dbobj>)</span></code>.</p></li>
<li><p><aclass="reference external"href="https://docs.python.org/2/tutorial/datastructures.html#more-on-lists">Lists</a>, like <codeclass="docutils literal notranslate"><spanclass="pre">[1,2,"test",</span><spanclass="pre"><dbobj>]</span></code>.</p></li>
<li><p><aclass="reference external"href="https://docs.python.org/2/tutorial/datastructures.html#dictionaries">Dicts</a>, like <codeclass="docutils literal notranslate"><spanclass="pre">{1:2,</span><spanclass="pre">"test":<dbobj>]</span></code>.</p></li>
<li><p><aclass="reference external"href="https://docs.python.org/2/tutorial/datastructures.html#sets">Sets</a>, like <codeclass="docutils literal notranslate"><spanclass="pre">{1,2,"test",<dbobj>}</span></code>.</p></li>
like <codeclass="docutils literal notranslate"><spanclass="pre">OrderedDict((1,2),</span><spanclass="pre">("test",</span><spanclass="pre"><dbobj>))</span></code>.</p>
<ulclass="simple">
<li><p><aclass="reference external"href="https://docs.python.org/2/library/collections.html#collections.deque">collections.Deque</a>, like
<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 external"href="Components/Attributes.html#Storing-Single-Objects">Single object</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="k">print</span><spanclass="p">(</span><spanclass="n">mylist</span><spanclass="p">)</span><spanclass="c1"># this is now [1,2,3,5]</span>
<spanclass="k">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>
</pre></div>
</td></tr></table></div>
<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="k">print</span><spanclass="p">(</span><spanclass="n">mylist</span><spanclass="p">)</span><spanclass="c1"># this is now [1,2,3,5]</span>
<spanclass="k">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>
</pre></div>
</td></tr></table></div>
<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.
<aclass="reference external"href="http://en.wikipedia.org/wiki/Immutable">Immutable</a> objects (strings, numbers, tuples etc) are
already disconnected from the database from the onset.</p>
<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="k">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>
</pre></div>
</td></tr></table></div>
<blockquote>
<div><p>Attributes will fetch data fresh from the database whenever you read them, so
if you are performing big operations on a mutable Attribute property (such as looping over a list
or dict) you should make sure to “disconnect” the Attribute’s value first and operate on this
rather than on the Attribute. You can gain dramatic speed improvements to big loops this
<p>First you need to set a <em>lock string</em> on your Attribute. Lock strings are specified <aclass="reference internal"href="Locks.html"><spanclass="doc">Locks</span></a>.
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">attrread</span></code> - limits who may read the value of the Attribute</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">attredit</span></code> - limits who may set/change this Attribute</p></li>
</ul>
<p>You cannot use the <codeclass="docutils literal notranslate"><spanclass="pre">db</span></code> handler to modify Attribute object (such as setting a lock on them) - The
<codeclass="docutils literal notranslate"><spanclass="pre">db</span></code> handler will return the Attribute’s <em>value</em>, not the Attribute object itself. Instead you use
the AttributeHandler and set it to return the object instead of the value:</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.
You have to add a check to your commands/code wherever it fits (such as before setting an
<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>
</td></tr></table></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>