destiny_sdk 0.3.0a0__tar.gz → 0.4.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.
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/PKG-INFO +1 -1
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/pyproject.toml +1 -1
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/src/destiny_sdk/client.py +50 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/src/destiny_sdk/imports.py +6 -15
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/src/destiny_sdk/robots.py +114 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/tests/unit/test_client.py +20 -13
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/uv.lock +1 -1
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/.gitignore +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/LICENSE +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/README.md +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/src/destiny_sdk/__init__.py +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/src/destiny_sdk/auth.py +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/src/destiny_sdk/core.py +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/src/destiny_sdk/enhancements.py +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/src/destiny_sdk/identifiers.py +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/src/destiny_sdk/parsers/__init__.py +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/src/destiny_sdk/parsers/eppi_parser.py +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/src/destiny_sdk/py.typed +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/src/destiny_sdk/references.py +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/src/destiny_sdk/visibility.py +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/tests/unit/__init__.py +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/tests/unit/conftest.py +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/tests/unit/parsers/test_eppi_parser.py +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/tests/unit/test_auth.py +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/tests/unit/test_data/eppi_import.jsonl +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/tests/unit/test_data/eppi_import_with_annotations.jsonl +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/tests/unit/test_data/eppi_report.json +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/tests/unit/test_enhancements.py +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/tests/unit/test_identifiers.py +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/tests/unit/test_references.py +0 -0
- {destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/tests/unit/test_robots.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: destiny_sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: A software development kit (sdk) to support interaction with the DESTINY repository
|
|
5
5
|
Author-email: Adam Hamilton <adam@futureevidence.org>, Andrew Harvey <andrew@futureevidence.org>, Daniel Breves <daniel@futureevidence.org>, Jack Walmisley <jack@futureevidence.org>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -8,6 +8,9 @@ from pydantic import UUID4, HttpUrl
|
|
|
8
8
|
|
|
9
9
|
from destiny_sdk.robots import (
|
|
10
10
|
EnhancementRequestRead,
|
|
11
|
+
RobotEnhancementBatch,
|
|
12
|
+
RobotEnhancementBatchRead,
|
|
13
|
+
RobotEnhancementBatchResult,
|
|
11
14
|
RobotResult,
|
|
12
15
|
)
|
|
13
16
|
|
|
@@ -89,3 +92,50 @@ class Client:
|
|
|
89
92
|
)
|
|
90
93
|
response.raise_for_status()
|
|
91
94
|
return EnhancementRequestRead.model_validate(response.json())
|
|
95
|
+
|
|
96
|
+
def send_robot_enhancement_batch_result(
|
|
97
|
+
self, robot_enhancement_batch_result: RobotEnhancementBatchResult
|
|
98
|
+
) -> RobotEnhancementBatchRead:
|
|
99
|
+
"""
|
|
100
|
+
Send a RobotEnhancementBatchResult to destiny repository.
|
|
101
|
+
|
|
102
|
+
Signs the request with the client's secret key.
|
|
103
|
+
|
|
104
|
+
:param robot_enhancement_batch_result: The RobotEnhancementBatchResult to send
|
|
105
|
+
:type robot_enhancement_batch_result: RobotEnhancementBatchResult
|
|
106
|
+
:return: The RobotEnhancementBatchRead object from the response.
|
|
107
|
+
:rtype: RobotEnhancementBatchRead
|
|
108
|
+
"""
|
|
109
|
+
response = self.session.post(
|
|
110
|
+
f"/robot-enhancement-batches/{robot_enhancement_batch_result.request_id}/results/",
|
|
111
|
+
json=robot_enhancement_batch_result.model_dump(mode="json"),
|
|
112
|
+
)
|
|
113
|
+
response.raise_for_status()
|
|
114
|
+
return RobotEnhancementBatchRead.model_validate(response.json())
|
|
115
|
+
|
|
116
|
+
def poll_robot_enhancement_batch(
|
|
117
|
+
self, robot_id: UUID4, limit: int = 10
|
|
118
|
+
) -> RobotEnhancementBatch | None:
|
|
119
|
+
"""
|
|
120
|
+
Poll for a robot enhancement batch.
|
|
121
|
+
|
|
122
|
+
Signs the request with the client's secret key.
|
|
123
|
+
|
|
124
|
+
:param robot_id: The ID of the robot to poll for
|
|
125
|
+
:type robot_id: UUID4
|
|
126
|
+
:param limit: The maximum number of pending enhancements to return
|
|
127
|
+
:type limit: int
|
|
128
|
+
:return: The RobotEnhancementBatch object from the response, or None if no
|
|
129
|
+
batches available
|
|
130
|
+
:rtype: RobotEnhancementBatch | None
|
|
131
|
+
"""
|
|
132
|
+
response = self.session.post(
|
|
133
|
+
"/robot-enhancement-batches/",
|
|
134
|
+
params={"robot_id": str(robot_id), "limit": limit},
|
|
135
|
+
)
|
|
136
|
+
# HTTP 204 No Content indicates no batches available
|
|
137
|
+
if response.status_code == httpx.codes.NO_CONTENT:
|
|
138
|
+
return None
|
|
139
|
+
|
|
140
|
+
response.raise_for_status()
|
|
141
|
+
return RobotEnhancementBatch.model_validate(response.json())
|
|
@@ -19,13 +19,11 @@ class ImportRecordStatus(StrEnum):
|
|
|
19
19
|
- `created`: Created, but no processing has started.
|
|
20
20
|
- `started`: Processing has started on the batch.
|
|
21
21
|
- `completed`: Processing has been completed.
|
|
22
|
-
- `cancelled`: Processing was cancelled by calling the API.
|
|
23
22
|
"""
|
|
24
23
|
|
|
25
24
|
CREATED = auto()
|
|
26
25
|
STARTED = auto()
|
|
27
26
|
COMPLETED = auto()
|
|
28
|
-
CANCELLED = auto()
|
|
29
27
|
|
|
30
28
|
|
|
31
29
|
class ImportBatchStatus(StrEnum):
|
|
@@ -35,21 +33,15 @@ class ImportBatchStatus(StrEnum):
|
|
|
35
33
|
- `created`: Created, but no processing has started.
|
|
36
34
|
- `started`: Processing has started on the batch.
|
|
37
35
|
- `failed`: Processing has failed.
|
|
38
|
-
- `
|
|
39
|
-
- `indexing`: The imports have been saved and are being indexed.
|
|
40
|
-
- `indexing_failed`: The imports have been saved but were not indexed.
|
|
36
|
+
- `partially_failed`: Some references succeeded while others failed.
|
|
41
37
|
- `completed`: Processing has been completed.
|
|
42
|
-
- `cancelled`: Processing was cancelled by calling the API.
|
|
43
38
|
"""
|
|
44
39
|
|
|
45
40
|
CREATED = auto()
|
|
46
41
|
STARTED = auto()
|
|
47
|
-
RETRYING = auto()
|
|
48
42
|
FAILED = auto()
|
|
49
|
-
|
|
50
|
-
INDEXING_FAILED = auto()
|
|
43
|
+
PARTIALLY_FAILED = auto()
|
|
51
44
|
COMPLETED = auto()
|
|
52
|
-
CANCELLED = auto()
|
|
53
45
|
|
|
54
46
|
|
|
55
47
|
class CollisionStrategy(StrEnum):
|
|
@@ -96,15 +88,15 @@ class ImportResultStatus(StrEnum):
|
|
|
96
88
|
more information.
|
|
97
89
|
- `failed`: The reference failed to be created. See the result's `failure_details`
|
|
98
90
|
field for more information.
|
|
99
|
-
- `
|
|
91
|
+
- `retrying`: Processing has failed, but is being retried.
|
|
100
92
|
"""
|
|
101
93
|
|
|
102
94
|
CREATED = auto()
|
|
103
95
|
STARTED = auto()
|
|
104
96
|
COMPLETED = auto()
|
|
105
|
-
CANCELLED = auto()
|
|
106
97
|
PARTIALLY_FAILED = auto()
|
|
107
98
|
FAILED = auto()
|
|
99
|
+
RETRYING = auto()
|
|
108
100
|
|
|
109
101
|
|
|
110
102
|
class _ImportRecordBase(BaseModel):
|
|
@@ -186,9 +178,8 @@ with each line formatted according to
|
|
|
186
178
|
)
|
|
187
179
|
callback_url: HttpUrl | None = Field(
|
|
188
180
|
default=None,
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
""",
|
|
181
|
+
deprecated=True,
|
|
182
|
+
description="This field is currently a no-op.",
|
|
192
183
|
)
|
|
193
184
|
|
|
194
185
|
|
|
@@ -52,6 +52,23 @@ None, the repository will assume that the result file is ready for processing.
|
|
|
52
52
|
)
|
|
53
53
|
|
|
54
54
|
|
|
55
|
+
class RobotEnhancementBatchResult(BaseModel):
|
|
56
|
+
"""Used to indicate that the robot has finished processing a batch."""
|
|
57
|
+
|
|
58
|
+
request_id: UUID4
|
|
59
|
+
error: RobotError | None = Field(
|
|
60
|
+
default=None,
|
|
61
|
+
description="""
|
|
62
|
+
Error the robot encountered while creating enhancements. If this field is populated,
|
|
63
|
+
we assume the entire robot enhancement batch failed,
|
|
64
|
+
rather than an individual reference.
|
|
65
|
+
If there was an error with processing an individual reference, it should be passed in
|
|
66
|
+
the result file and this field should be left as None. Vice-versa, if this field is
|
|
67
|
+
None, the repository will assume that the result file is ready for processing.
|
|
68
|
+
""",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
55
72
|
class RobotResultValidationEntry(_JsonlFileInputMixIn, BaseModel):
|
|
56
73
|
"""A single entry in the validation result file for a batch enhancement request."""
|
|
57
74
|
|
|
@@ -110,6 +127,37 @@ If the URL expires, a new one can be generated using
|
|
|
110
127
|
)
|
|
111
128
|
|
|
112
129
|
|
|
130
|
+
class RobotEnhancementBatch(BaseModel):
|
|
131
|
+
"""A robot enhancement batch from the repo to a robot."""
|
|
132
|
+
|
|
133
|
+
id: UUID4
|
|
134
|
+
reference_storage_url: HttpUrl = Field(
|
|
135
|
+
description="""
|
|
136
|
+
The URL at which the set of references are stored. The file is a jsonl
|
|
137
|
+
with each line formatted according to
|
|
138
|
+
:class:`Reference <libs.sdk.src.destiny_sdk.references.Reference>`, one
|
|
139
|
+
reference per line.
|
|
140
|
+
Each reference may have identifiers or enhancements attached, as
|
|
141
|
+
required by the robot.
|
|
142
|
+
If the URL expires, a new one can be generated using
|
|
143
|
+
``GET /robot-enhancement-batches/{batch_id}/``.
|
|
144
|
+
"""
|
|
145
|
+
)
|
|
146
|
+
result_storage_url: HttpUrl = Field(
|
|
147
|
+
description="""
|
|
148
|
+
The URL at which the set of enhancements are to be stored. The file is to be a jsonl
|
|
149
|
+
with each line formatted according to
|
|
150
|
+
:class:`EnhancementResultEntry <libs.sdk.src.destiny_sdk.robots.EnhancementResultEntry>`.
|
|
151
|
+
If the URL expires, a new one can be generated using
|
|
152
|
+
``GET /robot-enhancement-batches/{batch_id}/``.
|
|
153
|
+
""" # noqa: E501
|
|
154
|
+
)
|
|
155
|
+
extra_fields: dict | None = Field(
|
|
156
|
+
default=None,
|
|
157
|
+
description="Extra fields to pass to the robot. TBC.",
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
|
|
113
161
|
class EnhancementRequestStatus(StrEnum):
|
|
114
162
|
"""
|
|
115
163
|
The status of an enhancement request.
|
|
@@ -117,6 +165,7 @@ class EnhancementRequestStatus(StrEnum):
|
|
|
117
165
|
**Allowed values**:
|
|
118
166
|
- `received`: Enhancement request has been received by the repo.
|
|
119
167
|
- `accepted`: Enhancement request has been accepted by the robot.
|
|
168
|
+
- `processing`: Enhancement request is being processed by the robot.
|
|
120
169
|
- `rejected`: Enhancement request has been rejected by the robot.
|
|
121
170
|
- `partial_failed`: Some enhancements failed to create.
|
|
122
171
|
- `failed`: All enhancements failed to create.
|
|
@@ -128,6 +177,7 @@ class EnhancementRequestStatus(StrEnum):
|
|
|
128
177
|
|
|
129
178
|
RECEIVED = auto()
|
|
130
179
|
ACCEPTED = auto()
|
|
180
|
+
PROCESSING = auto()
|
|
131
181
|
REJECTED = auto()
|
|
132
182
|
PARTIAL_FAILED = auto()
|
|
133
183
|
FAILED = auto()
|
|
@@ -210,6 +260,70 @@ If the URL expires, a new one can be generated using
|
|
|
210
260
|
)
|
|
211
261
|
|
|
212
262
|
|
|
263
|
+
class _RobotEnhancementBatchBase(BaseModel):
|
|
264
|
+
"""
|
|
265
|
+
Base robot enhancement batch class.
|
|
266
|
+
|
|
267
|
+
A robot enhancement batch is a batch of pending enhancements the robot has picked up
|
|
268
|
+
for processing.
|
|
269
|
+
"""
|
|
270
|
+
|
|
271
|
+
robot_id: UUID4 = Field(
|
|
272
|
+
description="The robot to be used to create the enhancements."
|
|
273
|
+
)
|
|
274
|
+
source: str | None = Field(
|
|
275
|
+
default=None,
|
|
276
|
+
description="The source of the batch enhancement request.",
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
class RobotEnhancementBatchRead(_RobotEnhancementBatchBase):
|
|
281
|
+
"""Core robot enhancement batch class."""
|
|
282
|
+
|
|
283
|
+
id: UUID4
|
|
284
|
+
reference_data_url: HttpUrl | None = Field(
|
|
285
|
+
default=None,
|
|
286
|
+
description="""
|
|
287
|
+
The URL at which the set of references are stored. The file is a jsonl with each line
|
|
288
|
+
formatted according to
|
|
289
|
+
:class:`Reference <libs.sdk.src.destiny_sdk.references.Reference>`.
|
|
290
|
+
, one reference per line.
|
|
291
|
+
Each reference may have identifiers or enhancements attached, as
|
|
292
|
+
required by the robot.
|
|
293
|
+
If the URL expires, a new one can be generated using
|
|
294
|
+
``GET /enhancement-requests/{request_id}/``.
|
|
295
|
+
""",
|
|
296
|
+
)
|
|
297
|
+
result_storage_url: HttpUrl | None = Field(
|
|
298
|
+
default=None,
|
|
299
|
+
description="""
|
|
300
|
+
The URL at which the set of enhancements are stored. The file is to be a jsonl
|
|
301
|
+
with each line formatted according to
|
|
302
|
+
:class:`EnhancementResultEntry <libs.sdk.src.destiny_sdk.robots.EnhancementResultEntry>`.
|
|
303
|
+
This field is only relevant to robots.
|
|
304
|
+
If the URL expires, a new one can be generated using
|
|
305
|
+
``GET /robot-enhancement-batches/{batch_id}/``.
|
|
306
|
+
""", # noqa: E501
|
|
307
|
+
)
|
|
308
|
+
validation_result_url: HttpUrl | None = Field(
|
|
309
|
+
default=None,
|
|
310
|
+
description="""
|
|
311
|
+
The URL at which the result of the enhancement request is stored.
|
|
312
|
+
This file is a txt file, one line per reference, with either an error
|
|
313
|
+
or a success message.
|
|
314
|
+
If the URL expires, a new one can be generated using
|
|
315
|
+
``GET /robot-enhancement-batches/{batch_id}/``.
|
|
316
|
+
""",
|
|
317
|
+
)
|
|
318
|
+
error: str | None = Field(
|
|
319
|
+
default=None,
|
|
320
|
+
description="Error encountered during the enhancement process. This "
|
|
321
|
+
"is only used if the entire enhancement batch failed, rather than an "
|
|
322
|
+
"individual reference. If there was an error with processing an individual "
|
|
323
|
+
"reference, it is passed in the validation result file.",
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
|
|
213
327
|
class _RobotBase(BaseModel):
|
|
214
328
|
"""
|
|
215
329
|
Base Robot class.
|
|
@@ -5,7 +5,12 @@ import uuid
|
|
|
5
5
|
|
|
6
6
|
import pytest
|
|
7
7
|
from destiny_sdk.client import Client, create_signature
|
|
8
|
-
from destiny_sdk.robots import
|
|
8
|
+
from destiny_sdk.robots import (
|
|
9
|
+
RobotEnhancementBatchRead,
|
|
10
|
+
RobotEnhancementBatchResult,
|
|
11
|
+
RobotError,
|
|
12
|
+
)
|
|
13
|
+
from pydantic import HttpUrl
|
|
9
14
|
from pytest_httpx import HTTPXMock
|
|
10
15
|
|
|
11
16
|
|
|
@@ -17,34 +22,36 @@ def frozen_time(monkeypatch):
|
|
|
17
22
|
monkeypatch.setattr(time, "time", frozen_timestamp)
|
|
18
23
|
|
|
19
24
|
|
|
20
|
-
def test_verify_hmac_headers_sent(
|
|
21
|
-
|
|
25
|
+
def test_verify_hmac_headers_sent(
|
|
26
|
+
httpx_mock: HTTPXMock,
|
|
27
|
+
frozen_time, # noqa: ARG001
|
|
28
|
+
) -> None:
|
|
29
|
+
"""Test that robot enhancement batch result request is authorized."""
|
|
22
30
|
fake_secret_key = "asdfhjgji94523q0uflsjf349wjilsfjd9q23"
|
|
23
31
|
fake_robot_id = uuid.uuid4()
|
|
24
32
|
fake_destiny_repository_url = "https://www.destiny-repository-lives-here.co.au/v1"
|
|
25
33
|
|
|
26
|
-
|
|
34
|
+
fake_batch_result = RobotEnhancementBatchResult(
|
|
27
35
|
request_id=uuid.uuid4(), error=RobotError(message="Cannot process this batch")
|
|
28
36
|
)
|
|
29
37
|
|
|
30
|
-
expected_response_body =
|
|
31
|
-
reference_ids=[uuid.uuid4()],
|
|
38
|
+
expected_response_body = RobotEnhancementBatchRead(
|
|
32
39
|
id=uuid.uuid4(),
|
|
33
40
|
robot_id=uuid.uuid4(),
|
|
34
|
-
|
|
41
|
+
error="Cannot process this batch",
|
|
35
42
|
)
|
|
36
43
|
|
|
37
44
|
expected_signature = create_signature(
|
|
38
45
|
secret_key=fake_secret_key,
|
|
39
|
-
request_body=
|
|
46
|
+
request_body=fake_batch_result.model_dump_json().encode(),
|
|
40
47
|
client_id=fake_robot_id,
|
|
41
48
|
timestamp=time.time(),
|
|
42
49
|
)
|
|
43
50
|
|
|
44
51
|
httpx_mock.add_response(
|
|
45
52
|
url=fake_destiny_repository_url
|
|
46
|
-
+ "/enhancement-
|
|
47
|
-
+ f"{
|
|
53
|
+
+ "/robot-enhancement-batches/"
|
|
54
|
+
+ f"{fake_batch_result.request_id}/results/",
|
|
48
55
|
method="POST",
|
|
49
56
|
match_headers={
|
|
50
57
|
"Authorization": f"Signature {expected_signature}",
|
|
@@ -55,11 +62,11 @@ def test_verify_hmac_headers_sent(httpx_mock: HTTPXMock, frozen_time) -> None:
|
|
|
55
62
|
)
|
|
56
63
|
|
|
57
64
|
Client(
|
|
58
|
-
base_url=fake_destiny_repository_url,
|
|
65
|
+
base_url=HttpUrl(fake_destiny_repository_url),
|
|
59
66
|
secret_key=fake_secret_key,
|
|
60
67
|
client_id=fake_robot_id,
|
|
61
|
-
).
|
|
62
|
-
|
|
68
|
+
).send_robot_enhancement_batch_result(
|
|
69
|
+
robot_enhancement_batch_result=fake_batch_result,
|
|
63
70
|
)
|
|
64
71
|
|
|
65
72
|
callback_request = httpx_mock.get_requests()
|
|
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
|
{destiny_sdk-0.3.0a0 → destiny_sdk-0.4.1}/tests/unit/test_data/eppi_import_with_annotations.jsonl
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|