Core Concepts
The Cascade class
Cascade is the single entry point for all library interactions. Open a
session with it as a context manager:
from cascade_cms.wrapper import Cascade, EnvironmentVars
env: EnvironmentVars = {
"SERVER": "my-site",
"API_KEY": "your-api-key",
"CASCADE_URL": "https://your-cascade-instance.com",
}
with Cascade(env) as cascade:
# queue operations here
...
Previously known as CascadeWrapperBase; the alias still works but Cascade
is the current name.
Constructor
Cascade(
environmentVariables: EnvironmentVars,
debug: dict[str, Any] | None = None,
*,
exit_on_failure: bool = True,
log_dir: str | os.PathLike | None = None,
)
EnvironmentVars is a TypedDict with three required keys:
| Key | Description |
|---|---|
SERVER |
Label used in log output (not a network address) |
API_KEY |
Cascade REST API bearer token |
CASCADE_URL |
Base URL of your Cascade CMS instance |
exit_on_failure=True (default) ends the script non-zero on any failure.
Pass False for long-lived processes like the MCP server.
Operations
cascade.operations is the entry point for all CMS operations. It returns
an Operations builder that accepts the first call in a chain:
with Cascade(env) as cascade:
chain = cascade.operations.read("abc123")
Available operations mirror the Cascade REST API:
| Operation | Description |
|---|---|
.read(id) |
Read one asset |
.edit(payload) |
Edit an asset via callback or direct payload |
.publish(id) |
Publish an asset |
.delete(id) |
Delete an asset |
.copy(id, dest) |
Copy an asset |
.move(id, dest) |
Move an asset |
.checkIn(id) |
Check in an asset |
.checkOut(id) |
Check out an asset |
.search(query) |
Search assets |
.create(asset) |
Create a new asset |
See the API Reference for full signatures.
Operation chains
Each operation call returns an OperationChain, not a result. Nothing
executes until you call .submit_requests(). This design lets you compose
multi-step workflows before any network requests are made:
from cascade_cms.cmstypes import Asset
def set_searchable(asset: Asset) -> Asset:
asset.searchable = True
return asset
with Cascade(env) as cascade:
results = (
cascade.operations
.read("abc123")
.edit(set_searchable)
.publish("abc123")
.submit_requests(Asset)
)
The type argument to .submit_requests() is for the type checker. Asset
covers most cases; use a more specific type when the operation returns one.
edit() and callbacks
edit() accepts a callable, a single asset, or a list of assets. The
callable form is the most common in practice:
def update_keywords(asset: Asset) -> Asset:
asset.keywords = "updated"
return asset
cascade.operations.edit(update_keywords)
The callback receives the current asset and must return the modified asset.
The identifier is derived from the asset's own id/path/siteName fields
— there is no separate identifier argument on edit() in 3.9.1.
Batch execution and ChainGroup
Passing a list to operations that accept identifiers — read, delete,
publish, etc. — creates one independent OperationChain per identifier,
returned as a ChainGroup:
with Cascade(env) as cascade:
results = (
cascade.operations
.read(["id1", "id2", "id3"])
.submit_requests(Asset)
)
Failures in one chain do not cancel others. The returned ChainResults
covers all chains in the group.
Result handling
.submit_requests() returns ChainResults[T] — a list subclass with
.success and .failed properties. See Result Handling
for full details.
results = cascade.operations.read("abc123").submit_requests(Asset)
for asset in results.success:
print(asset.path)
for failure in results.failed:
print(f"[{failure.category}] {failure.message}")
Script logging
script_log.note() writes annotated log lines from within a script:
from cascade_cms.utils import script_log
with Cascade(env) as cascade:
script_log.note("Starting run")
results = cascade.operations.read("abc123").submit_requests(Asset)
script_log.note(f"Done — {len(results.success)} succeeded")
Calls outside the with block drop silently with a RuntimeWarning.
API keys are automatically redacted from log output.
Identifiers
The utils.identifiers module (added in 3.8.3) coerces raw Cascade
identifier dicts to IdentifierType:
from cascade_cms.utils.identifiers import to_identifier, to_identifiers
identifier = to_identifier({"id": "abc123", "type": "page", "path": None})
identifiers = to_identifiers([{"id": "a"}, {"id": "b"}])
Use these when processing raw API responses before passing identifiers to operations.