fairagro-middleware-api-client 8.6.2__tar.gz → 8.6.4.dev7__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.
- {fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/PKG-INFO +10 -26
- {fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/README.md +9 -25
- {fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/src/middleware/api_client/api_client.py +17 -12
- {fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/tests/unit/test_client.py +92 -2
- {fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/.gitignore +0 -0
- {fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/example_client_config.yaml +0 -0
- {fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/pyproject.toml +0 -0
- {fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/src/middleware/api_client/__init__.py +0 -0
- {fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/src/middleware/api_client/config.py +0 -0
- {fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/src/middleware/api_client/models.py +0 -0
- {fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/src/middleware/api_client/py.typed +0 -0
- {fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/tests/conftest.py +0 -0
- {fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/tests/integration/conftest.py +0 -0
- {fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/tests/integration/test_create_arcs.py +0 -0
- {fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/tests/unit/test_api_client_config.py +0 -0
- {fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/tests/unit/test_client_config.py +0 -0
- {fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/tests/unit/test_retry_logic.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fairagro-middleware-api-client
|
|
3
|
-
Version: 8.6.
|
|
3
|
+
Version: 8.6.4.dev7
|
|
4
4
|
Summary: The FAIRagro advanced middleware API client
|
|
5
5
|
Requires-Python: >=3.12
|
|
6
6
|
Requires-Dist: httpx>=0.28.1
|
|
@@ -60,13 +60,13 @@ async def main():
|
|
|
60
60
|
# Send a single ARC
|
|
61
61
|
response = await client.create_or_update_arc(
|
|
62
62
|
rdi="my-rdi",
|
|
63
|
-
arc=arc,
|
|
63
|
+
arc=arc, # Can be ARC object, dict, or JSON string
|
|
64
64
|
)
|
|
65
65
|
print(f"ARC status: {response.status}")
|
|
66
66
|
|
|
67
67
|
# Or run a harvest workflow
|
|
68
68
|
async def arc_stream():
|
|
69
|
-
yield arc
|
|
69
|
+
yield arc # Can yield ARC objects, dicts, or JSON strings
|
|
70
70
|
|
|
71
71
|
harvest = await client.harvest_arcs(
|
|
72
72
|
rdi="my-rdi",
|
|
@@ -94,14 +94,14 @@ asyncio.run(main())
|
|
|
94
94
|
|
|
95
95
|
## API Methods
|
|
96
96
|
|
|
97
|
-
### `create_or_update_arc(rdi: str, arc: ARC | dict) -> ArcResult`
|
|
97
|
+
### `create_or_update_arc(rdi: str, arc: ARC | dict | str) -> ArcResult`
|
|
98
98
|
|
|
99
99
|
Create or update one ARC in the Middleware API.
|
|
100
100
|
|
|
101
101
|
**Parameters:**
|
|
102
102
|
|
|
103
103
|
- `rdi` (str): The RDI identifier (e.g., "edaphobase").
|
|
104
|
-
- `arc` (ARC | dict): ARC object from arctrl
|
|
104
|
+
- `arc` (ARC | dict | str): ARC object from arctrl, pre-serialised RO-Crate dict, or JSON string.
|
|
105
105
|
|
|
106
106
|
**Returns:**
|
|
107
107
|
|
|
@@ -109,7 +109,7 @@ Create or update one ARC in the Middleware API.
|
|
|
109
109
|
|
|
110
110
|
**Raises:**
|
|
111
111
|
|
|
112
|
-
- `ApiClientError`: If the request fails due to HTTP errors or
|
|
112
|
+
- `ApiClientError`: If the request fails due to HTTP errors, network issues, or invalid JSON.
|
|
113
113
|
|
|
114
114
|
**Example:**
|
|
115
115
|
|
|
@@ -121,17 +121,18 @@ arc = ARC.from_arc_investigation(inv)
|
|
|
121
121
|
|
|
122
122
|
response = await client.create_or_update_arc(
|
|
123
123
|
rdi="edaphobase",
|
|
124
|
-
arc=arc,
|
|
124
|
+
arc=arc, # Can also be dict or JSON string
|
|
125
125
|
)
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
-
### `harvest_arcs(rdi: str, arcs: AsyncIterator[ARC | dict], expected_datasets: int | None = None) -> HarvestResult`
|
|
128
|
+
### `harvest_arcs(rdi: str, arcs: AsyncIterator[ARC | dict | str], expected_datasets: int | None = None) -> HarvestResult`
|
|
129
129
|
|
|
130
130
|
Convenience workflow to create a harvest, upload all ARCs from an async iterator, and complete the harvest.
|
|
131
131
|
|
|
132
132
|
- Uses `config.max_concurrency` by default.
|
|
133
133
|
- Continues on item-level submission errors and skips failed items.
|
|
134
134
|
- Cancels the harvest only for catastrophic errors.
|
|
135
|
+
- Supports ARC objects, pre-serialised RO-Crate dicts, and JSON strings.
|
|
135
136
|
|
|
136
137
|
All errors are raised as `ApiClientError` exceptions:
|
|
137
138
|
|
|
@@ -141,24 +142,7 @@ from middleware.api_client import ApiClientError
|
|
|
141
142
|
try:
|
|
142
143
|
response = await client.create_or_update_arc(
|
|
143
144
|
rdi="my-rdi",
|
|
144
|
-
arc=arc,
|
|
145
|
+
arc=arc, # Can be ARC object, dict, or JSON string
|
|
145
146
|
)
|
|
146
147
|
except ApiClientError as e:
|
|
147
148
|
print(f"API Error: {e}")
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
## Configuration via Environment Variables
|
|
151
|
-
|
|
152
|
-
You can override configuration values using environment variables:
|
|
153
|
-
|
|
154
|
-
```bash
|
|
155
|
-
export API_URL="https://production-api:8000"
|
|
156
|
-
export CLIENT_CERT_PATH="/secure/certs/prod-cert.pem"
|
|
157
|
-
export CLIENT_KEY_PATH="/secure/certs/prod-key.pem"
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
Or use Docker secrets in `/run/secrets/`.
|
|
161
|
-
|
|
162
|
-
## License
|
|
163
|
-
|
|
164
|
-
This is part of the FAIRagro Advanced Middleware project.
|
{fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/README.md
RENAMED
|
@@ -51,13 +51,13 @@ async def main():
|
|
|
51
51
|
# Send a single ARC
|
|
52
52
|
response = await client.create_or_update_arc(
|
|
53
53
|
rdi="my-rdi",
|
|
54
|
-
arc=arc,
|
|
54
|
+
arc=arc, # Can be ARC object, dict, or JSON string
|
|
55
55
|
)
|
|
56
56
|
print(f"ARC status: {response.status}")
|
|
57
57
|
|
|
58
58
|
# Or run a harvest workflow
|
|
59
59
|
async def arc_stream():
|
|
60
|
-
yield arc
|
|
60
|
+
yield arc # Can yield ARC objects, dicts, or JSON strings
|
|
61
61
|
|
|
62
62
|
harvest = await client.harvest_arcs(
|
|
63
63
|
rdi="my-rdi",
|
|
@@ -85,14 +85,14 @@ asyncio.run(main())
|
|
|
85
85
|
|
|
86
86
|
## API Methods
|
|
87
87
|
|
|
88
|
-
### `create_or_update_arc(rdi: str, arc: ARC | dict) -> ArcResult`
|
|
88
|
+
### `create_or_update_arc(rdi: str, arc: ARC | dict | str) -> ArcResult`
|
|
89
89
|
|
|
90
90
|
Create or update one ARC in the Middleware API.
|
|
91
91
|
|
|
92
92
|
**Parameters:**
|
|
93
93
|
|
|
94
94
|
- `rdi` (str): The RDI identifier (e.g., "edaphobase").
|
|
95
|
-
- `arc` (ARC | dict): ARC object from arctrl
|
|
95
|
+
- `arc` (ARC | dict | str): ARC object from arctrl, pre-serialised RO-Crate dict, or JSON string.
|
|
96
96
|
|
|
97
97
|
**Returns:**
|
|
98
98
|
|
|
@@ -100,7 +100,7 @@ Create or update one ARC in the Middleware API.
|
|
|
100
100
|
|
|
101
101
|
**Raises:**
|
|
102
102
|
|
|
103
|
-
- `ApiClientError`: If the request fails due to HTTP errors or
|
|
103
|
+
- `ApiClientError`: If the request fails due to HTTP errors, network issues, or invalid JSON.
|
|
104
104
|
|
|
105
105
|
**Example:**
|
|
106
106
|
|
|
@@ -112,17 +112,18 @@ arc = ARC.from_arc_investigation(inv)
|
|
|
112
112
|
|
|
113
113
|
response = await client.create_or_update_arc(
|
|
114
114
|
rdi="edaphobase",
|
|
115
|
-
arc=arc,
|
|
115
|
+
arc=arc, # Can also be dict or JSON string
|
|
116
116
|
)
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
-
### `harvest_arcs(rdi: str, arcs: AsyncIterator[ARC | dict], expected_datasets: int | None = None) -> HarvestResult`
|
|
119
|
+
### `harvest_arcs(rdi: str, arcs: AsyncIterator[ARC | dict | str], expected_datasets: int | None = None) -> HarvestResult`
|
|
120
120
|
|
|
121
121
|
Convenience workflow to create a harvest, upload all ARCs from an async iterator, and complete the harvest.
|
|
122
122
|
|
|
123
123
|
- Uses `config.max_concurrency` by default.
|
|
124
124
|
- Continues on item-level submission errors and skips failed items.
|
|
125
125
|
- Cancels the harvest only for catastrophic errors.
|
|
126
|
+
- Supports ARC objects, pre-serialised RO-Crate dicts, and JSON strings.
|
|
126
127
|
|
|
127
128
|
All errors are raised as `ApiClientError` exceptions:
|
|
128
129
|
|
|
@@ -132,24 +133,7 @@ from middleware.api_client import ApiClientError
|
|
|
132
133
|
try:
|
|
133
134
|
response = await client.create_or_update_arc(
|
|
134
135
|
rdi="my-rdi",
|
|
135
|
-
arc=arc,
|
|
136
|
+
arc=arc, # Can be ARC object, dict, or JSON string
|
|
136
137
|
)
|
|
137
138
|
except ApiClientError as e:
|
|
138
139
|
print(f"API Error: {e}")
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
## Configuration via Environment Variables
|
|
142
|
-
|
|
143
|
-
You can override configuration values using environment variables:
|
|
144
|
-
|
|
145
|
-
```bash
|
|
146
|
-
export API_URL="https://production-api:8000"
|
|
147
|
-
export CLIENT_CERT_PATH="/secure/certs/prod-cert.pem"
|
|
148
|
-
export CLIENT_KEY_PATH="/secure/certs/prod-key.pem"
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
Or use Docker secrets in `/run/secrets/`.
|
|
152
|
-
|
|
153
|
-
## License
|
|
154
|
-
|
|
155
|
-
This is part of the FAIRagro Advanced Middleware project.
|
|
@@ -262,13 +262,13 @@ class ApiClient:
|
|
|
262
262
|
async def _submit_arcs_parallel(
|
|
263
263
|
self,
|
|
264
264
|
harvest_id: str,
|
|
265
|
-
arcs: "AsyncGenerator[ARC | dict[str, Any], None] | AsyncIterator[ARC | dict[str, Any]]",
|
|
265
|
+
arcs: "AsyncGenerator[ARC | dict[str, Any] | str, None] | AsyncIterator[ARC | dict[str, Any] | str]",
|
|
266
266
|
) -> int:
|
|
267
267
|
"""Submit all ARCs in bounded parallelism and return number of skipped ARC submissions."""
|
|
268
268
|
pending_tasks: set[asyncio.Task[None]] = set()
|
|
269
269
|
failed_submissions = 0
|
|
270
270
|
|
|
271
|
-
async def submit_one(arc_item: "ARC | dict[str, Any]") -> None:
|
|
271
|
+
async def submit_one(arc_item: "ARC | dict[str, Any] | str") -> None:
|
|
272
272
|
await self.submit_arc_in_harvest(harvest_id, arc_item)
|
|
273
273
|
|
|
274
274
|
async for arc in arcs:
|
|
@@ -446,10 +446,15 @@ class ApiClient:
|
|
|
446
446
|
# ------------------------------------------------------------------
|
|
447
447
|
|
|
448
448
|
@classmethod
|
|
449
|
-
def _serialize_arc(cls, arc: "ARC | dict[str, Any]") -> dict[str, Any]:
|
|
450
|
-
"""Serialize an ARC object to a plain RO-Crate JSON dict."""
|
|
449
|
+
def _serialize_arc(cls, arc: "ARC | dict[str, Any] | str") -> dict[str, Any]:
|
|
450
|
+
"""Serialize an ARC object, dict, or JSON string to a plain RO-Crate JSON dict."""
|
|
451
451
|
if isinstance(arc, dict):
|
|
452
452
|
return arc
|
|
453
|
+
if isinstance(arc, str):
|
|
454
|
+
try:
|
|
455
|
+
return cast(dict[str, Any], json.loads(arc))
|
|
456
|
+
except json.JSONDecodeError as e:
|
|
457
|
+
raise ApiClientError(f"Invalid JSON string provided for ARC: {e}") from e
|
|
453
458
|
return cast(dict[str, Any], json.loads(arc.ToROCrateJsonString()))
|
|
454
459
|
|
|
455
460
|
@classmethod
|
|
@@ -473,7 +478,7 @@ class ApiClient:
|
|
|
473
478
|
async def create_or_update_arc(
|
|
474
479
|
self,
|
|
475
480
|
rdi: str,
|
|
476
|
-
arc: "ARC | dict[str, Any]",
|
|
481
|
+
arc: "ARC | dict[str, Any] | str",
|
|
477
482
|
) -> ArcResult:
|
|
478
483
|
"""Create or update an ARC.
|
|
479
484
|
|
|
@@ -483,7 +488,7 @@ class ApiClient:
|
|
|
483
488
|
|
|
484
489
|
Args:
|
|
485
490
|
rdi: RDI identifier.
|
|
486
|
-
arc: ARC object
|
|
491
|
+
arc: ARC object, a pre-serialised RO-Crate JSON dict, or a JSON string.
|
|
487
492
|
|
|
488
493
|
Returns:
|
|
489
494
|
:class:`ArcResult` with the result of the operation.
|
|
@@ -579,7 +584,7 @@ class ApiClient:
|
|
|
579
584
|
async def submit_arc_in_harvest(
|
|
580
585
|
self,
|
|
581
586
|
harvest_id: str,
|
|
582
|
-
arc: "ARC | dict[str, Any]",
|
|
587
|
+
arc: "ARC | dict[str, Any] | str",
|
|
583
588
|
) -> ArcResult:
|
|
584
589
|
"""Submit an ARC within an active harvest run.
|
|
585
590
|
|
|
@@ -588,7 +593,7 @@ class ApiClient:
|
|
|
588
593
|
|
|
589
594
|
Args:
|
|
590
595
|
harvest_id: Harvest identifier.
|
|
591
|
-
arc: ARC object
|
|
596
|
+
arc: ARC object, a pre-serialised RO-Crate JSON dict, or a JSON string.
|
|
592
597
|
|
|
593
598
|
Returns:
|
|
594
599
|
:class:`ArcResult` with the result of the operation.
|
|
@@ -601,7 +606,7 @@ class ApiClient:
|
|
|
601
606
|
async def harvest_arcs(
|
|
602
607
|
self,
|
|
603
608
|
rdi: str,
|
|
604
|
-
arcs: "AsyncGenerator[ARC | dict[str, Any], None] | AsyncIterator[ARC | dict[str, Any]]",
|
|
609
|
+
arcs: "AsyncGenerator[ARC | dict[str, Any] | str, None] | AsyncIterator[ARC | dict[str, Any] | str]",
|
|
605
610
|
expected_datasets: int | None = None,
|
|
606
611
|
) -> HarvestResult:
|
|
607
612
|
"""Create a harvest, upload all ARCs from an async generator, then complete it.
|
|
@@ -618,8 +623,8 @@ class ApiClient:
|
|
|
618
623
|
|
|
619
624
|
Args:
|
|
620
625
|
rdi: RDI identifier for the harvest.
|
|
621
|
-
arcs: Async generator or async iterator yielding ARC objects
|
|
622
|
-
pre-serialised RO-Crate dicts.
|
|
626
|
+
arcs: Async generator or async iterator yielding ARC objects,
|
|
627
|
+
pre-serialised RO-Crate dicts, or JSON strings.
|
|
623
628
|
expected_datasets: Optional hint about the total number of ARCs.
|
|
624
629
|
|
|
625
630
|
Returns:
|
|
@@ -631,7 +636,7 @@ class ApiClient:
|
|
|
631
636
|
|
|
632
637
|
Example::
|
|
633
638
|
|
|
634
|
-
async def my_arcs() -> AsyncGenerator[dict, None]:
|
|
639
|
+
async def my_arcs() -> AsyncGenerator[dict | str, None]:
|
|
635
640
|
for arc in source:
|
|
636
641
|
yield arc
|
|
637
642
|
|
|
@@ -226,6 +226,28 @@ async def test_create_or_update_arc_with_dict(client_config: Config) -> None:
|
|
|
226
226
|
assert isinstance(response, ArcResult)
|
|
227
227
|
|
|
228
228
|
|
|
229
|
+
@pytest.mark.asyncio
|
|
230
|
+
@respx.mock
|
|
231
|
+
async def test_create_or_update_arc_with_json_string(client_config: Config) -> None:
|
|
232
|
+
"""Test create_or_update_arc with a JSON string."""
|
|
233
|
+
route = respx.post(f"{client_config.api_url}v3/arcs").mock(
|
|
234
|
+
return_value=httpx.Response(http.HTTPStatus.OK, json=_ARC_RESPONSE)
|
|
235
|
+
)
|
|
236
|
+
async with ApiClient(client_config) as client:
|
|
237
|
+
response = await client.create_or_update_arc(rdi="test-rdi", arc='{"id": "mock-arc"}')
|
|
238
|
+
assert route.called
|
|
239
|
+
assert isinstance(response, ArcResult)
|
|
240
|
+
assert response.arc_id == "arc-123"
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
@pytest.mark.asyncio
|
|
244
|
+
async def test_create_or_update_arc_with_invalid_json_string(client_config: Config) -> None:
|
|
245
|
+
"""Test create_or_update_arc with an invalid JSON string."""
|
|
246
|
+
async with ApiClient(client_config) as client:
|
|
247
|
+
with pytest.raises(ApiClientError, match="Invalid JSON string provided for ARC"):
|
|
248
|
+
await client.create_or_update_arc(rdi="test-rdi", arc='{"id": "mock-arc"')
|
|
249
|
+
|
|
250
|
+
|
|
229
251
|
@pytest.mark.asyncio
|
|
230
252
|
@respx.mock
|
|
231
253
|
async def test_create_or_update_arc_http_error(client_config: Config) -> None:
|
|
@@ -495,13 +517,35 @@ async def test_submit_arc_in_harvest_invalid_response(client_config: Config) ->
|
|
|
495
517
|
await client.submit_arc_in_harvest("harvest-456", arc={"id": "mock"})
|
|
496
518
|
|
|
497
519
|
|
|
520
|
+
@pytest.mark.asyncio
|
|
521
|
+
@respx.mock
|
|
522
|
+
async def test_submit_arc_in_harvest_with_json_string(client_config: Config) -> None:
|
|
523
|
+
"""Test submit_arc_in_harvest with a JSON string."""
|
|
524
|
+
route = respx.post(f"{client_config.api_url}v3/harvests/harvest-456/arcs").mock(
|
|
525
|
+
return_value=httpx.Response(http.HTTPStatus.OK, json=_ARC_RESPONSE)
|
|
526
|
+
)
|
|
527
|
+
async with ApiClient(client_config) as client:
|
|
528
|
+
response = await client.submit_arc_in_harvest("harvest-456", arc='{"id": "mock-arc"}')
|
|
529
|
+
assert route.called
|
|
530
|
+
assert isinstance(response, ArcResult)
|
|
531
|
+
assert response.arc_id == "arc-123"
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
@pytest.mark.asyncio
|
|
535
|
+
async def test_submit_arc_in_harvest_with_invalid_json_string(client_config: Config) -> None:
|
|
536
|
+
"""Test submit_arc_in_harvest with an invalid JSON string."""
|
|
537
|
+
async with ApiClient(client_config) as client:
|
|
538
|
+
with pytest.raises(ApiClientError, match="Invalid JSON string provided for ARC"):
|
|
539
|
+
await client.submit_arc_in_harvest("harvest-456", arc='{"id": "mock-arc"')
|
|
540
|
+
|
|
541
|
+
|
|
498
542
|
# ---------------------------------------------------------------------------
|
|
499
543
|
# harvest_arcs
|
|
500
544
|
# ---------------------------------------------------------------------------
|
|
501
545
|
|
|
502
546
|
|
|
503
|
-
async def _arc_gen(*arcs: "dict[str, Any]") -> AsyncGenerator["dict[str, Any]", None]:
|
|
504
|
-
"""Yield the provided arc dicts as an async generator."""
|
|
547
|
+
async def _arc_gen(*arcs: "dict[str, Any] | str | ARC") -> AsyncGenerator["dict[str, Any] | str | ARC", None]:
|
|
548
|
+
"""Yield the provided arc dicts, JSON strings, or ARC objects as an async generator."""
|
|
505
549
|
for arc in arcs:
|
|
506
550
|
yield arc
|
|
507
551
|
|
|
@@ -650,6 +694,52 @@ async def test_harvest_arcs_cancels_on_catastrophic_error(client_config: Config)
|
|
|
650
694
|
assert cancel_route.called
|
|
651
695
|
|
|
652
696
|
|
|
697
|
+
@pytest.mark.asyncio
|
|
698
|
+
@respx.mock
|
|
699
|
+
async def test_harvest_arcs_with_json_string(client_config: Config) -> None:
|
|
700
|
+
"""harvest_arcs supports JSON strings in async generator."""
|
|
701
|
+
completed_response = {**_HARVEST_RESPONSE, "status": "COMPLETED", "completed_at": "2024-01-01T01:00:00Z"}
|
|
702
|
+
respx.post(f"{client_config.api_url}v3/harvests").mock(
|
|
703
|
+
return_value=httpx.Response(http.HTTPStatus.OK, json=_HARVEST_RESPONSE)
|
|
704
|
+
)
|
|
705
|
+
respx.post(f"{client_config.api_url}v3/harvests/harvest-456/arcs").mock(
|
|
706
|
+
return_value=httpx.Response(http.HTTPStatus.OK, json=_ARC_RESPONSE)
|
|
707
|
+
)
|
|
708
|
+
respx.post(f"{client_config.api_url}v3/harvests/harvest-456/complete").mock(
|
|
709
|
+
return_value=httpx.Response(http.HTTPStatus.OK, json=completed_response)
|
|
710
|
+
)
|
|
711
|
+
|
|
712
|
+
arcs = _arc_gen(
|
|
713
|
+
'{"id": "arc-1-string"}',
|
|
714
|
+
{"id": "arc-2-dict"},
|
|
715
|
+
ARC.from_arc_investigation(ArcInvestigation.create(identifier="test", title="Test")),
|
|
716
|
+
)
|
|
717
|
+
async with ApiClient(client_config) as client:
|
|
718
|
+
result = await client.harvest_arcs("test-rdi", arcs, expected_datasets=3)
|
|
719
|
+
|
|
720
|
+
assert isinstance(result, HarvestResult)
|
|
721
|
+
assert result.status == "COMPLETED"
|
|
722
|
+
|
|
723
|
+
|
|
724
|
+
@pytest.mark.asyncio
|
|
725
|
+
@respx.mock
|
|
726
|
+
async def test_harvest_arcs_with_invalid_json_string(client_config: Config) -> None:
|
|
727
|
+
"""harvest_arcs raises ApiClientError when JSON string is invalid."""
|
|
728
|
+
# Mock the harvest creation endpoint to prevent actual HTTP requests
|
|
729
|
+
respx.post(f"{client_config.api_url}v3/harvests").mock(
|
|
730
|
+
return_value=httpx.Response(http.HTTPStatus.OK, json=_HARVEST_RESPONSE)
|
|
731
|
+
)
|
|
732
|
+
# Mock the harvest cancellation endpoint
|
|
733
|
+
respx.delete(f"{client_config.api_url}v3/harvests/harvest-456").mock(
|
|
734
|
+
return_value=httpx.Response(http.HTTPStatus.NO_CONTENT)
|
|
735
|
+
)
|
|
736
|
+
|
|
737
|
+
async with ApiClient(client_config) as client:
|
|
738
|
+
arcs = _arc_gen('{"id": "arc-1"') # Single invalid JSON string
|
|
739
|
+
with pytest.raises(ApiClientError, match="Invalid JSON string provided for ARC"):
|
|
740
|
+
await client.harvest_arcs("test-rdi", arcs)
|
|
741
|
+
|
|
742
|
+
|
|
653
743
|
@pytest.mark.asyncio
|
|
654
744
|
@respx.mock
|
|
655
745
|
async def test_harvest_arcs_cancel_failure_does_not_mask_original_error(client_config: Config) -> None:
|
{fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/.gitignore
RENAMED
|
File without changes
|
|
File without changes
|
{fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/pyproject.toml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fairagro_middleware_api_client-8.6.2 → fairagro_middleware_api_client-8.6.4.dev7}/tests/conftest.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|