cascade-cms-rest 2.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,25 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ strategy:
11
+ matrix:
12
+ python-version: ["3.11", "3.12"]
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: ${{ matrix.python-version }}
18
+ - name: Install package
19
+ run: pip install -e ".[dev]"
20
+ - name: Lint
21
+ run: ruff check .
22
+ - name: Type check
23
+ run: mypy src/
24
+ - name: Test
25
+ run: pytest
@@ -0,0 +1,39 @@
1
+ # Dependency Review Action
2
+ #
3
+ # This Action will scan dependency manifest files that change as part of a Pull Request,
4
+ # surfacing known-vulnerable versions of the packages declared or updated in the PR.
5
+ # Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable
6
+ # packages will be blocked from merging.
7
+ #
8
+ # Source repository: https://github.com/actions/dependency-review-action
9
+ # Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
10
+ name: 'Dependency review'
11
+ on:
12
+ pull_request:
13
+ branches: [ "master" ]
14
+
15
+ # If using a dependency submission action in this workflow this permission will need to be set to:
16
+ #
17
+ # permissions:
18
+ # contents: write
19
+ #
20
+ # https://docs.github.com/en/enterprise-cloud@latest/code-security/supply-chain-security/understanding-your-software-supply-chain/using-the-dependency-submission-api
21
+ permissions:
22
+ contents: read
23
+ # Write permissions for pull-requests are required for using the `comment-summary-in-pr` option, comment out if you aren't using this option
24
+ pull-requests: write
25
+
26
+ jobs:
27
+ dependency-review:
28
+ runs-on: ubuntu-latest
29
+ steps:
30
+ - name: 'Checkout repository'
31
+ uses: actions/checkout@v4
32
+ - name: 'Dependency Review'
33
+ uses: actions/dependency-review-action@v4
34
+ # Commonly enabled options, see https://github.com/actions/dependency-review-action#configuration-options for all available options.
35
+ with:
36
+ comment-summary-in-pr: always
37
+ # fail-on-severity: moderate
38
+ # deny-licenses: GPL-1.0-or-later, LGPL-2.0-or-later
39
+ # retry-on-snapshot-warnings: true
@@ -0,0 +1,31 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+
9
+ # Virtual environments
10
+ .venv/
11
+ venv/
12
+
13
+ # Agents
14
+ .claude/
15
+ CLAUDE.md
16
+
17
+ # Cache
18
+ cache/
19
+ .pytest_cache/
20
+ .mypy_cache/
21
+ .ruff_cache/
22
+
23
+ # Environment / secrets
24
+ .env
25
+
26
+ # Editors
27
+ .vscode/
28
+ .idea/
29
+
30
+ # OS
31
+ .DS_Store
@@ -0,0 +1,29 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [2.0.2]
6
+
7
+ ### Fixed
8
+ - `SimplePayload.format_builder()` now respects field aliases during serialization, so payload subclasses (`copyParameters`, `deleteParameters`, `moveParameters`, `publishInformation`, etc.) emit camelCase keys instead of snake_case.
9
+ - `IdentifierType.identifier` now serializes as a bare 32-char hex string (instead of dashed UUID format) to match Cascade's REST API requirements.
10
+ - `CascadeWrapperBase` constructor was failing with `TypeError` due to `Operations` receiving `logger=` kwarg instead of matching its dataclass field name `_logger=`.
11
+ - Write operations (`edit`, `delete`, `copy`, `move`, `publish`, `checkIn`, `siteCopy`, `editAccessRights`, `markMessage`, `deleteMessage`, `editPreference`, `editWorkflowSettings`, `performWorkflowTransition`) now properly parse and surface bare `{"success": true}` responses instead of silently dropping them.
12
+
13
+ ### Added
14
+ - `Asset.asset_type` public property getter to read the asset type without accessing the private `_asset_type` attribute.
15
+ - `CascadeSuccess` response model and `parse_success` parser for handling success-only responses from write operations.
16
+
17
+ ## [2.0.0]
18
+
19
+ ### Added
20
+ - `Path`-based asset addressing (`IdentifierType | Path`) across all identifier-accepting operations.
21
+ - Dedicated response parsers for `readAccessRights`, `readWorkflowSettings`, `checkOut`, and `readWorkflowInformation`.
22
+ - `performWorkflowTransition` implementation (previously a stub).
23
+ - `src/`-layout packaging via `pyproject.toml` (Hatchling build backend).
24
+
25
+ ### Fixed
26
+ - `readWorkflowInformation` was calling the `readWorkflowSettings` endpoint instead of its own.
27
+
28
+ ### Changed
29
+ - `cmstypes.py` reorganized into clearly separated payload models, response models, type adapters, and parsers.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 py-cascade-cms contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,114 @@
1
+ # Packaging Roadmap: Distributing `cascade_cms` on PyPI
2
+
3
+ This document lays out the cleanest path from the current repo layout to a publishable PyPI package. Nothing here has been executed — it's a recommendation to work through when the library is ready to ship.
4
+
5
+ ## 1. Target file tree
6
+
7
+ Move to a `src/`-layout. It forces imports to go through the installed package (not the working directory), which is what actually catches packaging mistakes before a user does.
8
+
9
+ ```
10
+ py-cascade-cms/
11
+ ├── pyproject.toml
12
+ ├── README.md
13
+ ├── LICENSE
14
+ ├── CHANGELOG.md
15
+ ├── .gitignore
16
+ ├── src/
17
+ │ └── cascade_cms/
18
+ │ ├── __init__.py
19
+ │ ├── cmstypes.py
20
+ │ ├── driver.py
21
+ │ ├── operations.py
22
+ │ └── wrapper.py
23
+ ├── tests/
24
+ │ ├── conftest.py
25
+ │ ├── test_cmstypes.py
26
+ │ ├── test_operations.py
27
+ │ └── test_driver.py
28
+ ├── examples/
29
+ │ └── read_and_update_asset.py # test_script.py's pattern, cleaned up
30
+ └── .github/
31
+ └── workflows/
32
+ └── ci.yml
33
+ ```
34
+
35
+ Changes from today:
36
+ - `cascade_cms/` moves under `src/`.
37
+ - `test_script.py` moves into `examples/` (it's a usage demo, not a test — see §3) with the hardcoded credentials replaced by environment variable reads.
38
+ - `cache/cache.sqlite` stays out of version control (add to `.gitignore` if not already).
39
+
40
+ ## 2. `pyproject.toml`
41
+
42
+ Recommend **Hatchling** as the build backend — zero-config for a single-package `src/` layout, no `setup.py` needed.
43
+
44
+ ```toml
45
+ [build-system]
46
+ requires = ["hatchling"]
47
+ build-backend = "hatchling.build"
48
+
49
+ [project]
50
+ name = "cascade-cms"
51
+ version = "0.1.0"
52
+ description = "A typed, async REST client for Hannon Hill Cascade CMS"
53
+ readme = "README.md"
54
+ license = "MIT"
55
+ requires-python = ">=3.11" # uses `Self`, `TypeAlias`, PEP 604 unions
56
+ authors = [{ name = "..." }]
57
+ dependencies = [
58
+ "aiohttp-client-cache[sqlite]",
59
+ "python-dotenv",
60
+ "pydantic>=2",
61
+ ]
62
+
63
+ [project.optional-dependencies]
64
+ dev = ["pytest", "pytest-asyncio", "mypy", "ruff", "build", "twine"]
65
+
66
+ [project.urls]
67
+ Homepage = "https://github.com/<org>/py-cascade-cms"
68
+
69
+ [tool.hatch.build.targets.wheel]
70
+ packages = ["src/cascade_cms"]
71
+ ```
72
+
73
+ Note the current code already uses `Self` (PEP 673) and `X | Y` unions, so `requires-python` should be pinned to whatever minimum Python version was actually tested (3.11+ recommended; confirm against the `.venv`'s interpreter version).
74
+
75
+ ## 3. Tests vs. examples
76
+
77
+ There is currently no `tests/` directory — `test_script.py` is a manual, network-hitting demo script (hardcoded API key/URL), not an automated test. For PyPI-quality packaging:
78
+ - Move it to `examples/` and strip the hardcoded credentials in favor of `os.environ` + `python-dotenv`.
79
+ - Add real `tests/` using `pytest` + `pytest-asyncio`, mocking `aiohttp.ClientSession` (e.g. via `aioresponses` or a hand-rolled fake session) so tests don't require a live Cascade instance. Priority coverage: `resolve_identifier` (both `IdentifierType` and `Path` branches), `RequestExecutor.fetch` caching behavior, and the `ResponseParser` CascadeError-vs-success branching.
80
+
81
+ ## 4. Versioning
82
+
83
+ Start with manual versioning in `pyproject.toml` (`version = "0.1.0"`), bump by hand per release. Once the release cadence is established, consider `hatch-vcs` to derive the version from git tags instead of hand-editing — not necessary for a first release.
84
+
85
+ ## 5. README
86
+
87
+ Currently there is no `README.md`. It should show the fluent pattern already demonstrated in `test_script.py`/`examples/`:
88
+ ```python
89
+ with CascadeWrapperBase(env, config) as cascade:
90
+ cascade.operations.read(identifier)
91
+ results = cascade.submit_requests(Asset)
92
+ ```
93
+ plus a short note on the `IdentifierType | Path` addressing modes now supported.
94
+
95
+ ## 6. CI
96
+
97
+ A minimal `.github/workflows/ci.yml` running on push/PR: install `.[dev]`, run `ruff check`, `mypy src/`, `pytest`. Keep it to lint + type-check + test — no publish step in this workflow (see §7).
98
+
99
+ ## 7. Build & publish checklist (manual, not automated here)
100
+
101
+ 1. `python -m build` → produces `dist/*.whl` and `dist/*.tar.gz`.
102
+ 2. `twine check dist/*` → validates metadata/README rendering before upload.
103
+ 3. Upload to **TestPyPI** first: `twine upload --repository testpypi dist/*`, install in a scratch venv, sanity-check `import cascade_cms`.
104
+ 4. Only once TestPyPI install is confirmed clean: `twine upload dist/*` to the real index.
105
+ 5. Tag the release in git (`git tag vX.Y.Z`) matching the published version.
106
+
107
+ Steps 3-5 involve publishing to a shared, effectively irreversible public index — do these manually and deliberately, not as part of an automated agent run.
108
+
109
+ ## Summary of concrete next actions
110
+ 1. Add `pyproject.toml` (§2), remove `requirements.txt` once dependencies are captured there.
111
+ 2. Restructure into `src/cascade_cms/` (§1).
112
+ 3. Add `tests/` with mocked HTTP (§3); keep `test_script.py`'s pattern alive as `examples/`.
113
+ 4. Add `README.md`, `LICENSE`, `.gitignore`, CI workflow (§5, §6).
114
+ 5. Only then proceed to the manual build/publish checklist (§7).
@@ -0,0 +1,90 @@
1
+ Metadata-Version: 2.4
2
+ Name: cascade-cms-rest
3
+ Version: 2.0.2
4
+ Summary: A typed, async REST client for Hannon Hill Cascade CMS
5
+ Project-URL: Homepage, https://github.com/Sharkdroid/py-cascade-cms
6
+ Author: ...
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Requires-Python: >=3.11
10
+ Requires-Dist: aiohttp-client-cache[sqlite]
11
+ Requires-Dist: pydantic>=2
12
+ Requires-Dist: python-dotenv
13
+ Provides-Extra: dev
14
+ Requires-Dist: build; extra == 'dev'
15
+ Requires-Dist: mypy; extra == 'dev'
16
+ Requires-Dist: pytest; extra == 'dev'
17
+ Requires-Dist: pytest-asyncio; extra == 'dev'
18
+ Requires-Dist: ruff; extra == 'dev'
19
+ Requires-Dist: twine; extra == 'dev'
20
+ Description-Content-Type: text/markdown
21
+
22
+ # cascade-cms
23
+
24
+ A typed, async REST client for Hannon Hill Cascade CMS.
25
+
26
+ [Full Documentation](https://sharkdroid.github.io/wiki/cascade-cms-wiki/)
27
+
28
+ ## Usage
29
+
30
+ ```python
31
+ from cascade_cms.cmstypes import Asset, IdentifierType
32
+ from cascade_cms.wrapper import CascadeWrapperBase
33
+
34
+ environment_variables = {
35
+ "API_KEY": "...",
36
+ "CASCADE_URL": "...",
37
+ "SERVER": "prod", # label used for logfile naming
38
+ }
39
+ configuration_variables = {
40
+ "cache_name": "./cache/cache.sqlite",
41
+ "allowed_codes": (200,),
42
+ "allowed_methods": ("GET",),
43
+ }
44
+
45
+ with CascadeWrapperBase(environment_variables, configuration_variables) as cascade:
46
+ identifier = IdentifierType(identifier="e868f539ac1001062cfa029c4c5df4d0", asset_type="folder")
47
+ cascade.operations.read(identifier)
48
+ results = cascade.submit_requests(Asset)
49
+ ```
50
+
51
+ Operations that take an identifier (`read`, `delete`, `copy`, `move`, `publish`, `checkIn`, `checkOut`,
52
+ `listSubscribers`, `readAccessRights`, `readWorkflowSettings`, `readWorkflowInformation`,
53
+ `performWorkflowTransition`) accept either an `IdentifierType` (asset type + UUID) or a `Path`
54
+ (asset type + site name + site-relative path) — see `cascade_cms.cmstypes.resolve_identifier`.
55
+
56
+ See `examples/read_and_update_asset.py` for a fuller walkthrough.
57
+
58
+ ### Logging
59
+
60
+ `CascadeWrapperBase` accepts an optional third `debug` argument. Leaving it as `None`
61
+ (the default) runs in **normal mode**: a minimal console (`[INIT]`/`[RUNNING]`/`Processed: n/N`/
62
+ `[DONE]`/`[EXIT]`) plus a simple logfile at `./logs/{SERVER}_{timestamp}.log`. Passing a dict
63
+ switches to **debug mode**: a quiet console and a verbose, nested logfile at
64
+ `./logs/{SERVER}_debug_{timestamp}.log` describing every request, response, callback, and error.
65
+
66
+ ```python
67
+ debug_config = {
68
+ "log_dir": "./logs",
69
+ "log_operations": True,
70
+ "log_callbacks": True,
71
+ "log_responses": True,
72
+ "show_payload_data": True,
73
+ "show_network_headers": False,
74
+ "show_error_variables": True,
75
+ "response_line_limit": 8, # -1 = dump full response body
76
+ }
77
+
78
+ with CascadeWrapperBase(environment_variables, configuration_variables, debug=debug_config) as cascade:
79
+ ...
80
+ ```
81
+
82
+ All keys are required in debug mode — there are no inferred defaults, so you always know what
83
+ you opted into.
84
+
85
+ ## Development
86
+
87
+ ```bash
88
+ pip install -e ".[dev]"
89
+ pytest
90
+ ```
@@ -0,0 +1,69 @@
1
+ # cascade-cms
2
+
3
+ A typed, async REST client for Hannon Hill Cascade CMS.
4
+
5
+ [Full Documentation](https://sharkdroid.github.io/wiki/cascade-cms-wiki/)
6
+
7
+ ## Usage
8
+
9
+ ```python
10
+ from cascade_cms.cmstypes import Asset, IdentifierType
11
+ from cascade_cms.wrapper import CascadeWrapperBase
12
+
13
+ environment_variables = {
14
+ "API_KEY": "...",
15
+ "CASCADE_URL": "...",
16
+ "SERVER": "prod", # label used for logfile naming
17
+ }
18
+ configuration_variables = {
19
+ "cache_name": "./cache/cache.sqlite",
20
+ "allowed_codes": (200,),
21
+ "allowed_methods": ("GET",),
22
+ }
23
+
24
+ with CascadeWrapperBase(environment_variables, configuration_variables) as cascade:
25
+ identifier = IdentifierType(identifier="e868f539ac1001062cfa029c4c5df4d0", asset_type="folder")
26
+ cascade.operations.read(identifier)
27
+ results = cascade.submit_requests(Asset)
28
+ ```
29
+
30
+ Operations that take an identifier (`read`, `delete`, `copy`, `move`, `publish`, `checkIn`, `checkOut`,
31
+ `listSubscribers`, `readAccessRights`, `readWorkflowSettings`, `readWorkflowInformation`,
32
+ `performWorkflowTransition`) accept either an `IdentifierType` (asset type + UUID) or a `Path`
33
+ (asset type + site name + site-relative path) — see `cascade_cms.cmstypes.resolve_identifier`.
34
+
35
+ See `examples/read_and_update_asset.py` for a fuller walkthrough.
36
+
37
+ ### Logging
38
+
39
+ `CascadeWrapperBase` accepts an optional third `debug` argument. Leaving it as `None`
40
+ (the default) runs in **normal mode**: a minimal console (`[INIT]`/`[RUNNING]`/`Processed: n/N`/
41
+ `[DONE]`/`[EXIT]`) plus a simple logfile at `./logs/{SERVER}_{timestamp}.log`. Passing a dict
42
+ switches to **debug mode**: a quiet console and a verbose, nested logfile at
43
+ `./logs/{SERVER}_debug_{timestamp}.log` describing every request, response, callback, and error.
44
+
45
+ ```python
46
+ debug_config = {
47
+ "log_dir": "./logs",
48
+ "log_operations": True,
49
+ "log_callbacks": True,
50
+ "log_responses": True,
51
+ "show_payload_data": True,
52
+ "show_network_headers": False,
53
+ "show_error_variables": True,
54
+ "response_line_limit": 8, # -1 = dump full response body
55
+ }
56
+
57
+ with CascadeWrapperBase(environment_variables, configuration_variables, debug=debug_config) as cascade:
58
+ ...
59
+ ```
60
+
61
+ All keys are required in debug mode — there are no inferred defaults, so you always know what
62
+ you opted into.
63
+
64
+ ## Development
65
+
66
+ ```bash
67
+ pip install -e ".[dev]"
68
+ pytest
69
+ ```
@@ -0,0 +1,26 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "cascade-cms-rest"
7
+ version = "2.0.2"
8
+ description = "A typed, async REST client for Hannon Hill Cascade CMS"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.11" # uses `Self`, `TypeAlias`, PEP 604 unions
12
+ authors = [{ name = "..." }]
13
+ dependencies = [
14
+ "aiohttp-client-cache[sqlite]",
15
+ "python-dotenv",
16
+ "pydantic>=2",
17
+ ]
18
+
19
+ [project.optional-dependencies]
20
+ dev = ["pytest", "pytest-asyncio", "mypy", "ruff", "build", "twine"]
21
+
22
+ [project.urls]
23
+ Homepage = "https://github.com/Sharkdroid/py-cascade-cms"
24
+
25
+ [tool.hatch.build.targets.wheel]
26
+ packages = ["src/cascade_cms"]
@@ -0,0 +1,6 @@
1
+ """Cascade CMS REST API client library.
2
+
3
+ Provides an async REST driver, a fluent Operations builder for queuing
4
+ Cascade CMS requests, Pydantic-based payload/response models, and an
5
+ OperationLogger for console/logfile output.
6
+ """