cks-runtime 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.
- cks_runtime/__init__.py +11 -0
- cks_runtime/adapters/__init__.py +0 -0
- cks_runtime/config.py +22 -0
- cks_runtime/core_api/__init__.py +0 -0
- cks_runtime/core_api/interfaces.py +78 -0
- cks_runtime/diagnostics/__init__.py +0 -0
- cks_runtime/diagnostics/aggregator.py +115 -0
- cks_runtime/diagnostics/diagnostic.py +68 -0
- cks_runtime/explainability/__init__.py +0 -0
- cks_runtime/explainability/explainability_manager.py +0 -0
- cks_runtime/runtime.py +85 -0
- cks_runtime/session/__init__.py +0 -0
- cks_runtime/session/session.py +72 -0
- cks_runtime/session/session_manager.py +98 -0
- cks_runtime/storage/__init__.py +0 -0
- cks_runtime/storage/exceptions.py +37 -0
- cks_runtime/storage/memory_storage.py +127 -0
- cks_runtime/storage/storage.py +90 -0
- cks_runtime/transaction/__init__.py +0 -0
- cks_runtime/transaction/transaction.py +149 -0
- cks_runtime/transaction/transaction_manager.py +125 -0
- cks_runtime/versioning/__init__.py +0 -0
- cks_runtime/versioning/version.py +44 -0
- cks_runtime/versioning/version_manager.py +81 -0
- cks_runtime-0.1.2.dist-info/METADATA +306 -0
- cks_runtime-0.1.2.dist-info/RECORD +29 -0
- cks_runtime-0.1.2.dist-info/WHEEL +5 -0
- cks_runtime-0.1.2.dist-info/licenses/LICENSE +21 -0
- cks_runtime-0.1.2.dist-info/top_level.txt +1 -0
cks_runtime/__init__.py
ADDED
|
File without changes
|
cks_runtime/config.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Runtime configuration.
|
|
3
|
+
|
|
4
|
+
SPEC-001 Runtime Overview
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass(slots=True)
|
|
13
|
+
class RuntimeConfig:
|
|
14
|
+
"""
|
|
15
|
+
Runtime configuration.
|
|
16
|
+
|
|
17
|
+
Future specifications may extend this configuration.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
runtime_name: str = "CKS Runtime"
|
|
21
|
+
|
|
22
|
+
runtime_version: str = "0.1.2"
|
|
File without changes
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Core boundary interfaces.
|
|
3
|
+
|
|
4
|
+
This module defines the exclusive semantic boundary
|
|
5
|
+
between CKS Runtime and CKS Core.
|
|
6
|
+
|
|
7
|
+
Runtime depends only on these abstractions.
|
|
8
|
+
|
|
9
|
+
Concrete Core implementations are supplied externally.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from abc import ABC
|
|
15
|
+
from abc import abstractmethod
|
|
16
|
+
from typing import Any
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class CoreInterface(ABC):
|
|
20
|
+
"""
|
|
21
|
+
Semantic boundary between Runtime and CKS Core.
|
|
22
|
+
|
|
23
|
+
Runtime owns operational behaviour.
|
|
24
|
+
|
|
25
|
+
CKS Core owns semantic behaviour.
|
|
26
|
+
|
|
27
|
+
Runtime shall never implement semantic rules itself.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
@abstractmethod
|
|
31
|
+
def validate(
|
|
32
|
+
self,
|
|
33
|
+
knowledge_structure: Any,
|
|
34
|
+
) -> Any:
|
|
35
|
+
"""
|
|
36
|
+
Execute canonical Core validation.
|
|
37
|
+
|
|
38
|
+
Validation semantics belong exclusively
|
|
39
|
+
to CKS Core.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
@abstractmethod
|
|
43
|
+
def serialize(
|
|
44
|
+
self,
|
|
45
|
+
knowledge_structure: Any,
|
|
46
|
+
) -> Any:
|
|
47
|
+
"""
|
|
48
|
+
Produce canonical serialization.
|
|
49
|
+
|
|
50
|
+
Serialization semantics belong exclusively
|
|
51
|
+
to CKS Core.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
@abstractmethod
|
|
55
|
+
def evolve(
|
|
56
|
+
self,
|
|
57
|
+
knowledge_structure: Any,
|
|
58
|
+
operation: Any,
|
|
59
|
+
) -> Any:
|
|
60
|
+
"""
|
|
61
|
+
Execute canonical semantic evolution.
|
|
62
|
+
|
|
63
|
+
Runtime coordinates execution.
|
|
64
|
+
|
|
65
|
+
CKS Core defines the resulting semantic state.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
@abstractmethod
|
|
69
|
+
def explain(
|
|
70
|
+
self,
|
|
71
|
+
knowledge_structure: Any,
|
|
72
|
+
) -> Any:
|
|
73
|
+
"""
|
|
74
|
+
Produce semantic explanation.
|
|
75
|
+
|
|
76
|
+
Runtime may expose explanations but never
|
|
77
|
+
generates semantic explanations itself.
|
|
78
|
+
"""
|
|
File without changes
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Runtime Diagnostic Aggregator.
|
|
3
|
+
|
|
4
|
+
Aggregates Runtime and Core diagnostics.
|
|
5
|
+
|
|
6
|
+
Aggregation preserves ordering and ownership.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import Iterable
|
|
12
|
+
|
|
13
|
+
from .diagnostic import (
|
|
14
|
+
Diagnostic,
|
|
15
|
+
DiagnosticSeverity,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class DiagnosticAggregator:
|
|
20
|
+
"""
|
|
21
|
+
Collects Runtime Diagnostics.
|
|
22
|
+
|
|
23
|
+
Diagnostics remain immutable.
|
|
24
|
+
|
|
25
|
+
Aggregation never modifies their meaning.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self) -> None:
|
|
29
|
+
self._diagnostics: list[Diagnostic] = []
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def add(
|
|
33
|
+
self,
|
|
34
|
+
diagnostic: Diagnostic,
|
|
35
|
+
) -> None:
|
|
36
|
+
"""
|
|
37
|
+
Add a Diagnostic.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
self._diagnostics.append(
|
|
41
|
+
diagnostic
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def extend(
|
|
46
|
+
self,
|
|
47
|
+
diagnostics: Iterable[Diagnostic],
|
|
48
|
+
) -> None:
|
|
49
|
+
"""
|
|
50
|
+
Add multiple Diagnostics.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
self._diagnostics.extend(
|
|
54
|
+
diagnostics
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def clear(
|
|
59
|
+
self,
|
|
60
|
+
) -> None:
|
|
61
|
+
"""
|
|
62
|
+
Remove all Diagnostics.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
self._diagnostics.clear()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def all(
|
|
69
|
+
self,
|
|
70
|
+
) -> tuple[Diagnostic, ...]:
|
|
71
|
+
"""
|
|
72
|
+
Return an immutable snapshot.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
return tuple(
|
|
76
|
+
self._diagnostics
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def count(
|
|
81
|
+
self,
|
|
82
|
+
) -> int:
|
|
83
|
+
return len(
|
|
84
|
+
self._diagnostics
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def has_errors(
|
|
89
|
+
self,
|
|
90
|
+
) -> bool:
|
|
91
|
+
"""
|
|
92
|
+
True if any Runtime Diagnostic has ERROR severity.
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
return any(
|
|
96
|
+
diagnostic.severity
|
|
97
|
+
is DiagnosticSeverity.ERROR
|
|
98
|
+
for diagnostic in self._diagnostics
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def __len__(
|
|
103
|
+
self,
|
|
104
|
+
) -> int:
|
|
105
|
+
return len(
|
|
106
|
+
self._diagnostics
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def __iter__(
|
|
111
|
+
self,
|
|
112
|
+
):
|
|
113
|
+
return iter(
|
|
114
|
+
self._diagnostics
|
|
115
|
+
)
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Runtime Diagnostic model.
|
|
3
|
+
|
|
4
|
+
Runtime Diagnostics describe operational observations.
|
|
5
|
+
|
|
6
|
+
They never modify Runtime state and never redefine
|
|
7
|
+
CKS Core semantics.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
from datetime import UTC, datetime
|
|
14
|
+
from enum import Enum
|
|
15
|
+
from typing import Any
|
|
16
|
+
from uuid import UUID, uuid4
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class DiagnosticSource(str, Enum):
|
|
20
|
+
"""
|
|
21
|
+
Origin of a Diagnostic.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
CORE = "core"
|
|
25
|
+
RUNTIME = "runtime"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class DiagnosticSeverity(str, Enum):
|
|
29
|
+
"""
|
|
30
|
+
Runtime Diagnostic severity.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
INFO = "info"
|
|
34
|
+
WARNING = "warning"
|
|
35
|
+
ERROR = "error"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass(frozen=True, slots=True)
|
|
39
|
+
class Diagnostic:
|
|
40
|
+
"""
|
|
41
|
+
Immutable Runtime Diagnostic.
|
|
42
|
+
|
|
43
|
+
Ownership:
|
|
44
|
+
|
|
45
|
+
- Core Diagnostics belong to CKS Core;
|
|
46
|
+
- Runtime Diagnostics belong to Runtime;
|
|
47
|
+
- Runtime preserves diagnostics without modifying them.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
message: str
|
|
51
|
+
|
|
52
|
+
source: DiagnosticSource
|
|
53
|
+
|
|
54
|
+
severity: DiagnosticSeverity
|
|
55
|
+
|
|
56
|
+
code: str | None = None
|
|
57
|
+
|
|
58
|
+
metadata: dict[str, Any] = field(
|
|
59
|
+
default_factory=dict
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
diagnostic_id: UUID = field(
|
|
63
|
+
default_factory=uuid4
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
created_at: datetime = field(
|
|
67
|
+
default_factory=lambda: datetime.now(UTC)
|
|
68
|
+
)
|
|
File without changes
|
|
File without changes
|
cks_runtime/runtime.py
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Canonical Runtime.
|
|
3
|
+
|
|
4
|
+
SPEC-001 Runtime Overview.
|
|
5
|
+
|
|
6
|
+
Runtime coordinates operational behaviour.
|
|
7
|
+
|
|
8
|
+
Runtime never owns semantics.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from cks_runtime.config import RuntimeConfig
|
|
14
|
+
|
|
15
|
+
from cks_runtime.core_api.interfaces import CoreInterface
|
|
16
|
+
|
|
17
|
+
from cks_runtime.diagnostics.aggregator import (
|
|
18
|
+
DiagnosticAggregator,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
from cks_runtime.session.session_manager import (
|
|
22
|
+
SessionManager,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
from cks_runtime.storage.memory_storage import (
|
|
26
|
+
InMemoryStorage,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
from cks_runtime.storage.storage import (
|
|
30
|
+
RuntimeStorage,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
from cks_runtime.transaction.transaction_manager import (
|
|
34
|
+
TransactionManager,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
from cks_runtime.versioning.version_manager import (
|
|
38
|
+
VersionManager,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class Runtime:
|
|
43
|
+
"""
|
|
44
|
+
Canonical Runtime.
|
|
45
|
+
|
|
46
|
+
Coordinates Runtime subsystems.
|
|
47
|
+
|
|
48
|
+
Ownership:
|
|
49
|
+
|
|
50
|
+
- Sessions;
|
|
51
|
+
- Transactions;
|
|
52
|
+
- Version History;
|
|
53
|
+
- Diagnostics;
|
|
54
|
+
- Storage.
|
|
55
|
+
|
|
56
|
+
Runtime never owns semantic behaviour.
|
|
57
|
+
Semantic behaviour belongs exclusively
|
|
58
|
+
to CKS Core.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
def __init__(
|
|
62
|
+
self,
|
|
63
|
+
*,
|
|
64
|
+
core: CoreInterface | None = None,
|
|
65
|
+
storage: RuntimeStorage | None = None,
|
|
66
|
+
config: RuntimeConfig | None = None,
|
|
67
|
+
) -> None:
|
|
68
|
+
|
|
69
|
+
self.config = config or RuntimeConfig()
|
|
70
|
+
|
|
71
|
+
self.core = core
|
|
72
|
+
|
|
73
|
+
self.storage = (
|
|
74
|
+
storage
|
|
75
|
+
if storage is not None
|
|
76
|
+
else InMemoryStorage()
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
self.sessions = SessionManager()
|
|
80
|
+
|
|
81
|
+
self.transactions = TransactionManager()
|
|
82
|
+
|
|
83
|
+
self.versions = VersionManager()
|
|
84
|
+
|
|
85
|
+
self.diagnostics = DiagnosticAggregator()
|
|
File without changes
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Runtime Session model.
|
|
3
|
+
|
|
4
|
+
A Runtime Session is the fundamental operational
|
|
5
|
+
boundary of CKS Runtime.
|
|
6
|
+
|
|
7
|
+
A Session owns Runtime operational state.
|
|
8
|
+
|
|
9
|
+
A Session never owns semantic meaning, which remains
|
|
10
|
+
the responsibility of CKS Core.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from dataclasses import dataclass, field
|
|
14
|
+
from typing import Any
|
|
15
|
+
from uuid import uuid4
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class RuntimeSession:
|
|
20
|
+
"""
|
|
21
|
+
Represents an isolated Runtime execution context.
|
|
22
|
+
|
|
23
|
+
A Runtime Session owns operational state only.
|
|
24
|
+
|
|
25
|
+
Ownership rules:
|
|
26
|
+
|
|
27
|
+
- exactly one Runtime owns a Session;
|
|
28
|
+
- exactly one Session owns its Runtime state;
|
|
29
|
+
- semantic meaning belongs exclusively to CKS Core.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
knowledge_structure: Any
|
|
33
|
+
|
|
34
|
+
session_id: str = field(
|
|
35
|
+
default_factory=lambda: str(uuid4())
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
metadata: dict[str, Any] = field(
|
|
39
|
+
default_factory=dict
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
diagnostics: list[Any] = field(
|
|
43
|
+
default_factory=list
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
version_history: list[Any] = field(
|
|
47
|
+
default_factory=list
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
active_transaction: Any | None = None
|
|
51
|
+
|
|
52
|
+
closed: bool = False
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def is_active(self) -> bool:
|
|
56
|
+
"""
|
|
57
|
+
Returns True while the Session remains active.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
return not self.closed
|
|
61
|
+
|
|
62
|
+
def close(self) -> None:
|
|
63
|
+
"""
|
|
64
|
+
Close the Runtime Session.
|
|
65
|
+
|
|
66
|
+
Closing a Session ends its operational lifecycle.
|
|
67
|
+
|
|
68
|
+
Lifecycle ownership remains the responsibility of
|
|
69
|
+
SessionManager.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
self.closed = True
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Runtime Session Manager.
|
|
3
|
+
|
|
4
|
+
Owns Runtime Session lifecycle.
|
|
5
|
+
|
|
6
|
+
Responsibilities:
|
|
7
|
+
|
|
8
|
+
- create Sessions;
|
|
9
|
+
- retrieve Sessions;
|
|
10
|
+
- enumerate active Sessions;
|
|
11
|
+
- close Sessions.
|
|
12
|
+
|
|
13
|
+
Does not own:
|
|
14
|
+
|
|
15
|
+
- semantic validation;
|
|
16
|
+
- persistence;
|
|
17
|
+
- transactions;
|
|
18
|
+
- version history.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from typing import Any
|
|
22
|
+
|
|
23
|
+
from .session import RuntimeSession
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class SessionManager:
|
|
27
|
+
"""
|
|
28
|
+
Owns Runtime Session lifecycle.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def __init__(self) -> None:
|
|
32
|
+
self._sessions: dict[str, RuntimeSession] = {}
|
|
33
|
+
|
|
34
|
+
def create_session(
|
|
35
|
+
self,
|
|
36
|
+
knowledge_structure: Any,
|
|
37
|
+
) -> RuntimeSession:
|
|
38
|
+
"""
|
|
39
|
+
Create and register a new Runtime Session.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
session = RuntimeSession(
|
|
43
|
+
knowledge_structure=knowledge_structure,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
self._sessions[
|
|
47
|
+
session.session_id
|
|
48
|
+
] = session
|
|
49
|
+
|
|
50
|
+
return session
|
|
51
|
+
|
|
52
|
+
def get_session(
|
|
53
|
+
self,
|
|
54
|
+
session_id: str,
|
|
55
|
+
) -> RuntimeSession | None:
|
|
56
|
+
"""
|
|
57
|
+
Return a Runtime Session by identifier.
|
|
58
|
+
|
|
59
|
+
Returns None if the Session does not exist.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
return self._sessions.get(
|
|
63
|
+
session_id,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
def list_sessions(
|
|
67
|
+
self,
|
|
68
|
+
) -> list[RuntimeSession]:
|
|
69
|
+
"""
|
|
70
|
+
Return all currently active Runtime Sessions.
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
return list(
|
|
74
|
+
self._sessions.values(),
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
def close_session(
|
|
78
|
+
self,
|
|
79
|
+
session_id: str,
|
|
80
|
+
) -> None:
|
|
81
|
+
"""
|
|
82
|
+
Close and unregister a Runtime Session.
|
|
83
|
+
|
|
84
|
+
Unknown Session identifiers are ignored.
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
session = self._sessions.get(
|
|
88
|
+
session_id,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
if session is None:
|
|
92
|
+
return
|
|
93
|
+
|
|
94
|
+
session.close()
|
|
95
|
+
|
|
96
|
+
del self._sessions[
|
|
97
|
+
session_id
|
|
98
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Storage exceptions.
|
|
3
|
+
|
|
4
|
+
SPEC-006 Storage
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class StorageError(Exception):
|
|
11
|
+
"""
|
|
12
|
+
Base Runtime Storage exception.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class SessionNotFound(StorageError):
|
|
17
|
+
"""
|
|
18
|
+
Requested Runtime Session does not exist.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, session_id: str):
|
|
22
|
+
super().__init__(
|
|
23
|
+
f"Runtime Session '{session_id}' was not found."
|
|
24
|
+
)
|
|
25
|
+
self.session_id = session_id
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class VersionNotFound(StorageError):
|
|
29
|
+
"""
|
|
30
|
+
Requested Runtime Version does not exist.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, version_id: str):
|
|
34
|
+
super().__init__(
|
|
35
|
+
f"Runtime Version '{version_id}' was not found."
|
|
36
|
+
)
|
|
37
|
+
self.version_id = version_id
|