Properties on Objects
Properties are typed key-value rows attached to an Object. Children
inherit every property defined on their parents — owners follow the
child by default, or stay pinned to the parent if inherit_owner=True.
For function reference (signatures of set_property, get_property,
etc.) see SDK Functions. For the lookup architecture and caching
behaviour, see Caching.
Reading a property
The canonical pattern is try/except:
from moo.sdk import NoSuchPropertyError
try:
description = obj.get_property("description")
except NoSuchPropertyError:
description = "You see nothing special."
get_property() walks the inheritance chain and deserialises the
value. It honours the three-tier cache (per-session dict → Redis →
database with AncestorCache join), so repeat reads inside a single
command are free.
Don’t pair has_property() with get_property(). That makes two
queries for the same data. The try/except form does one.
obj.<name> via __getattr__ also resolves to a property if no verb
matches first, but the verb miss is one extra database hit. Use
get_property("name") when you know it’s a property.
To get the underlying Property ORM instance instead of the
deserialised value (e.g. to read its owner or permissions), pass
original=True:
prop = obj.get_property("description", original=True)
prop.owner # Player who owns this property row
prop.inherit_owner
Writing a property
obj.set_property("description", "A dark, cold room.")
set_property saves its own row — you do not need to call
obj.save() afterwards. To create a property where children should
keep the parent’s ownership rather than rebasing to each child’s
owner, pass inherit_owner=True:
obj.set_property("ps", "they", inherit_owner=True)
See “Inheritance” below for what that flag actually changes.
Permissions
Adding a new property to an object requires write permission on the
object. Updating an existing property requires write on the
property itself. Changing a property’s owner requires entrust.
Deleting a property requires write.
Like every model-layer permission check, these fire automatically in
Property.save() and Property.delete() — verb code does not need
to check first. If the caller lacks the permission, AccessError
propagates and the player sees a clean error message. See
How Permissions Work in Verbs.
The named permissions a property recognises:
Permission |
Effect |
|---|---|
|
Read the property value |
|
Modify the property value |
|
Change the owner of the property |
|
Set permissions on the property |
|
Wildcard — all of the above |
Property attributes
- Property.pk
The unique identifying number of this Property.
- Property.name
Name of the Property. Unique per
origin.
- Property.value
Serialised value of the Property.
Object.get_property()returns the deserialised Python value; read this field directly only when you need the raw moojson representation.
- Property.type
One of
string,python, ordynamic. Controls howvalueis decoded.
- Property.owner
The Object that owns this Property row. Changes require
entrustpermission.
- Property.origin
The Object the Property is defined on. Inheritance copies the Property to descendants when they’re created.
- Property.inherit_owner
If
True, descendants keep the parent’sownerwhen they inherit the Property. IfFalse(the default), each descendant’s row is owned by the descendant’s owner. See Properties on Objects for the LambdaMOOc-bit equivalent and when to use it.
Inheritance and inherit_owner
When a child object reads a property defined on a parent, the child gets its own row with the parent’s value copied in. By default, the child’s owner becomes the property’s owner on the child — so any verb running as the child’s owner can modify the property.
inherit_owner=True reverses that: the child’s row keeps the
parent’s owner. This matters when a parent verb (running as the
parent’s owner) needs to mutate the property on every descendant.
Without inherit_owner=True, the verb loses write access on every
descendant whose owner is a different player.
The classic example: a Generic Player defines pronoun properties
(ps, po, pp, …) that the gender_utils verb (owned by
Wizard) updates when a player runs @gender male. With
inherit_owner=True on those properties, every player’s pronoun
properties are still owned by Wizard, and the wizard verb can change
them. Without it, each player would own their own pronoun rows and
the wizard verb would hit AccessError.
# In a bootstrap script:
player_class.set_property("ps", "they", inherit_owner=True)
For the LambdaMOO origin of this design (the c permission bit), see
the LambdaMOO Programmer’s Manual.