Metadata-Version: 2.4
Name: spltz-viur-actions
Version: 0.4.0
Summary: Action-based request handling and workflow engine for ViUR modules.
Author: Andreas H. Kelch
License: MIT License
        
        Copyright © 2026 Andreas H. Kelch
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://github.com/sprengplatz/viur-actions
Project-URL: Repository, https://github.com/sprengplatz/viur-actions.git
Project-URL: Bug Tracker, https://github.com/sprengplatz/viur-actions/issues
Project-URL: Changelog, https://github.com/sprengplatz/viur-actions/blob/main/CHANGELOG.md
Keywords: viur,actions,workflow,router,render
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: viur-core<4,>=3.8
Provides-Extra: test
Requires-Dist: pytest~=8.0; extra == "test"
Requires-Dist: pytest-cov~=5.0; extra == "test"
Requires-Dist: coverage[toml]~=7.0; extra == "test"
Requires-Dist: spltz-viur-light-mock>=0.2.0; extra == "test"
Provides-Extra: docs
Requires-Dist: mkdocs-material~=9.5; extra == "docs"
Requires-Dist: mkdocstrings[python]~=0.26; extra == "docs"
Requires-Dist: mkdocs-static-i18n~=1.3; extra == "docs"
Provides-Extra: dev
Requires-Dist: spltz-viur-actions[docs,test]; extra == "dev"
Requires-Dist: build~=1.2; extra == "dev"
Dynamic: license-file

# viur-actions

Action-based request handling for ViUR modules.

[![Tests](https://github.com/sprengplatz/viur-actions/actions/workflows/test.yml/badge.svg)](https://github.com/sprengplatz/viur-actions/actions/workflows/test.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

## Features

- `@action` decorator and `ActionModule` mixin
- Class-init hook wiring (`can<X>` / `on<X>` / `then<X>` / `<X>Skel`), falling
  back to the suffix-less defaults (`can` / `on` / `then` / `skel`)
- **Envelope-v2 via a versioned renderer** — mounted under `/json/v2/` ·
  `/vi/v2/` by `install()`, selected per-URL. No monkey-patch, no global
  switch. By default the unversioned `/json/` · `/vi/` follow the newest
  version (v2); pass `alias_to_newest=False` to keep them on v1.

Multi-step workflows (drafts, sliding TTL, optimistic locking, cleanup task)
live in the sibling
[`viur-workflow`](https://github.com/sprengplatz/viur-workflow) package. See
[CHANGELOG.md](CHANGELOG.md) for the running summary.

## Requirements

- Python ≥ 3.12
- viur-core ≥ 3.8, < 4

## Install

```bash
pip install spltz-viur-actions
```

## Quick taste

Serve the envelope by mounting the versioned renderer after `setup()`:

```python
from viur.core import setup
import viur.actions
import modules

app = setup(modules)
viur.actions.install()          # mounts /json/v2/… + /vi/v2/…; unversioned /json/ · /vi/ follow v2
```

Declare actions and hooks on a module:

```python
from viur.core.prototypes import List
from viur.actions import action, ActionModule

class Example(ActionModule, List):

    @action
    def edit(self, key, **kwargs):
        ...

    # Fallback hooks — every action without specific hooks lands here.
    # (No `skel`: on a SkelModule viur-core's own `skel` is the base
    #  skeleton factory, so defining one here would shadow it and recurse.)
    def can(self, skel): ...
    def on(self, skel): ...
    def then(self, skel): ...

    # Action-specific overrides — picked up automatically:
    def canEdit(self, skel): ...
    def editSkel(self): ...
```

The class-init wiring (`__init_subclass__`) checks at class definition time
which hooks the module provides, and resolves missing ones to the
suffix-less default chain. Lookup at runtime is constant-time.

> **Note:** these hooks are resolved for *your own* `@action` bodies (via the
> `runtime` helpers). viur-core's built-in `view`/`edit`/… still call their own
> `canView`/`onEdited`/… directly — `can` is **not** a global policy for them.

## Development

Two test layers, run separately:

**Unit (fast, mocked) — `tests/`, 100 % coverage gate:**

```bash
git clone https://github.com/sprengplatz/viur-actions
cd viur-actions
pip install --no-deps -e .
pip install pytest pytest-cov 'coverage[toml]' 'spltz-viur-light-mock>=0.2.0'
pytest                  # 100% coverage required
```

`spltz-viur-light-mock` provides the `viur.core.*` stand-ins so these run without
the App Engine stack.

**Integration (real core) — `integration/`, no coverage gate:**

```bash
pip install "viur-core>=3.8,<4" rsa pytest      # NOT spltz-viur-light-mock
pip install --no-deps -e .
python -m pytest -c integration/pytest.ini integration
```

Runs the envelope + signature-parity tests against the **real** framework —
the layer that catches mock-vs-core drift. See
[integration/README.md](integration/README.md).

> **Coverage policy.** The 100 % gate applies to the **unit** layer only.
> The integration layer runs **without** a coverage requirement — a coverage
> target there would pressure mocking the very framework it exists to exercise.

## License

MIT — see [LICENSE](LICENSE).
