destiny_sdk 0.8.0__tar.gz → 0.9.0__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.
Files changed (39) hide show
  1. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/PKG-INFO +3 -3
  2. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/pyproject.toml +3 -3
  3. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/src/destiny_sdk/__init__.py +2 -0
  4. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/src/destiny_sdk/auth.py +8 -7
  5. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/src/destiny_sdk/client.py +11 -9
  6. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/src/destiny_sdk/core.py +8 -2
  7. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/src/destiny_sdk/enhancements.py +5 -5
  8. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/src/destiny_sdk/identifiers.py +12 -8
  9. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/src/destiny_sdk/imports.py +9 -8
  10. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/src/destiny_sdk/references.py +3 -3
  11. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/src/destiny_sdk/robots.py +16 -16
  12. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/tests/unit/test_auth.py +2 -2
  13. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/tests/unit/test_client.py +8 -8
  14. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/tests/unit/test_enhancements.py +12 -12
  15. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/tests/unit/test_identifiers.py +5 -5
  16. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/tests/unit/test_references.py +5 -7
  17. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/tests/unit/test_robots.py +2 -2
  18. destiny_sdk-0.9.0/uv.lock +945 -0
  19. destiny_sdk-0.8.0/uv.lock +0 -825
  20. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/.gitignore +0 -0
  21. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/LICENSE +0 -0
  22. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/README.md +0 -0
  23. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/src/destiny_sdk/labs/__init__.py +0 -0
  24. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/src/destiny_sdk/labs/references.py +0 -0
  25. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/src/destiny_sdk/parsers/__init__.py +0 -0
  26. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/src/destiny_sdk/parsers/eppi_parser.py +0 -0
  27. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/src/destiny_sdk/parsers/exceptions.py +0 -0
  28. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/src/destiny_sdk/py.typed +0 -0
  29. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/src/destiny_sdk/search.py +0 -0
  30. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/src/destiny_sdk/visibility.py +0 -0
  31. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/tests/unit/__init__.py +0 -0
  32. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/tests/unit/conftest.py +0 -0
  33. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/tests/unit/labs/test_references.py +0 -0
  34. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/tests/unit/parsers/test_eppi_parser.py +0 -0
  35. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/tests/unit/test_data/destiny_references.jsonl +0 -0
  36. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/tests/unit/test_data/eppi_import.jsonl +0 -0
  37. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/tests/unit/test_data/eppi_import_with_annotations.jsonl +0 -0
  38. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/tests/unit/test_data/eppi_import_with_raw.jsonl +0 -0
  39. {destiny_sdk-0.8.0 → destiny_sdk-0.9.0}/tests/unit/test_data/eppi_report.json +0 -0
@@ -1,16 +1,16 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: destiny_sdk
3
- Version: 0.8.0
3
+ Version: 0.9.0
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>, Tim Repke <tim.repke@pik-potsdam.de>
6
6
  License-Expression: Apache-2.0
7
7
  License-File: LICENSE
8
8
  Requires-Python: <4,>=3.12
9
9
  Requires-Dist: cachetools<6,>=5.5.2
10
- Requires-Dist: fastapi<0.116,>=0.115.12
10
+ Requires-Dist: fastapi>=0.119.1
11
11
  Requires-Dist: httpx<0.29,>=0.28.1
12
12
  Requires-Dist: msal>=1.34.0
13
- Requires-Dist: pydantic<3,>=2.11.3
13
+ Requires-Dist: pydantic<3,>=2.12.5
14
14
  Requires-Dist: python-jose<4,>=3.4.0
15
15
  Provides-Extra: labs
16
16
  Description-Content-Type: text/markdown
@@ -24,10 +24,10 @@ authors = [
24
24
  ]
25
25
  dependencies = [
26
26
  "cachetools>=5.5.2,<6",
27
- "fastapi>=0.115.12,<0.116",
27
+ "fastapi>=0.119.1",
28
28
  "httpx>=0.28.1,<0.29",
29
29
  "msal>=1.34.0",
30
- "pydantic>=2.11.3,<3",
30
+ "pydantic>=2.12.5,<3",
31
31
  "python-jose>=3.4.0,<4",
32
32
  ]
33
33
  description = "A software development kit (sdk) to support interaction with the DESTINY repository"
@@ -35,7 +35,7 @@ license = "Apache-2.0"
35
35
  name = "destiny_sdk"
