marsh-lib 0.3.2__tar.gz → 0.3.3__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.
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/PKG-INFO +1 -1
- marsh_lib-0.3.3/docs/releases/v0.3.3.md +33 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/pyproject.toml +1 -1
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/serialization.py +4 -26
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/docker/docker_executor.py +5 -1
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/.circleci/config.yml +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/.github/ISSUE_TEMPLATE/bug-report.md +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/.github/ISSUE_TEMPLATE/other.md +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/.github/pull_request_template.md +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/.github/workflows/docker-integration.yml +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/.github/workflows/release-rehearsal.yml +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/.github/workflows/release.yml +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/.github/workflows/ssh-integration.yml +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/.github/workflows/test.yml +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/.gitignore +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/LICENSE +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/README.md +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/Taskfile.yml +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/docs/P0_REPOSITORY_AUDIT.md +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/docs/P6_UX_COMPOSITION_EVALUATION.md +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/docs/api-migration.md +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/docs/architecture.md +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/docs/v0.3.2-test-portability.md +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/docs/workflow-guide.md +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/run_act.sh +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/run_pytest.sh +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/run_tests_with_sysbox.sh +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/__init__.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/bash/__init__.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/bash/bash_factory.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/bash/bash_grammar.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/bash/bash_runner_decorators.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/bash/bash_script.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/constants.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/__init__.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/authenticator.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/cache.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/cmd_run_decorator.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/cmd_runner_spec.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/command_grammar.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/configuration.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/connector.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/conveyor.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/dag_bridge.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/diagnostics.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/domain.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/executor.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/expression.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/observability.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/policies.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/providers.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/runtime.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/script.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/core/validation.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/dag/__init__.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/dag/dag.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/dag/node.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/dag/startable.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/docker/__init__.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/docker/docker_command_grammar.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/exceptions.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/logger.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/modifier_functions/__init__.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/modifier_functions/case_conversion.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/modifier_functions/readers.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/powershell/__init__.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/processor_functions/__init__.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/processor_functions/printers.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/processor_functions/raisers.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/processor_functions/redirections.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/providers/__init__.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/runtime/__init__.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/signals.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/ssh/__init__.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/ssh/ssh_command_grammar.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/ssh/ssh_connector.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/ssh/ssh_factory.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/utils/__init__.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/utils/output_streams.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/src/marsh/workflow/__init__.py +0 -0
- {marsh_lib-0.3.2 → marsh_lib-0.3.3}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: marsh-lib
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: Lightweight, extensible Python library for building, managing, and executing command workflows.
|
|
5
5
|
Project-URL: Repository, https://github.com/CedricAnover/marsh
|
|
6
6
|
Author-email: Cedric Anover <cedric.anover@hotmail.com>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# v0.3.3 — Kernel Contract Stabilization
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
v0.3.3 stabilizes the smallest Marsh execution kernel before further provider and concurrency work.
|
|
6
|
+
|
|
7
|
+
## Contract changes
|
|
8
|
+
|
|
9
|
+
- `plan_workflow()` is the canonical dependency-planning semantic owner.
|
|
10
|
+
- `validate_workflow()` delegates to canonical planning instead of maintaining a second topological implementation.
|
|
11
|
+
- Deterministic task order and initial readiness are regression-tested.
|
|
12
|
+
- Scheduler and Machine replacement are covered by conformance tests.
|
|
13
|
+
- Lifecycle, failure, timeout, cancellation, dependency-skip, and fail-fast semantics are regression-tested.
|
|
14
|
+
- Modern namespace compatibility remains covered without removing legacy APIs.
|
|
15
|
+
- Observer failures remain non-authoritative and cannot change execution outcomes.
|
|
16
|
+
|
|
17
|
+
## Reliability fix
|
|
18
|
+
|
|
19
|
+
- Hardened Docker container cleanup against auto-remove races that can surface as stale-container `404 Not Found` errors.
|
|
20
|
+
|
|
21
|
+
## Verification
|
|
22
|
+
|
|
23
|
+
- CircleCI: Python 3.10, 3.11, 3.12
|
|
24
|
+
- CircleCI: lint and wheel build
|
|
25
|
+
- CircleCI: Docker integration
|
|
26
|
+
- CircleCI: SSH integration
|
|
27
|
+
- GitHub Actions: Linux test/coverage
|
|
28
|
+
- GitHub Actions: native Windows portability
|
|
29
|
+
- GitHub Actions: Docker integration smoke
|
|
30
|
+
|
|
31
|
+
## Scope guardrails
|
|
32
|
+
|
|
33
|
+
No new runtime dependency, concurrency engine, remote execution model, workflow IR expansion, or provider architecture expansion was introduced in this release.
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "marsh-lib"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.3"
|
|
8
8
|
description = "Lightweight, extensible Python library for building, managing, and executing command workflows."
|
|
9
9
|
authors = [{ name = "Cedric Anover", email = "cedric.anover@hotmail.com" }]
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -1,39 +1,17 @@
|
|
|
1
1
|
"""Workflow validation and deterministic serialization."""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
-
from heapq import heappop, heappush
|
|
5
4
|
from typing import Any, Mapping
|
|
6
5
|
|
|
7
6
|
from marsh.core.configuration import normalize_workflow
|
|
8
7
|
from marsh.core.domain import Workflow
|
|
8
|
+
from marsh.core.runtime import plan_workflow
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def validate_workflow(workflow: Workflow | Mapping[str, Any]) -> tuple[str, ...]:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
dependents = {task_id: [] for task_id in tasks}
|
|
16
|
-
for task in workflow.tasks:
|
|
17
|
-
for dependency in task.dependencies:
|
|
18
|
-
if dependency not in tasks:
|
|
19
|
-
raise ValueError(f"task {task.id!r} has unknown dependencies: {dependency}")
|
|
20
|
-
indegree[task.id] += 1
|
|
21
|
-
dependents[dependency].append(task.id)
|
|
22
|
-
ready = []
|
|
23
|
-
for task_id, degree in indegree.items():
|
|
24
|
-
if degree == 0:
|
|
25
|
-
heappush(ready, task_id)
|
|
26
|
-
order = []
|
|
27
|
-
while ready:
|
|
28
|
-
task_id = heappop(ready)
|
|
29
|
-
order.append(task_id)
|
|
30
|
-
for dependent in sorted(dependents[task_id]):
|
|
31
|
-
indegree[dependent] -= 1
|
|
32
|
-
if indegree[dependent] == 0:
|
|
33
|
-
heappush(ready, dependent)
|
|
34
|
-
if len(order) != len(tasks):
|
|
35
|
-
raise ValueError("workflow contains a dependency cycle")
|
|
36
|
-
return tuple(order)
|
|
12
|
+
"""Validate dependencies using the canonical planning semantic owner."""
|
|
13
|
+
|
|
14
|
+
return plan_workflow(normalize_workflow(workflow)).order
|
|
37
15
|
|
|
38
16
|
|
|
39
17
|
def _data(value: Any) -> Any:
|
|
@@ -103,7 +103,11 @@ class DockerContainer:
|
|
|
103
103
|
self._timer.cancel()
|
|
104
104
|
|
|
105
105
|
# Remove the Container
|
|
106
|
-
|
|
106
|
+
try:
|
|
107
|
+
all_containers: list[Container] = self._client.containers.list(all=True)
|
|
108
|
+
except NotFound:
|
|
109
|
+
all_containers = []
|
|
110
|
+
|
|
107
111
|
for container in all_containers:
|
|
108
112
|
if container.name == self._name:
|
|
109
113
|
try:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|