destiny_sdk 0.7.3__tar.gz → 0.7.5__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.7.3 → destiny_sdk-0.7.5}/PKG-INFO +1 -1
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/pyproject.toml +1 -1
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/src/destiny_sdk/client.py +14 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/src/destiny_sdk/enhancements.py +46 -1
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/src/destiny_sdk/identifiers.py +5 -2
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/tests/unit/test_enhancements.py +51 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/.gitignore +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/LICENSE +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/README.md +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/src/destiny_sdk/__init__.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/src/destiny_sdk/auth.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/src/destiny_sdk/core.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/src/destiny_sdk/imports.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/src/destiny_sdk/labs/__init__.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/src/destiny_sdk/labs/references.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/src/destiny_sdk/parsers/__init__.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/src/destiny_sdk/parsers/eppi_parser.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/src/destiny_sdk/parsers/exceptions.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/src/destiny_sdk/py.typed +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/src/destiny_sdk/references.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/src/destiny_sdk/robots.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/src/destiny_sdk/search.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/src/destiny_sdk/visibility.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/tests/unit/__init__.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/tests/unit/conftest.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/tests/unit/labs/test_references.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/tests/unit/parsers/test_eppi_parser.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/tests/unit/test_auth.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/tests/unit/test_client.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/tests/unit/test_data/destiny_references.jsonl +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/tests/unit/test_data/eppi_import.jsonl +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/tests/unit/test_data/eppi_import_with_annotations.jsonl +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/tests/unit/test_data/eppi_import_with_raw.jsonl +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/tests/unit/test_data/eppi_report.json +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/tests/unit/test_identifiers.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/tests/unit/test_references.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/tests/unit/test_robots.py +0 -0
- {destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: destiny_sdk
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.5
|
|
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
|
|
@@ -479,6 +479,7 @@ class OAuthClient:
|
|
|
479
479
|
self,
|
|
480
480
|
base_url: HttpUrl | str,
|
|
481
481
|
auth: httpx.Auth | None = None,
|
|
482
|
+
timeout: int = 10,
|
|
482
483
|
) -> None:
|
|
483
484
|
"""
|
|
484
485
|
Initialize the client.
|
|
@@ -490,6 +491,8 @@ class OAuthClient:
|
|
|
490
491
|
instance of ``OAuthMiddleware``, unless you need to create a custom auth
|
|
491
492
|
class.
|
|
492
493
|
:type auth: httpx.Auth | None
|
|
494
|
+
:param timeout: The timeout for requests, in seconds. Defaults to 10 seconds.
|
|
495
|
+
:type timeout: int
|
|
493
496
|
"""
|
|
494
497
|
self._client = httpx.Client(
|
|
495
498
|
base_url=str(base_url).removesuffix("/").removesuffix("/v1") + "/v1",
|
|
@@ -497,6 +500,7 @@ class OAuthClient:
|
|
|
497
500
|
"Content-Type": "application/json",
|
|
498
501
|
"User-Agent": user_agent,
|
|
499
502
|
},
|
|
503
|
+
timeout=timeout,
|
|
500
504
|
)
|
|
501
505
|
|
|
502
506
|
if auth:
|
|
@@ -529,6 +533,7 @@ class OAuthClient:
|
|
|
529
533
|
annotations: list[str | AnnotationFilter] | None = None,
|
|
530
534
|
sort: str | None = None,
|
|
531
535
|
page: int = 1,
|
|
536
|
+
timeout: int | None = None,
|
|
532
537
|
) -> ReferenceSearchResult:
|
|
533
538
|
"""
|
|
534
539
|
Send a search request to the Destiny Repository API.
|
|
@@ -547,6 +552,9 @@ class OAuthClient:
|
|
|
547
552
|
:type sort: str | None
|
|
548
553
|
:param page: The page number of results to retrieve.
|
|
549
554
|
:type page: int
|
|
555
|
+
:param timeout: The timeout for the request, in seconds. If provided, this will override
|
|
556
|
+
the client timeout.
|
|
557
|
+
:type timeout: int | None
|
|
550
558
|
:return: The response from the API.
|
|
551
559
|
:rtype: libs.sdk.src.destiny_sdk.references.ReferenceSearchResult
|
|
552
560
|
""" # noqa: E501
|
|
@@ -562,6 +570,7 @@ class OAuthClient:
|
|
|
562
570
|
response = self._client.get(
|
|
563
571
|
"/references/search/",
|
|
564
572
|
params=params,
|
|
573
|
+
timeout=timeout or httpx.USE_CLIENT_DEFAULT,
|
|
565
574
|
)
|
|
566
575
|
self._raise_for_status(response)
|
|
567
576
|
return ReferenceSearchResult.model_validate(response.json())
|
|
@@ -569,6 +578,7 @@ class OAuthClient:
|
|
|
569
578
|
def lookup(
|
|
570
579
|
self,
|
|
571
580
|
identifiers: list[str | IdentifierLookup],
|
|
581
|
+
timeout: int | None = None,
|
|
572
582
|
) -> list[Reference]:
|
|
573
583
|
"""
|
|
574
584
|
Lookup references by identifiers.
|
|
@@ -577,6 +587,9 @@ class OAuthClient:
|
|
|
577
587
|
|
|
578
588
|
:param identifiers: The identifiers to look up.
|
|
579
589
|
:type identifiers: list[str | libs.sdk.src.destiny_sdk.identifiers.IdentifierLookup]
|
|
590
|
+
:param timeout: The timeout for the request, in seconds. If provided, this will override
|
|
591
|
+
the client timeout.
|
|
592
|
+
:type timeout: int | None
|
|
580
593
|
:return: The list of references matching the identifiers.
|
|
581
594
|
:rtype: list[libs.sdk.src.destiny_sdk.references.Reference]
|
|
582
595
|
""" # noqa: E501
|
|
@@ -585,6 +598,7 @@ class OAuthClient:
|
|
|
585
598
|
params={
|
|
586
599
|
"identifier": ",".join([str(identifier) for identifier in identifiers])
|
|
587
600
|
},
|
|
601
|
+
timeout=timeout or httpx.USE_CLIENT_DEFAULT,
|
|
588
602
|
)
|
|
589
603
|
self._raise_for_status(response)
|
|
590
604
|
return TypeAdapter(list[Reference]).validate_python(response.json())
|
|
@@ -8,6 +8,7 @@ from typing import Annotated, Any, Literal, Self
|
|
|
8
8
|
from pydantic import UUID4, BaseModel, Field, HttpUrl, model_validator
|
|
9
9
|
|
|
10
10
|
from destiny_sdk.core import _JsonlFileInputMixIn
|
|
11
|
+
from destiny_sdk.identifiers import Identifier
|
|
11
12
|
from destiny_sdk.visibility import Visibility
|
|
12
13
|
|
|
13
14
|
|
|
@@ -26,6 +27,8 @@ class EnhancementType(StrEnum):
|
|
|
26
27
|
"""A free-form enhancement for tagging with labels."""
|
|
27
28
|
LOCATION = auto()
|
|
28
29
|
"""Locations where the reference can be found."""
|
|
30
|
+
REFERENCE_ASSOCIATION = auto()
|
|
31
|
+
"""Associations to other references."""
|
|
29
32
|
RAW = auto()
|
|
30
33
|
"""A free form enhancement for arbitrary/unstructured data."""
|
|
31
34
|
FULL_TEXT = auto()
|
|
@@ -56,7 +59,11 @@ class Authorship(BaseModel):
|
|
|
56
59
|
for our purposes.
|
|
57
60
|
"""
|
|
58
61
|
|
|
59
|
-
display_name: str = Field(
|
|
62
|
+
display_name: str = Field(
|
|
63
|
+
description="The display name of the author. "
|
|
64
|
+
"Expected format FIRSTNAME <MIDDLENAME> LASTNAME. "
|
|
65
|
+
"Providing display_name in an unexpected format will affect search performance."
|
|
66
|
+
)
|
|
60
67
|
orcid: str | None = Field(default=None, description="The ORCid of the author.")
|
|
61
68
|
position: AuthorPosition = Field(
|
|
62
69
|
description="The position of the author within the list of authors."
|
|
@@ -320,6 +327,43 @@ class LocationEnhancement(BaseModel):
|
|
|
320
327
|
)
|
|
321
328
|
|
|
322
329
|
|
|
330
|
+
class ReferenceAssociationType(StrEnum):
|
|
331
|
+
"""
|
|
332
|
+
The type of association between references.
|
|
333
|
+
|
|
334
|
+
Direction is important: "this reference <association_type> associated reference".
|
|
335
|
+
"""
|
|
336
|
+
|
|
337
|
+
CITES = auto()
|
|
338
|
+
"""This reference cites the related reference."""
|
|
339
|
+
IS_CITED_BY = auto()
|
|
340
|
+
"""This reference is cited by the related reference."""
|
|
341
|
+
IS_SIMILAR_TO = auto()
|
|
342
|
+
"""This reference is similar to the related reference."""
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
class ReferenceAssociationEnhancement(BaseModel):
|
|
346
|
+
"""An enhancement for storing associations between references."""
|
|
347
|
+
|
|
348
|
+
enhancement_type: Literal[EnhancementType.REFERENCE_ASSOCIATION] = (
|
|
349
|
+
EnhancementType.REFERENCE_ASSOCIATION
|
|
350
|
+
)
|
|
351
|
+
associated_reference_ids: list[Identifier] = Field(
|
|
352
|
+
min_length=1,
|
|
353
|
+
description=(
|
|
354
|
+
"A list of Identifiers which are associated to this reference. "
|
|
355
|
+
"These can either be ExternalIdentifiers or resolved repository UUID4s."
|
|
356
|
+
),
|
|
357
|
+
)
|
|
358
|
+
association_type: ReferenceAssociationType = Field(
|
|
359
|
+
description=(
|
|
360
|
+
"The type of association between this reference and the associated ones. "
|
|
361
|
+
"Direction is important: "
|
|
362
|
+
'"this reference <association_type> associated reference".'
|
|
363
|
+
)
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
|
|
323
367
|
class RawEnhancement(BaseModel):
|
|
324
368
|
"""
|
|
325
369
|
An enhancement for storing raw/arbitrary/unstructured data.
|
|
@@ -377,6 +421,7 @@ EnhancementContent = Annotated[
|
|
|
377
421
|
| AbstractContentEnhancement
|
|
378
422
|
| AnnotationEnhancement
|
|
379
423
|
| LocationEnhancement
|
|
424
|
+
| ReferenceAssociationEnhancement
|
|
380
425
|
| RawEnhancement,
|
|
381
426
|
Field(discriminator="enhancement_type"),
|
|
382
427
|
]
|
|
@@ -165,6 +165,9 @@ ExternalIdentifier = Annotated[
|
|
|
165
165
|
Field(discriminator="identifier_type"),
|
|
166
166
|
]
|
|
167
167
|
|
|
168
|
+
#: Any identifier including external identifiers and repository UUID4s.
|
|
169
|
+
Identifier = Annotated[ExternalIdentifier | UUID4, Field()]
|
|
170
|
+
|
|
168
171
|
ExternalIdentifierAdapter: TypeAdapter[ExternalIdentifier] = TypeAdapter(
|
|
169
172
|
ExternalIdentifier
|
|
170
173
|
)
|
|
@@ -245,7 +248,7 @@ class IdentifierLookup(BaseModel):
|
|
|
245
248
|
)
|
|
246
249
|
|
|
247
250
|
@classmethod
|
|
248
|
-
def from_identifier(cls, identifier:
|
|
251
|
+
def from_identifier(cls, identifier: Identifier) -> Self:
|
|
249
252
|
"""Create an IdentifierLookup from an ExternalIdentifier or UUID4."""
|
|
250
253
|
if isinstance(identifier, uuid.UUID):
|
|
251
254
|
return cls(identifier=str(identifier), identifier_type=None)
|
|
@@ -255,7 +258,7 @@ class IdentifierLookup(BaseModel):
|
|
|
255
258
|
other_identifier_name=getattr(identifier, "other_identifier_name", None),
|
|
256
259
|
)
|
|
257
260
|
|
|
258
|
-
def to_identifier(self) ->
|
|
261
|
+
def to_identifier(self) -> Identifier:
|
|
259
262
|
"""Convert into an ExternalIdentifier or UUID4 if it has no identifier_type."""
|
|
260
263
|
if self.identifier_type is None:
|
|
261
264
|
return UUID4(self.identifier)
|
|
@@ -173,3 +173,54 @@ def test_empty_location_enhancement_errors():
|
|
|
173
173
|
enhancement_type=destiny_sdk.enhancements.EnhancementType.LOCATION,
|
|
174
174
|
locations=[],
|
|
175
175
|
)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def test_association_enhancement_valid():
|
|
179
|
+
# Create valid association content
|
|
180
|
+
association_content = destiny_sdk.enhancements.ReferenceAssociationEnhancement(
|
|
181
|
+
enhancement_type=destiny_sdk.enhancements.EnhancementType.REFERENCE_ASSOCIATION,
|
|
182
|
+
associated_reference_ids=[
|
|
183
|
+
uuid.uuid4(),
|
|
184
|
+
destiny_sdk.identifiers.OpenAlexIdentifier(
|
|
185
|
+
identifier="https://openalex.org/W1234567890",
|
|
186
|
+
identifier_type=destiny_sdk.identifiers.ExternalIdentifierType.OPEN_ALEX,
|
|
187
|
+
),
|
|
188
|
+
],
|
|
189
|
+
association_type=destiny_sdk.enhancements.ReferenceAssociationType.CITES,
|
|
190
|
+
)
|
|
191
|
+
enhancement = destiny_sdk.enhancements.Enhancement(
|
|
192
|
+
id=uuid.uuid4(),
|
|
193
|
+
source="test_source",
|
|
194
|
+
visibility="public",
|
|
195
|
+
robot_version="1.0",
|
|
196
|
+
enhancement_type=destiny_sdk.enhancements.EnhancementType.REFERENCE_ASSOCIATION,
|
|
197
|
+
content=association_content,
|
|
198
|
+
reference_id=uuid.uuid4(),
|
|
199
|
+
)
|
|
200
|
+
assert (
|
|
201
|
+
enhancement.content.association_type
|
|
202
|
+
== destiny_sdk.enhancements.ReferenceAssociationType.CITES
|
|
203
|
+
)
|
|
204
|
+
assert enhancement.content.associated_reference_ids[1].identifier == "W1234567890"
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def test_association_enhancement_empty_associated_reference_ids_errors():
|
|
208
|
+
# Test that an empty associated_reference_ids list raises a validation error
|
|
209
|
+
with pytest.raises(ValidationError):
|
|
210
|
+
destiny_sdk.enhancements.ReferenceAssociationEnhancement(
|
|
211
|
+
enhancement_type=destiny_sdk.enhancements.EnhancementType.REFERENCE_ASSOCIATION,
|
|
212
|
+
associated_reference_ids=[],
|
|
213
|
+
association_type=destiny_sdk.enhancements.ReferenceAssociationType.CITES,
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def test_association_enhancement_invalid_identifier_type_errors():
|
|
218
|
+
# Test that an invalid identifier type raises a validation error
|
|
219
|
+
with pytest.raises(ValidationError):
|
|
220
|
+
destiny_sdk.enhancements.ReferenceAssociationEnhancement(
|
|
221
|
+
enhancement_type=destiny_sdk.enhancements.EnhancementType.REFERENCE_ASSOCIATION,
|
|
222
|
+
associated_reference_ids=[
|
|
223
|
+
"random-string",
|
|
224
|
+
],
|
|
225
|
+
association_type=destiny_sdk.enhancements.ReferenceAssociationType.CITES,
|
|
226
|
+
)
|
|
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
|
{destiny_sdk-0.7.3 → destiny_sdk-0.7.5}/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
|
|
File without changes
|