roborean-storage-base 0.1.2__py3-none-any.whl
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.
- roborean_storage_base/__init__.py +16 -0
- roborean_storage_base/errors.py +17 -0
- roborean_storage_base/ports.py +57 -0
- roborean_storage_base/types.py +5 -0
- roborean_storage_base-0.1.2.dist-info/METADATA +26 -0
- roborean_storage_base-0.1.2.dist-info/RECORD +7 -0
- roborean_storage_base-0.1.2.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Persistence ports for Roborean projects and durable runs."""
|
|
2
|
+
|
|
3
|
+
from .errors import ConflictError, IntegrityError, NotFoundError, StorageError
|
|
4
|
+
from .ports import ArtifactStore, ProjectRepository, RunRepository
|
|
5
|
+
|
|
6
|
+
__version__ = "0.2.0"
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"ArtifactStore",
|
|
10
|
+
"ConflictError",
|
|
11
|
+
"IntegrityError",
|
|
12
|
+
"NotFoundError",
|
|
13
|
+
"ProjectRepository",
|
|
14
|
+
"RunRepository",
|
|
15
|
+
"StorageError",
|
|
16
|
+
]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Shared storage failure types."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class StorageError(Exception):
|
|
5
|
+
"""Base storage failure."""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class NotFoundError(StorageError):
|
|
9
|
+
"""Entity missing from the store."""
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ConflictError(StorageError):
|
|
13
|
+
"""Idempotency or optimistic-lock conflict."""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class IntegrityError(StorageError):
|
|
17
|
+
"""Corrupt or incomplete package."""
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""Repository and artifact store protocols."""
|
|
2
|
+
|
|
3
|
+
from typing import Protocol
|
|
4
|
+
|
|
5
|
+
from roborean_spec import Project, RunRecord
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ProjectRepository(Protocol):
|
|
9
|
+
"""Load and save portable projects by identifier."""
|
|
10
|
+
|
|
11
|
+
def get(self, project_id: str) -> Project:
|
|
12
|
+
"""Return the current revision of a project."""
|
|
13
|
+
|
|
14
|
+
def get_revision(self, project_id: str, revision: str) -> Project:
|
|
15
|
+
"""Return a pinned project revision."""
|
|
16
|
+
|
|
17
|
+
def save(self, project: Project, *, revision: str | None = None) -> str:
|
|
18
|
+
"""Persist a project and return the revision identifier."""
|
|
19
|
+
|
|
20
|
+
def list_ids(self) -> list[str]:
|
|
21
|
+
"""List stored project identifiers."""
|
|
22
|
+
|
|
23
|
+
def delete(self, project_id: str) -> None:
|
|
24
|
+
"""Remove a project and its revisions."""
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class RunRepository(Protocol):
|
|
28
|
+
"""Persist durable run records with idempotency lookup."""
|
|
29
|
+
|
|
30
|
+
def get(self, run_id: str) -> RunRecord:
|
|
31
|
+
"""Return one run by identifier."""
|
|
32
|
+
|
|
33
|
+
def get_by_idempotency(
|
|
34
|
+
self, project_id: str, idempotency_key: str
|
|
35
|
+
) -> RunRecord | None:
|
|
36
|
+
"""Return an existing run for an idempotency key, if any."""
|
|
37
|
+
|
|
38
|
+
def save(self, record: RunRecord) -> None:
|
|
39
|
+
"""Insert a new run record."""
|
|
40
|
+
|
|
41
|
+
def update(self, record: RunRecord) -> None:
|
|
42
|
+
"""Replace an existing run record."""
|
|
43
|
+
|
|
44
|
+
def list_for_project(
|
|
45
|
+
self, project_id: str, *, limit: int = 50
|
|
46
|
+
) -> list[RunRecord]:
|
|
47
|
+
"""List recent runs for a project, newest first."""
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class ArtifactStore(Protocol):
|
|
51
|
+
"""Store opaque binary artifacts referenced by runs."""
|
|
52
|
+
|
|
53
|
+
def put_bytes(self, key: str, data: bytes, *, content_type: str) -> str:
|
|
54
|
+
"""Store bytes and return the storage key."""
|
|
55
|
+
|
|
56
|
+
def get_bytes(self, key: str) -> bytes:
|
|
57
|
+
"""Load previously stored bytes."""
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: roborean-storage-base
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: Persistence ports for Roborean projects and runs
|
|
5
|
+
Project-URL: Homepage, https://github.com/TNick/roborean
|
|
6
|
+
Project-URL: Repository, https://github.com/TNick/roborean
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Requires-Python: >=3.11
|
|
9
|
+
Requires-Dist: roborean-spec>=0.1.1
|
|
10
|
+
Provides-Extra: dev
|
|
11
|
+
Requires-Dist: black>=24.0; extra == 'dev'
|
|
12
|
+
Requires-Dist: flake8>=7.0; extra == 'dev'
|
|
13
|
+
Requires-Dist: isort>=5.0; extra == 'dev'
|
|
14
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# roborean-storage-base
|
|
18
|
+
|
|
19
|
+
Persistence ports for Roborean projects and durable runs.
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
from roborean_storage_base import ProjectRepository, RunRepository
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Adapters implement these protocols; the engine never writes files directly
|
|
26
|
+
from `runner.py`.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
roborean_storage_base/__init__.py,sha256=59ZG0PuTFD2lHpnvc5d8soWl7upg2JD-KTeKyVSngFo,400
|
|
2
|
+
roborean_storage_base/errors.py,sha256=7v8ZUZn5xE8ZxSBdJG-EYpgZ1ErP_RR_PlgAkC2upFk,346
|
|
3
|
+
roborean_storage_base/ports.py,sha256=nB2OpjIPrwj80-TgeBhyoHolhQSGj_C37Sp28VFOB8c,1792
|
|
4
|
+
roborean_storage_base/types.py,sha256=WXCiU9i_k_IgcO2SddbdBssBG2aLigoxKVU8WEO9k4s,187
|
|
5
|
+
roborean_storage_base-0.1.2.dist-info/METADATA,sha256=FYqZSo_3fJ8etWxgZLyRvUQk_tJrP2-iv3HExpks1W8,814
|
|
6
|
+
roborean_storage_base-0.1.2.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
|
|
7
|
+
roborean_storage_base-0.1.2.dist-info/RECORD,,
|