- Documentation
- Locus
- Python Developer API
Python Developer API
On supported Engine versions, Locus exposes its shared request foundation
directly under unreal. Python uses these requests rather than the Blueprint
async-action proxies.
The entry point is unreal.LocusDeveloperRequestLibrary. Factory and property
names are snake case, such as create_document, on_succeeded,
operation_status, and request_id. Enum values use uppercase snake case,
such as LocusDeveloperRequestState.NOT_STARTED and
LocusDeveloperResultCode.STALE_REVISION.
Construct, retain, bind, start
Section titled “Construct, retain, bind, start”This order is part of the contract:
Construct → Retain references → Bind → Start → CompletionConstruction does not submit work. Retain the request, delegate wrappers, and
bound Python callables until terminal completion. Bind success and failure
before start() because admission failure can complete inline. Remove the
bindings and release those references after completion.
import unreal
input_value = unreal.LocusDeveloperDocumentCreateInput( path="DeveloperExamples/PythonGettingStarted.md", markdown="# Created from Unreal Python\n", presentation_root=unreal.LocusDeveloperDocumentRoot.LOCUS_DOCUMENTS,)request = unreal.LocusDeveloperRequestLibrary.create_document(input_value)
def on_succeeded(result): unreal.log(f"Created {result.identity.relative_path}") release_bindings()
def on_failed(error): unreal.log_error(f"Locus failed: {error.code.name}: {error.message}") release_bindings()
success_delegate = request.on_succeededfailure_delegate = request.on_failed
def release_bindings(): success_delegate.remove_callable(on_succeeded) failure_delegate.remove_callable(on_failed)
success_delegate.add_callable(on_succeeded)failure_delegate.add_callable(on_failed)
if not request.start(): unreal.log_error("The request had already been started")The example creates a real Document. Choose a project-appropriate path and handle an existing identity through the typed failure callback.
Inspect a completed request
Section titled “Inspect a completed request”A completed typed request retains:
stateandsucceeded;request_id;- typed
result; - typed
error; operation_status.
It also exposes has_started() and is_completed(). Tick-driven inspection is
valid. A busy polling loop is not: it blocks the Game Thread that must complete
the request.
cancel() requests cooperative cancellation. It can prevent queued work, but
cannot interrupt repository work or turn a committed mutation into a cancelled
result.
Partial updates
Section titled “Partial updates”Use the reflected set_* flags to express intent:
changes = unreal.LocusDeveloperNoteChanges()
changes.set_title = False # Leave unchanged; title is ignored.changes.title = "ignored"
changes.set_body = True # Set a non-empty value.changes.body = "Updated body"
changes.set_tags = True # Explicitly clear tags.changes.tags = []
request = unreal.LocusDeveloperRequestLibrary.update_note( note_identity, current_revision, changes,)There is no Python-specific None convention. Pin metadata changes use the
same explicit set_title, set_description, set_pin_type, and set_tags
properties.
Unattended Editor automation
Section titled “Unattended Editor automation”The supported model is an Unreal Editor process with PythonScriptPlugin enabled:
External automation ↓UnrealEditor-Cmd full Editor environment ↓PythonScriptPlugin ↓Locus reflected requestsThe supported unattended launch shape is shown below with UE 5.6; use the matching Editor executable for UE 5.7 or 5.8:
& "C:\Program Files\Epic Games\UE_5.6\Engine\Binaries\Win64\UnrealEditor-Cmd.exe" ` "C:\Path\To\Project.uproject" ` "-ExecutePythonScript=C:\Path\To\Script.py" ` -ScriptErrorsAreFatal -unattended -NullRHI -nosplashAn asynchronous unattended script should:
- call
unreal.EditorPythonScripting.set_keep_python_script_alive(True); - register
unreal.register_slate_post_tick_callback(...); - construct, retain, bind, and start its Locus request;
- allow normal Editor ticks to drive Locus’s existing executor;
- observe terminal completion and remove delegate bindings;
- unregister the tick callback;
- call
set_keep_python_script_alive(False)for clean exit.
Do not use sleep(), spin waiting, a synchronous future wait, or manual Game
Thread pumping.
Pipeline limits
Section titled “Pipeline limits”- Python requires an Unreal Editor process and PythonScriptPlugin.
- Locus itself does not depend on PythonScriptPlugin and still loads when it is disabled.
- Standalone
python.execannot import Locus. - Pins require a supported saved project-owned world.
- The
-run=PythonScriptcommandlet is not the complete supported environment; validation received a transient unsaved world rather than the saved world required for the complete API. - Use the full Editor application’s
-ExecutePythonScriptpath for unattended automation. - Startup or index reconciliation can produce retryable
Unavailable; resubmit on a later normal Editor tick rather than blocking.
See the Developer API overview for identities, revisions, errors, operation status, and the capability matrix.