The DjangoMOO Runtime
DjangoMOO verb code runs inside a RestrictedPython sandbox with a
constrained runtime environment. This page documents the global names
available to a verb, the context object, and the execution-environment
limits the sandbox enforces. For the conceptual model and full set of
sandbox guards, see Verb Sandbox Security Reference.
Names available in every verb
Six names are injected into the verb’s local scope by the compiler.
Linters will flag them as undefined — add a
# pylint: disable=undefined-variable at the top of every verb file.
Name |
Type |
Description |
|---|---|---|
|
|
The object the verb was matched on. With |
|
callable |
Calls the same verb on the next ancestor up the parent chain (the MOO |
|
|
The System Object ( |
|
|
Positional arguments when the verb is invoked as a method. Empty when invoked from the command parser. |
|
|
Keyword arguments when invoked as a method. Empty from the parser. |
|
|
The exact alias the caller used to invoke the verb. Never assign to a local named |
The context object
from moo.sdk import context exposes a module-level proxy whose
attributes track the state of the currently executing session. The
proxy is implemented over contextvars.ContextVar, so each Celery
task gets its own isolated copy.
When a player sends a command, the task runner opens a
ContextManager scope:
with code.ContextManager(caller, output.append, task_id=task_id) as ctx:
parse.interpret(ctx, line)
parse.interpret then attaches a Parser instance, making the full
session state available to whatever verb dispatches.
Attributes
- _Context.player = None
The Object that originated the command. Stays anchored to the session initiator across nested verb calls. Use this for “who is acting” logic.
- _Context.caller = None
The Object whose verb code is currently executing. Shifts as verbs invoke other verbs. Permission checks evaluate against this, not
player.
- _Context.parser = None
The
Parserfor the current command.Nonewhen a Celery task re-invokes a verb without an active player command (e.g. scheduledinvoke()calls).
- _Context.writer = None
Callable that
print()ends up calling. Sends a single string to the originating player’s connection.
- _Context.task_id = None
The Celery task ID for the current execution.
- _Context.task_time = None
TaskTime(elapsed, time_limit, remaining)namedtuple in seconds.Nonewhen no time limit is configured. Used for time-aware continuation.
- _Context.caller_stack = []
Stack of caller frames accumulated as verbs invoke sub-verbs. The returned list is a copy; mutating it does not affect the live stack.
context.player and context.caller are the same object at the start
of a command. They diverge as verbs invoke other verbs: caller shifts
to the new executor, while player stays the original session
initiator. See How Permissions Work in Verbs for why this matters.
Execution environment
Verb code is compiled by RestrictedPython and executed inside a controlled globals dict. Practical effects on what verb code can do:
The
print()builtin routes throughcontext.writerand ends up on the initiator’s connection. Output is buffered for the duration of the verb task; consecutiveprint(..., end="")calls are coalesced into one writer invocation so a verb can stream a phrase with multiple calls without producing fragmented lines on the client.Attribute names beginning with
_raiseAttributeError(the global_reference to the System Object is the single allowed exception).Augmented assignment to a subscript (
d["k"] += 1) is rejected — use a plain variable instead. Augmented assignment on locals (x += 1) works.Only the builtins in
settings.ALLOWED_BUILTINSare available (all,any,dict,enumerate,getattr,hasattr,list,max,min,set,sorted,sum,PermissionError).Only the modules in
settings.ALLOWED_MODULESmay be imported (moo.sdk,hashlib,re,datetime,time). Wizard-owned verbs additionally getmoo.core.models.{object,verb,property}.returnmay appear at any depth in the verb body, not just at function end.Each verb invocation finishes within
settings.CELERY_TASK_TIME_LIMIT(default 3 seconds) or the worker terminates the task. Synchronous calls to other verbs share that budget.
For the full sandbox model — including model-layer permission checks,
QuerySet method whitelists, and the str.format block — see
Verb Sandbox Security Reference.
Looking up objects
There is no LambdaMOO-style #N literal syntax in Python. To
obtain an object reference inside verb code, use lookup():
- moo.sdk.lookup(x, return_first=True)
Lookup an object within the current site by PK, name, or alias.
PK lookups are site-scoped: an integer PK that belongs to a different universe raises
NoSuchObjectErrorthe same as a missing object would. Internal system code that genuinely needs cross-site access should useObject.global_objectsdirectly rather than going through this function.- Parameters:
x (
Union[int,str]) – lookup valuereturn_first (
bool) – when True (default), return the first match or raise NoSuchObjectError; when False, return a list of all matches (may be empty)
- Returns:
the result of the lookup, or a list when return_first is False
- Return type:
- Raises:
NoSuchObjectError – when a result cannot be found and return_first is True
lookup() accepts an object PK, an exact name, or any of an
object’s aliases. It raises NoSuchObjectError if nothing matches —
that exception is a UserError and propagates cleanly to the player
when uncaught (see Creating MOO Verbs).