spot-sdk-python 2.1.0b2__tar.gz → 2.1.1__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.
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/PKG-INFO +1 -1
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/pyproject.toml +1 -1
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/pyproject.toml.orig +1 -1
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/hosting.py +17 -8
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/testing/container.py +10 -10
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/README.md +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/__init__.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/_json.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/app.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/artifacts.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/clients.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/config.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/correlation.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/email.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/errors.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/knowledge.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/knowledge_tags.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/llm.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/logging.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/manifest.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/mime.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/model_input.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/orchestrator.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/proxy.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/py.typed +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/retriever.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/settings.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/signals.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/testing/README.md +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/testing/__init__.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/testing/contract.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/testing/corpus.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/testing/engine.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/testing/fake_knowledge_client.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/testing/fake_llm.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/testing/fake_spot.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/testing/metrics.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/testing/report.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/testing/settings.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/testing/views.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/urls.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/verdict.py +0 -0
- {spot_sdk_python-2.1.0b2 → spot_sdk_python-2.1.1}/spot_sdk/workflow.py +0 -0
|
@@ -44,7 +44,11 @@ could expand past the bound once decoded."""
|
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
class AnswerRefusedError(Exception):
|
|
47
|
-
"""A plugin's answer that is not read: encoded, or longer than
|
|
47
|
+
"""A plugin's answer that is not read: encoded, or longer than its bound."""
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class AnswerTooLargeError(AnswerRefusedError):
|
|
51
|
+
"""An answer longer than its bound, which a caller may treat apart from an encoded one."""
|
|
48
52
|
|
|
49
53
|
|
|
50
54
|
class InvalidResponseError(Exception):
|
|
@@ -53,8 +57,10 @@ class InvalidResponseError(Exception):
|
|
|
53
57
|
|
|
54
58
|
def isolated(egress: Egress | None) -> bool:
|
|
55
59
|
"""Whether a plugin of this egress class runs on a network without a route
|
|
56
|
-
out: class
|
|
57
|
-
|
|
60
|
+
out: every class, from SPOT 2.1 (spot/spot#148). A plugin reaches the
|
|
61
|
+
hosts its settings of type url name, through SPOT's egress gateway, and
|
|
62
|
+
nothing else: its class says what it sends out, not where it runs."""
|
|
63
|
+
return True
|
|
58
64
|
|
|
59
65
|
|
|
60
66
|
def limits(resources: Resources) -> dict[str, Any]:
|
|
@@ -119,11 +125,14 @@ def secrets_archive(secrets: Mapping[str, str]) -> bytes:
|
|
|
119
125
|
return buffer.getvalue()
|
|
120
126
|
|
|
121
127
|
|
|
122
|
-
async def read_answer(
|
|
123
|
-
|
|
128
|
+
async def read_answer(
|
|
129
|
+
response: httpx2.Response, max_bytes: int = MAX_ANSWER_BYTES
|
|
130
|
+
) -> bytes:
|
|
131
|
+
"""A streamed answer's body, as sent, read up to ``max_bytes``.
|
|
124
132
|
|
|
125
133
|
Raises:
|
|
126
|
-
AnswerRefusedError: the answer is encoded
|
|
134
|
+
AnswerRefusedError: the answer is encoded
|
|
135
|
+
AnswerTooLargeError: the answer is longer than ``max_bytes``
|
|
127
136
|
"""
|
|
128
137
|
if (
|
|
129
138
|
response.headers.get("content-encoding", "identity").strip().lower()
|
|
@@ -133,8 +142,8 @@ async def read_answer(response: httpx2.Response) -> bytes:
|
|
|
133
142
|
body = bytearray()
|
|
134
143
|
async for chunk in response.aiter_raw():
|
|
135
144
|
body += chunk
|
|
136
|
-
if len(body) >
|
|
137
|
-
raise
|
|
145
|
+
if len(body) > max_bytes:
|
|
146
|
+
raise AnswerTooLargeError(f"response too large: over {max_bytes} bytes")
|
|
138
147
|
return bytes(body)
|
|
139
148
|
|
|
140
149
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"""A plugin's image run as SPOT runs it, and checked: ``run_plugin_test``.
|
|
2
2
|
|
|
3
3
|
The engine runs in a container that reaches the Docker daemon: spot-cli's
|
|
4
|
-
image, given the socket. For each run it creates a network
|
|
5
|
-
out
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
image, given the socket. For each run it creates a network without a route
|
|
5
|
+
out, as SPOT runs every plugin (``isolated``), and joins it under SPOT's
|
|
6
|
+
names, so that the plugin reaches the fake SPOT where it reaches SPOT. The
|
|
7
|
+
plugin's container gets the plugin-manager's options and limits, a new token
|
|
8
|
+
and its secret settings as files (``spot_sdk.hosting``). The network and the
|
|
9
|
+
container carry the label ``spot.test.run=<run>``, by which the run removes
|
|
10
|
+
them when it ends, however it ends: even one the daemon made while the call
|
|
11
|
+
that asked for it failed. The image is never pulled.
|
|
12
12
|
Needs the ``testing`` extra: ``pip install "spot-sdk-python[testing]"``.
|
|
13
13
|
"""
|
|
14
14
|
|
|
@@ -93,8 +93,8 @@ def run_plugin_test(
|
|
|
93
93
|
"""Run the plugin's image as SPOT runs it, against ``corpus``, and report.
|
|
94
94
|
|
|
95
95
|
It runs in a container that reaches the Docker daemon: spot-cli's image,
|
|
96
|
-
given the socket. It creates the plugin's network (internal for
|
|
97
|
-
|
|
96
|
+
given the socket. It creates the plugin's network (internal, as for every
|
|
97
|
+
plugin), joins it as SPOT's services, starts the plugin with the
|
|
98
98
|
plugin-manager's options, its limits, a new token and its secrets as
|
|
99
99
|
files, serves the fake SPOT, runs the checks and removes what it
|
|
100
100
|
created, whatever happens.
|
|
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
|