cascade-cms
A typed, async REST client for Hannon Hill Cascade CMS.
Usage
from cascade_cms.cmstypes import Asset, IdentifierType
from cascade_cms.wrapper import CascadeWrapperBase
environment_variables = {
"API_KEY": "...",
"CASCADE_URL": "...",
"SERVER": "prod", # label used for logfile naming
}
configuration_variables = {
"cache_name": "./cache/cache.sqlite",
"allowed_codes": (200,),
"allowed_methods": ("GET",),
}
with CascadeWrapperBase(environment_variables, configuration_variables) as cascade:
identifier = IdentifierType(identifier="e868f539ac1001062cfa029c4c5df4d0", asset_type="folder")
cascade.operations.read(identifier)
results = cascade.submit_requests(Asset)
Operations that take an identifier (read, delete, copy, move, publish, checkIn, checkOut,
listSubscribers, readAccessRights, readWorkflowSettings, readWorkflowInformation,
performWorkflowTransition) accept either an IdentifierType (asset type + UUID) or a Path
(asset type + site name + site-relative path) — see cascade_cms.cmstypes.resolve_identifier.
See examples/read_and_update_asset.py for a fuller walkthrough.
Operation chains
Every cascade.operations.<op>() call starts an operation chain and returns it. Chaining
.then(callback) or another operation onto it adds a step to that chain; a fresh
cascade.operations.<op>() call starts a separate one.
Steps inside a chain run strictly in order, each receiving the previous step's result, so a read can be transformed and written back in one pass:
def rewrite(asset):
asset.keywords = "updated"
return asset
with CascadeWrapperBase(environment_variables, configuration_variables) as cascade:
cascade.operations.read(page_a).edit(page_a, rewrite).publish(page_a)
cascade.operations.read(page_b).then(report)
cascade.operations.delete(old_page)
results = cascade.submit_requests()
- Chains run concurrently, so a batch still costs one round of requests, not one per chain. Only the steps within a chain are sequential.
- One result per chain, in the order the chains were built —
results[0]belongs to the first chain. No more matching responses back to requests by hand. - Failures are values, not gaps. A chain stops at its first failure and that object lands in
the results: a
CascadeErrorwhen the API rejects a request, or the exception a callback raised. Other chains are unaffected. Check withisinstance(result, CascadeError). - A callback returning
Nonepasses the previous result through, so side-effect callbacks (logging, reporting) don't break the chain. edit()accepts a callable as its payload; it is invoked with the previous step's result, which is how a transformed asset gets written back.- Chains are cleared once
submit_requests()returns, so a callback registered for one batch never re-runs in the next.
Logging
CascadeWrapperBase accepts an optional third debug argument. Leaving it as None
(the default) runs in normal mode: a minimal console ([INIT]/[RUNNING]/Processed: n/N/
[DONE]/[EXIT]) plus a simple logfile at ./logs/{SERVER}_{timestamp}.log. Passing a dict
switches to debug mode: a quiet console and a verbose, nested logfile at
./logs/{SERVER}_debug_{timestamp}.log describing every request, response, callback, and error.
debug_config = {
"log_dir": "./logs",
"log_operations": True,
"log_callbacks": True,
"log_responses": True,
"show_payload_data": True,
"show_network_headers": False,
"show_error_variables": True,
"response_line_limit": 8, # -1 = dump full response body
}
with CascadeWrapperBase(environment_variables, configuration_variables, debug=debug_config) as cascade:
...
All keys are required in debug mode — there are no inferred defaults, so you always know what you opted into.
Development
pip install -e ".[dev]"
pytest
Release files for cascade-cms-rest 3.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| cascade_cms_rest-3.1.2.tar.gz | 436.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cascade_cms_rest-3.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 488.4 kB
Release files / cascade_cms_rest-3.1.2.tar.gz
| Download URL | cascade_cms_rest-3.1.2.tar.gz |
|---|---|
| Size | 436.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bb3fc19b0210fc0bca4f75bd7e8a0abefb27aace38b3c4ddee46db1e2709aa05
|
|
BLAKE2b-256 checksum How to use checksums |
616df71b70ac095769a3403862239563a06c966265368118e4105a0df040ca7f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.
Transparency logRelease files / cascade_cms_rest-3.1.2-py3-none-any.whl
| Download URL | cascade_cms_rest-3.1.2-py3-none-any.whl |
|---|---|
| Size | 52.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d7b47c61f838bc954f294432eb4799fa5d5f2dc526da7a347eab451af9a83213
|
|
BLAKE2b-256 checksum How to use checksums |
60f123915f5954873a6d76009abc4760d0a6bece14683e51847dd6fa381427b9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.
Transparency log