36
36
  readme = "README.md"
37
37
  requires-python = ">=3.12, <4"
38
- version = "0.8.0"
38
+ version = "0.9.0"
39
39
 
40
40
  [project.optional-dependencies]
41
41
  labs = []
@@ -11,8 +11,10 @@ from . import (
11
11
  search,
12
12
  visibility,
13
13
  )
14
+ from .core import UUID
14
15
 
15
16
  __all__ = [
17
+ "UUID",
16
18
  "auth",
17
19
  "client",
18
20
  "enhancements",
@@ -4,10 +4,11 @@ import hashlib
4
4
  import hmac
5
5
  import time
6
6
  from typing import Protocol, Self
7
- from uuid import UUID
8
7
 
9
8
  from fastapi import HTTPException, Request, status
10
- from pydantic import UUID4, BaseModel
9
+ from pydantic import BaseModel, TypeAdapter
10
+
11
+ from destiny_sdk.core import UUID
11
12
 
12
13
  FIVE_MINUTES = 60 * 5
13
14
 
@@ -29,7 +30,7 @@ class AuthException(HTTPException):
29
30
 
30
31
 
31
32
  def create_signature(
32
- secret_key: str, request_body: bytes, client_id: UUID4, timestamp: float
33
+ secret_key: str, request_body: bytes, client_id: UUID, timestamp: float
33
34
  ) -> str:
34
35
  """
35
36
  Create an HMAC signature using SHA256.
@@ -39,7 +40,7 @@ def create_signature(
39
40
  :param request_body: request body to be encrypted
40
41
  :type request_body: bytes
41
42
  :param client_id: client id to include in hmac
42
- :type: UUID4
43
+ :type: UUID
43
44
  :param timestamp: timestamp for when the request is sent
44
45
  :type: float
45
46
  :return: encrypted hexdigest of the request body with the secret key
@@ -64,7 +65,7 @@ class HMACAuthorizationHeaders(BaseModel):
64
65
  """
65
66
 
66
67
  signature: str
67
- client_id: UUID4
68
+ client_id: UUID
68
69
  timestamp: float
69
70
 
70
71
  @classmethod
@@ -108,11 +109,11 @@ class HMACAuthorizationHeaders(BaseModel):
108
109
  )
109
110
 
110
111
  try:
111
- UUID(client_id)
112
+ TypeAdapter(UUID).validate_python(client_id)
112
113
  except (ValueError, TypeError) as exc:
113
114
  raise AuthException(
114
115
  status_code=status.HTTP_401_UNAUTHORIZED,
115
- detail="Invalid format for client id, expected UUID4.",
116
+ detail="Invalid format for client id, expected UUIDv4 or UUIDv7.",
116
117
  ) from exc
117
118
 
118
119
  timestamp = request.headers.get("X-Request-Timestamp")
@@ -11,10 +11,10 @@ from msal import (
11
11
  PublicClientApplication,
12
12
  UserAssignedManagedIdentity,
13
13
  )
14
- from pydantic import UUID4, HttpUrl, TypeAdapter
14
+ from pydantic import HttpUrl, TypeAdapter
15
15
 
16
16
  from destiny_sdk.auth import create_signature
17
- from destiny_sdk.core import sdk_version
17
+ from destiny_sdk.core import UUID, sdk_version
18
18
  from destiny_sdk.identifiers import IdentifierLookup
19
19
  from destiny_sdk.references import Reference, ReferenceSearchResult
