On this page

Own the room's working objects๏ƒ

Prerequisite: Rift setup. The workstation is the room's local binding canvas. It holds objects, attributes, and methods you give it; it is not another Spellbook or an implicit resolver.

The saved example binds the name subject in both the object and method stores. The store= argument distinguishes them. It selects a method as the active target, calls it, clears the target without deleting the binding, and releases the object.

Be explicit about retention๏ƒ

weak_ref=True requests weak storage. The lesson proves a non-weak-referenceable value is refused rather than silently stored strongly. A strong binding retains the object for the binding's lifetime; a weak binding does not give it that lifetime.

Keep room storage and world access separate. Retrieve permitted world objects through the room's command/view surfaces, then place the objects you need on the canvas. Expert rooms continue into operation and codegen.

The workflow in code๏ƒ

These are the core steps from the saved example. Use its complete linked script for all class definitions and setup.

 1def main() -> None:
 2    nexus = md.Nexus()
 3    system_config = nexus.create_configuration()
 4    system_config.with_rift_creation_enabled(True)
 5    nexus.activate(system_config)
 6
 7    rift_config = nexus.create_rift_configuration()
 8    rift_config.with_space_type("capability")
 9    rift = nexus.create_rift(configuration=rift_config, rift_name="bench")
10    rift.mark_active()
11
12    workstation = rift.space.workstation
13    assert isinstance(workstation, md.Workstation)
14    assert workstation.owner_space_id == rift.space.space_id
15    print("workstation:", workstation.workstation_id)
16    print("owned by room:", workstation.owner_space_id == rift.space.space_id)
17
18    # THREE STORES. The same name in two stores is not a collision.
19    greeter = Greeter()
20    workstation.bind_object("subject", greeter)
21    workstation.bind_method("subject", greeter.greet)
22    print("bound 'subject' into two different stores")
23
24    from_objects = workstation.get("subject", store="objects")
25    from_methods = workstation.get("subject", store="methods")
26    assert from_objects is greeter
27    assert from_methods() == "hello from the canvas"
28    print("objects['subject'] is the instance; methods['subject'] is callable")
29
30    # THE READ DOOR. Ask the canvas what is on it.
31    summary = workstation.describe_bindings()
32    print("describe_bindings keys:", sorted(summary))
33    for store in ("objects", "attributes", "methods", "target_name"):
34        assert store in summary, store
35    assert "subject" in summary["objects"]
36    assert "subject" in summary["methods"]
37
38    # Five keys, and the docstring now says five. `target_store` names the
39    # store the active target came from - enough to round-trip it back
40    # through get(name, store=...).
41    assert set(summary) == {"objects", "attributes", "methods",
42                            "target_name", "target_store"}
43    print("keys:", len(summary), "- documented and returned agree")
44
45    # ONE TARGET AT A TIME.
46    workstation.set_target("subject", store="methods")
47    assert workstation.get_target() is not None
48    print("target set from the methods store")
49
50    result = workstation.call_target()
51    assert result == "hello from the canvas"
52    print("call_target ->", result)
53
54    workstation.clear_target()
55    # Clearing deselects; it does not delete the binding underneath.
56    assert workstation.get("subject", store="methods") is not None
57    print("target cleared; the binding it pointed at is still there")
58
59    # WEAK BY REQUEST. A class instance can be weak-referenced.
60    workstation.bind_object("weak_subject", Greeter(), weak_ref=True)
61    print("weak binding accepted for a weak-referenceable object")
62
63    # ...and an int cannot. This RAISES rather than quietly storing it
64    # strongly, which is the whole point.
65    try:
66        workstation.bind_object("weak_number", 42, weak_ref=True)
67        raise AssertionError(
68            "expected a refusal - int cannot be weak-referenced"
69        )
70    except (TypeError, ValueError, RuntimeError) as error:
71        print("explicit weak binding refused:", type(error).__name__)
72
73    # No silent degrade means: it is not on the canvas at all.
74    after = workstation.describe_bindings()
75    assert "weak_number" not in after["objects"]
76    print("refused binding was NOT stored strongly as a fallback")
77
78    # release() takes it back off the canvas and hands it to you.
79    released = workstation.release("subject", store="objects")
80    assert released is greeter
81    assert "subject" not in workstation.describe_bindings()["objects"]
82    print("released 'subject' from objects; methods copy untouched:",
83          "subject" in workstation.describe_bindings()["methods"])
84
85    print()
86    print("the canvas holds; the command system resolves. separate jobs.")
87    print("weak when asked, never by accident - refuse instead of degrade")

Runnable examples๏ƒ

All advanced examples ยท Level contents ยท Full contents

Canonical page source