20
20
  from destiny_sdk.robots import (
@@ -35,7 +35,7 @@ class HMACSigningAuth(httpx.Auth):
35
35
 
36
36
  requires_request_body = True
37
37
 
38
- def __init__(self, secret_key: str, client_id: UUID4) -> None:
38
+ def __init__(self, secret_key: str, client_id: UUID) -> None:
39
39
  """
40
40
  Initialize the client.
41
41
 
@@ -73,14 +73,16 @@ class RobotClient:
73
73
  Current implementation only supports robot results.
74
74
  """
75
75
 
76
- def __init__(self, base_url: HttpUrl, secret_key: str, client_id: UUID4) -> None:
76
+ def __init__(self, base_url: HttpUrl, secret_key: str, client_id: UUID) -> None:
77
77
  """
78
78
  Initialize the client.
79
79
 
80
80
  :param base_url: The base URL for the Destiny Repository API.
81
81
  :type base_url: HttpUrl
82
82
  :param secret_key: The secret key for signing requests
83
- :type auth_method: str
83
+ :type secret_key: str
84
+ :param client_id: The client ID for signing requests
85
+ :type client_id: UUID
84
86
  """
85
87
  self.session = httpx.Client(
86
88
  base_url=str(base_url).removesuffix("/").removesuffix("/v1") + "/v1",
@@ -131,7 +133,7 @@ class RobotClient:
131
133
 
132
134
  def poll_robot_enhancement_batch(
133
135
  self,
134
- robot_id: UUID4,
136
+ robot_id: UUID,
135
137
  limit: int = 10,
136
138
  lease: str | None = None,
137
139
  timeout: int = 60,
@@ -142,7 +144,7 @@ class RobotClient:
142
144
  Signs the request with the client's secret key.
143
145
 
144
146
  :param robot_id: The ID of the robot to poll for
145
- :type robot_id: UUID4
147
+ :type robot_id: UUID
146
148
  :param limit: The maximum number of pending enhancements to return
147
149
  :type limit: int
148
150
  :param lease: The duration to lease the pending enhancements for,
@@ -169,7 +171,7 @@ class RobotClient:
169
171
  return RobotEnhancementBatch.model_validate(response.json())
170
172
 
171
173
  def renew_robot_enhancement_batch_lease(
172
- self, robot_enhancement_batch_id: UUID4, lease_duration: str | None = None
174
+ self, robot_enhancement_batch_id: UUID, lease_duration: str | None = None
173
175
  ) -> None:
174
176
  """
175
177
  Renew the lease for a robot enhancement batch.
@@ -177,7 +179,7 @@ class RobotClient:
177
179
  Signs the request with the client's secret key.
178
180
 
179
181
  :param robot_enhancement_batch_id: The ID of the robot enhancement batch
180
- :type robot_enhancement_batch_id: UUID4
182
+ :type robot_enhancement_batch_id: UUID
181
183
  :param lease_duration: The duration to lease the pending enhancements for,
182
184
  in ISO 8601 duration format eg PT10M. If not provided the repository will
183
185
  use a default lease duration.
@@ -1,9 +1,9 @@
1
1
  """Core classes for the Destiny SDK, not exposed to package users."""
2
2
 
3
3
  from importlib.metadata import PackageNotFoundError, version
4
- from typing import Self
4
+ from typing import Annotated, Self
5
5
 
6
- from pydantic import BaseModel, Field
6
+ from pydantic import UUID4, UUID7, BaseModel, Field
7
7
 
8
8
  from destiny_sdk.search import SearchResultPage, SearchResultTotal
9
9
 
@@ -67,3 +67,9 @@ class SearchResultMixIn(BaseModel):
67
67
  page: SearchResultPage = Field(
68
68
  description="Information about the page of results.",
69
69
  )
70
+
71
+
72
+ UUID = Annotated[
73
+ UUID4 | UUID7,
74
+ Field(description="A DESTINY UUID, which can be either UUID4 or UUID7."),
75
+ ]
@@ -5,9 +5,9 @@ import json
5
5
  from enum import StrEnum, auto
6
6
  from typing import Annotated, Any, Literal, Self
7
7
 
8
- from pydantic import UUID4, BaseModel, Field, HttpUrl, field_validator, model_validator
8
+ from pydantic import BaseModel, Field, HttpUrl, field_validator, model_validator
9
9
 
10
- from destiny_sdk.core import _JsonlFileInputMixIn
10
+ from destiny_sdk.core import UUID, _JsonlFileInputMixIn
11
11
  from destiny_sdk.identifiers import Identifier
12
12
  from destiny_sdk.visibility import Visibility
13
13
 
@@ -524,7 +524,7 @@ EnhancementContent = Annotated[
524
524
  class Enhancement(_JsonlFileInputMixIn, BaseModel):
525
525
  """Core enhancement class."""
526
526
 
527
- id: UUID4 | None = Field(
527
+ id: UUID | None = Field(
528
528
  default=None,
529
529
  description=(
530
530
  "The ID of the enhancement. "
@@ -532,7 +532,7 @@ class Enhancement(_JsonlFileInputMixIn, BaseModel):
532
532
  ),
533
533
  )
534
534
 
535
- reference_id: UUID4 = Field(
535
+ reference_id: UUID = Field(
536
536
  description="The ID of the reference this enhancement is associated with."
537
537
  )
538
538
  source: str = Field(
@@ -545,7 +545,7 @@ class Enhancement(_JsonlFileInputMixIn, BaseModel):
545
545
  default=None,
546
546
  description="The version of the robot that generated the content.",
547
547
  )
548
- derived_from: list[UUID4] | None = Field(
548
+ derived_from: list[UUID] | None = Field(
549
549
  default=None,
550
550
  description="List of enhancement IDs that this enhancement was derived from.",
551
551
  )
@@ -6,7 +6,9 @@ import uuid
6
6
  from enum import StrEnum, auto
7
7
  from typing import Annotated, Literal, Self
8
8
 
9
- from pydantic import UUID4, BaseModel, Field, PositiveInt, TypeAdapter, field_validator
9
+ from pydantic import BaseModel, Field, PositiveInt, TypeAdapter, field_validator
10
+
11
+ from .core import UUID
10
12
 
11
13
  # Case-insensitive patterns for DOI URL prefix stripping
12
14
  _DOI_URL_PREFIX_RE = re.compile(r"^(?:https?://)?(?:dx\.)?doi\.org/", re.IGNORECASE)
@@ -205,7 +207,7 @@ ExternalIdentifier = Annotated[
205
207
  ]
206
208
 
207
209
  #: Any identifier including external identifiers and repository UUID4s.
208
- Identifier = Annotated[ExternalIdentifier | UUID4, Field()]
210
+ Identifier = Annotated[ExternalIdentifier | UUID, Field()]
209
211
 
210
212
  ExternalIdentifierAdapter: TypeAdapter[ExternalIdentifier] = TypeAdapter(
211
213
  ExternalIdentifier
@@ -219,7 +221,7 @@ class LinkedExternalIdentifier(BaseModel):
219
221
  description="The identifier of the reference.",
220
222
  discriminator="identifier_type",
221
223
  )
222
- reference_id: UUID4 = Field(
224
+ reference_id: UUID = Field(
223
225
  description="The ID of the reference this identifier identifies."
224
226
  )
225
227
 
@@ -250,11 +252,11 @@ class IdentifierLookup(BaseModel):
250
252
  """Parse an identifier string into an IdentifierLookup."""
251
253
  if delimiter not in identifier_lookup_string:
252
254
  try:
253
- UUID4(identifier_lookup_string)
255
+ TypeAdapter(UUID).validate_python(identifier_lookup_string)
254
256
  except ValueError as exc:
255
257
  msg = (
256
258
  f"Invalid identifier lookup string: {identifier_lookup_string}. "
257
- "Must be UUIDv4 if no identifier type is specified."
259
+ "Must be UUID if no identifier type is specified."
258
260
  )
259
261
  raise ValueError(msg) from exc
260
262
  return cls(
@@ -288,7 +290,9 @@ class IdentifierLookup(BaseModel):
288
290
 
289
291
  @classmethod
290
292
  def from_identifier(cls, identifier: Identifier) -> Self:
291
- """Create an IdentifierLookup from an ExternalIdentifier or UUID4."""
293
+ """Create an IdentifierLookup from an ExternalIdentifier or UUID."""
294
+ # Use stdlib uuid here as we can't use Annotated types in isinstance checks
295
+ # The UUID versions is already validated per `identifier`
292
296
  if isinstance(identifier, uuid.UUID):
293
297
  return cls(identifier=str(identifier), identifier_type=None)
294
298
  return cls(
@@ -298,9 +302,9 @@ class IdentifierLookup(BaseModel):
298
302
  )
299
303
 
300
304
  def to_identifier(self) -> Identifier:
301
- """Convert into an ExternalIdentifier or UUID4 if it has no identifier_type."""
305
+ """Convert into an ExternalIdentifier or UUID if it has no identifier_type."""
302
306
  if self.identifier_type is None:
303
- return UUID4(self.identifier)
307
+ return TypeAdapter(UUID).validate_python(self.identifier)
304
308
  return ExternalIdentifierAdapter.validate_python(self.model_dump())
305
309
 
306
310
  def __repr__(self) -> str:
@@ -4,13 +4,14 @@ import datetime
4
4
  from enum import StrEnum, auto
5
5
 
6
6
  from pydantic import (
7
- UUID4,
8
7
  BaseModel,
9
8
  Field,
10
9
  HttpUrl,
11
10
  PastDatetime,
12
11
  )
13
12
 
13
+ from .core import UUID
14
+
14
15
 
15
16
  class ImportRecordStatus(StrEnum):
16
17
  """Describes the status of an import record."""
@@ -108,7 +109,7 @@ class ImportRecordIn(_ImportRecordBase):
108
109
  class ImportRecordRead(_ImportRecordBase):
109
110
  """Core import record class."""
110
111
 
111
- id: UUID4 = Field(
112
+ id: UUID = Field(
112
113
  description="The ID of the import record",
113
114
  )
114
115
  status: ImportRecordStatus = Field(
@@ -140,13 +141,13 @@ class ImportBatchIn(_ImportBatchBase):
140
141
  class ImportBatchRead(_ImportBatchBase):
141
142
  """Core import batch class."""
142
143
 
143
- id: UUID4 = Field(
144
+ id: UUID = Field(
144
145
  description="The ID of the import batch",
145
146
  )
146
147
  status: ImportBatchStatus = Field(
147
148
  default=ImportBatchStatus.CREATED, description="The status of the batch."
148
149
  )
149
- import_record_id: UUID4 = Field(
150
+ import_record_id: UUID = Field(
150
151
  description="The ID of the import record this batch is associated with"
151
152
  )
152
153
  import_record: ImportRecordRead | None = Field(
@@ -160,13 +161,13 @@ class ImportBatchRead(_ImportBatchBase):
160
161
  class ImportBatchSummary(_ImportBatchBase):
161
162
  """A view for an import batch that includes a summary of its results."""
162
163
 
163
- id: UUID4 = Field(
164
+ id: UUID = Field(
164
165
  description="""
165
166
  The identifier of the batch.
166
167
  """,
167
168
  )
168
169
 
169
- import_batch_id: UUID4 = Field(description="The ID of the batch being summarised")
170
+ import_batch_id: UUID = Field(description="The ID of the batch being summarised")
170
171
 
171
172
  import_batch_status: ImportBatchStatus = Field(
172
173
  description="The status of the batch being summarised"
@@ -187,8 +188,8 @@ The identifier of the batch.
187
188
  class ImportResultRead(BaseModel):
188
189
  """Core import result class."""
189
190
 
190
- id: UUID4 = Field(description="The ID of the import result.")
191
- reference_id: UUID4 | None = Field(
191
+ id: UUID = Field(description="The ID of the import result.")
192
+ reference_id: UUID | None = Field(
192
193
  default=None,
193
194
  description="The ID of the reference created by this import result.",
194
195
  )
@@ -2,9 +2,9 @@
2
2
 
3
3
  from typing import Self
4
4
 
5
- from pydantic import UUID4, BaseModel, Field, TypeAdapter
5
+ from pydantic import BaseModel, Field, TypeAdapter
6
6
 
7
- from destiny_sdk.core import SearchResultMixIn, _JsonlFileInputMixIn
7
+ from destiny_sdk.core import UUID, SearchResultMixIn, _JsonlFileInputMixIn
8
8
  from destiny_sdk.enhancements import Enhancement, EnhancementFileInput
9
9
  from destiny_sdk.identifiers import ExternalIdentifier
10
10
  from destiny_sdk.visibility import Visibility
@@ -19,7 +19,7 @@ class Reference(_JsonlFileInputMixIn, BaseModel):
19
19
  default=Visibility.PUBLIC,
20
20
  description="The level of visibility of the reference",
21
21
  )
22
- id: UUID4 = Field(
22
+ id: UUID = Field(
23
23
  description="The ID of the reference",
24
24
  )
25
25
  identifiers: list[ExternalIdentifier] | None = Field(
@@ -3,9 +3,9 @@
3
3
  from enum import StrEnum, auto
4
4
  from typing import Annotated, Any
5
5
 
6
- from pydantic import UUID4, BaseModel, ConfigDict, Field, HttpUrl
6
+ from pydantic import BaseModel, ConfigDict, Field, HttpUrl
7
7
 
8
- from destiny_sdk.core import _JsonlFileInputMixIn
8
+ from destiny_sdk.core import UUID, _JsonlFileInputMixIn
9
9
  from destiny_sdk.enhancements import Enhancement
10
10
 
11
11
 
@@ -30,7 +30,7 @@ class LinkedRobotError(_JsonlFileInputMixIn, RobotError):
30
30
  id is derived from the request id.
31
31
  """
32
32
 
33
- reference_id: UUID4 = Field(
33
+ reference_id: UUID = Field(
34
34
  description="The ID of the reference which caused the error."
35
35
  )
36
36
 
@@ -38,7 +38,7 @@ class LinkedRobotError(_JsonlFileInputMixIn, RobotError):
38
38
  class RobotResult(BaseModel):
39
39
  """Used to indicate to the repository that the robot has finished processing."""
40
40
 
41
- request_id: UUID4
41
+ request_id: UUID
42
42
  error: RobotError | None = Field(
43
43
  default=None,
44
44
  description="""
@@ -55,7 +55,7 @@ None, the repository will assume that the result file is ready for processing.
55
55
  class RobotEnhancementBatchResult(BaseModel):
56
56
  """Used to indicate that the robot has finished processing a batch."""
57
57
 
58
- request_id: UUID4
58
+ request_id: UUID
59
59
  error: RobotError | None = Field(
60
60
  default=None,
61
61
  description="""
@@ -72,7 +72,7 @@ None, the repository will assume that the result file is ready for processing.
72
72
  class RobotResultValidationEntry(_JsonlFileInputMixIn, BaseModel):
73
73
  """A single entry in the validation result file for a batch enhancement request."""
74
74
 
75
- reference_id: UUID4 | None = Field(
75
+ reference_id: UUID | None = Field(
76
76
  default=None,
77
77
  description=(
78
78
  "The ID of the reference which was enhanced. "
@@ -99,7 +99,7 @@ EnhancementResultEntry = Annotated[
99
99
  class RobotRequest(BaseModel):
100
100
  """A batch enhancement request from the repo to a robot."""
101
101
 
102
- id: UUID4
102
+ id: UUID
103
103
  reference_storage_url: HttpUrl = Field(
104
104
  description="""
105
105
  The URL at which the set of references are stored. The file is a jsonl
@@ -130,7 +130,7 @@ If the URL expires, a new one can be generated using
130
130
  class RobotEnhancementBatch(BaseModel):
131
131
  """A robot enhancement batch from the repo to a robot."""
132
132
 
133
- id: UUID4
133
+ id: UUID
134
134
  reference_storage_url: HttpUrl = Field(
135
135
  description="""
136
136
  The URL at which the set of references are stored. The file is a jsonl
@@ -190,10 +190,10 @@ class _EnhancementRequestBase(BaseModel):
190
190
  A enhancement request is a request to create one or more enhancements.
191
191
  """
192
192
 
193
- robot_id: UUID4 = Field(
193
+ robot_id: UUID = Field(
194
194
  description="The robot to be used to create the enhancements."
195
195
  )
196
- reference_ids: list[UUID4] = Field(
196
+ reference_ids: list[UUID] = Field(
197
197
  description="The IDs of the references to be enhanced."
198
198
  )
199
199
  source: str | None = Field(
@@ -209,7 +209,7 @@ class EnhancementRequestIn(_EnhancementRequestBase):
209
209
  class EnhancementRequestRead(_EnhancementRequestBase):
210
210
  """Core batch enhancement request class."""
211
211
 
212
- id: UUID4
212
+ id: UUID
213
213
  request_status: EnhancementRequestStatus = Field(
214
214
  description="The status of the request to create enhancements",
215
215
  )
@@ -264,7 +264,7 @@ class _RobotEnhancementBatchBase(BaseModel):
264
264
  for processing.
265
265
  """
266
266
 
267
- robot_id: UUID4 = Field(
267
+ robot_id: UUID = Field(
268
268
  description="The robot to be used to create the enhancements."
269
269
  )
270
270
  source: str | None = Field(
@@ -276,7 +276,7 @@ class _RobotEnhancementBatchBase(BaseModel):
276
276
  class RobotEnhancementBatchRead(_RobotEnhancementBatchBase):
277
277
  """Core robot enhancement batch class."""
278
278
 
279
- id: UUID4
279
+ id: UUID
280
280
  reference_data_url: HttpUrl | None = Field(
281
281
  default=None,
282
282
  description="""
@@ -343,7 +343,7 @@ class RobotIn(_RobotBase):
343
343
  class Robot(_RobotBase):
344
344
  """Then model for a registered robot."""
345
345
 
346
- id: UUID4 = Field(
346
+ id: UUID = Field(
347
347
  description="The id of the robot provided by destiny repository. "
348
348
  "Used as the client_id when sending HMAC authenticated requests."
349
349
  )
@@ -366,7 +366,7 @@ class ProvisionedRobot(Robot):
366
366
  class _RobotAutomationBase(BaseModel):
367
367
  """Base Robot Automation class."""
368
368
 
369
- robot_id: UUID4 = Field(
369
+ robot_id: UUID = Field(
370
370
  description="The ID of the robot that will be used to enhance the reference."
371
371
  )
372
372
  query: dict[str, Any] = Field(
@@ -394,6 +394,6 @@ class RobotAutomation(_RobotAutomationBase):
394
394
  is sent to the specified robot to perform the enhancement.
395
395
  """
396
396
 
397
- id: UUID4 = Field(
397
+ id: UUID = Field(
398
398
  description="The ID of the robot automation.",
399
399
  )
@@ -1,8 +1,8 @@
1
1
  """Tests for HMAC Authentication."""
2
2
 
3
3
  import time
4
- import uuid
5
4
  from collections.abc import AsyncGenerator
5
+ from uuid import uuid7
6
6
 
7
7
  import destiny_sdk
8
8
  import pytest
@@ -11,7 +11,7 @@ from fastapi import APIRouter, Depends, FastAPI, status
11
11
  from httpx import ASGITransport, AsyncClient
12
12
 
13
13
  TEST_SECRET_KEY = "dlfskdfhgk8ei346oiehslkdfrerikfglser934utofs"
14
- TEST_CLIENT_ID = uuid.uuid4()
14
+ TEST_CLIENT_ID = uuid7()
15
15
  REQUEST_BODY = b'{"message": "info"}'
16
16
 
17
17
 
@@ -1,7 +1,7 @@
1
1
  """Tests client authentication"""
2
2
 
3
3
  import time
4
- import uuid
4
+ from uuid import UUID, uuid7
5
5
 
6
6
  import httpx
7
7
  import pytest
@@ -43,7 +43,7 @@ def base_url():
43
43
 
44
44
  @pytest.fixture
45
45
  def test_reference_id():
46
- return uuid.uuid4()
46
+ return uuid7()
47
47
 
48
48
 
49
49
  @pytest.fixture
@@ -66,19 +66,19 @@ class TestRobotClient:
66
66
  ) -> None:
67
67
  """Test that robot enhancement batch result request is authorized."""
68
68
  fake_secret_key = "asdfhjgji94523q0uflsjf349wjilsfjd9q23"
69
- fake_robot_id = uuid.uuid4()
69
+ fake_robot_id = uuid7()
70
70
  fake_destiny_repository_url = (
71
71
  "https://www.destiny-repository-lives-here.co.au/v1"
72
72
  )
73
73
 
74
74
  fake_batch_result = RobotEnhancementBatchResult(
75
- request_id=uuid.uuid4(),
75
+ request_id=uuid7(),
76
76
  error=RobotError(message="Cannot process this batch"),
77
77
  )
78
78
 
79
79
  expected_response_body = RobotEnhancementBatchRead(
80
- id=uuid.uuid4(),
81
- robot_id=uuid.uuid4(),
80
+ id=uuid7(),
81
+ robot_id=uuid7(),
82
82
  error="Cannot process this batch",
83
83
  )
84
84
 
@@ -126,7 +126,7 @@ class TestOAuthClient:
126
126
  httpx_mock: HTTPXMock,
127
127
  oauth_client: OAuthClient,
128
128
  base_url: str,
129
- test_reference_id: uuid.UUID,
129
+ test_reference_id: UUID,
130
130
  mock_reference_response: dict,
131
131
  ) -> None:
132
132
  """Test that search works without authentication."""
@@ -199,7 +199,7 @@ class TestOAuthClient:
199
199
  httpx_mock: HTTPXMock,
200
200
  oauth_client: OAuthClient,
201
201
  base_url: str,
202
- test_reference_id: uuid.UUID,
202
+ test_reference_id: UUID,
203
203
  ) -> None:
204
204
  """Test lookup references by identifiers."""
205
205
  httpx_mock.add_response(