clarity-api-sdk-python 0.4.0__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.
Files changed (60) hide show
  1. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/PKG-INFO +1 -1
  2. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/pyproject.toml +1 -1
  3. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/clarity_api_sdk_python.egg-info/PKG-INFO +1 -1
  4. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/api/sonar_wiz_api.py +28 -4
  5. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/api/sonar_wiz_async_api.py +30 -4
  6. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/tests/test_sdk_async_methods.py +72 -0
  7. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/tests/test_sdk_methods.py +68 -0
  8. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/README.md +0 -0
  9. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/setup.cfg +0 -0
  10. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/clarity_api_sdk_python.egg-info/SOURCES.txt +0 -0
  11. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/clarity_api_sdk_python.egg-info/dependency_links.txt +0 -0
  12. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/clarity_api_sdk_python.egg-info/entry_points.txt +0 -0
  13. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/clarity_api_sdk_python.egg-info/requires.txt +0 -0
  14. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/clarity_api_sdk_python.egg-info/top_level.txt +0 -0
  15. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/__init__.py +0 -0
  16. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/api/__init__.py +0 -0
  17. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/api/async_client.py +0 -0
  18. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/api/client.py +0 -0
  19. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/api/session.py +0 -0
  20. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/cli/__init__.py +0 -0
  21. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/cli/__main__.py +0 -0
  22. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/cli/client.py +0 -0
  23. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/cli/main.py +0 -0
  24. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/logger/__init__.py +0 -0
  25. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/logger/logger.py +0 -0
  26. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/main.py +0 -0
  27. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/main_api.py +0 -0
  28. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/__init__.py +0 -0
  29. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/altitude_source.py +0 -0
  30. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/attitude_source.py +0 -0
  31. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/deferred_object_deletion.py +0 -0
  32. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/depth_source.py +0 -0
  33. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/device.py +0 -0
  34. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/device_type.py +0 -0
  35. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/final_product.py +0 -0
  36. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/hierarchy.py +0 -0
  37. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/layback_algorithm.py +0 -0
  38. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/layback_source.py +0 -0
  39. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/layback_type.py +0 -0
  40. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/organization.py +0 -0
  41. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/platform.py +0 -0
  42. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/platform_type.py +0 -0
  43. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/position_source.py +0 -0
  44. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/processing_job.py +0 -0
  45. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/processing_log.py +0 -0
  46. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/project.py +0 -0
  47. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/projection_option.py +0 -0
  48. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/raw_file.py +0 -0
  49. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/raw_file_configuration.py +0 -0
  50. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/raw_file_device_mapping.py +0 -0
  51. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/raw_file_state.py +0 -0
  52. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/s3.py +0 -0
  53. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/sidescan_ping_source.py +0 -0
  54. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/source.py +0 -0
  55. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/survey.py +0 -0
  56. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/target.py +0 -0
  57. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/tow_system.py +0 -0
  58. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/src/cti/model/user_layer.py +0 -0
  59. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/tests/test_cli.py +0 -0
  60. {clarity_api_sdk_python-0.4.0 → clarity_api_sdk_python-0.4.1}/tests/test_raw_file_device_mapping_model.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: clarity-api-sdk-python
3
- Version: 0.4.0
3
+ Version: 0.4.1
4
4
  Summary: A Python SDK to connect to the CTI Clarity API server.
5
5
  Author-email: "Chesapeake Technology Inc." <support@chesapeaketech.com>
6
6
  Project-URL: Homepage, https://github.com/chesapeake-tech/clarity-api-sdk-python
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
 
6
6
  [project]
7
7
  name = "clarity-api-sdk-python"
8
- version = "0.4.0"
8
+ version = "0.4.1"
9
9
  authors = [
10
10
  { name="Chesapeake Technology Inc.", email="support@chesapeaketech.com" },
11
11
  ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: clarity-api-sdk-python
3
- Version: 0.4.0
3
+ Version: 0.4.1
4
4
  Summary: A Python SDK to connect to the CTI Clarity API server.
5
5
  Author-email: "Chesapeake Technology Inc." <support@chesapeaketech.com>
6
6
  Project-URL: Homepage, https://github.com/chesapeake-tech/clarity-api-sdk-python
@@ -357,13 +357,37 @@ class SonarWizApi:
357
357
  response.raise_for_status()
358
358
  return RawFileDeviceMapping.model_validate(response.json())
359
359
 
360
- def list_raw_file_device_mappings(self) -> list[RawFileDeviceMapping]:
361
- """List all raw file device mappings.
360
+ def get_raw_file_device_mappings(
361
+ self,
362
+ *,
363
+ raw_file_id: UUID | str | None = None,
364
+ device_id: UUID | str | None = None,
365
+ ) -> list[RawFileDeviceMapping]:
366
+ """Get raw file device mappings filtered by raw file or device.
367
+
368
+ At least one of ``raw_file_id`` / ``device_id`` must be provided —
369
+ the server requires a filter and returns 400 otherwise.
370
+
371
+ Args:
372
+ raw_file_id: Match only mappings for this raw file.
373
+ device_id: Match only mappings for this device.
362
374
 
363
375
  Returns:
364
- List of raw file device mapping instances.
376
+ List of matching raw file device mappings (empty if none match).
377
+
378
+ Raises:
379
+ ValueError: If neither ``raw_file_id`` nor ``device_id`` is given.
365
380
  """
366
- response = self._client.get("/api/v1/raw-file-device-mappings")
381
+ if raw_file_id is None and device_id is None:
382
+ raise ValueError(
383
+ "At least one of raw_file_id or device_id must be provided."
384
+ )
385
+ params: dict[str, str] = {}
386
+ if raw_file_id is not None:
387
+ params["raw_file_id"] = str(raw_file_id)
388
+ if device_id is not None:
389
+ params["device_id"] = str(device_id)
390
+ response = self._client.get("/api/v1/raw-file-device-mappings", params=params)
367
391
  response.raise_for_status()
368
392
  return [RawFileDeviceMapping.model_validate(item) for item in response.json()]
369
393
 
@@ -357,13 +357,39 @@ class SonarWizAsyncApi:
357
357
  response.raise_for_status()
358
358
  return RawFileDeviceMapping.model_validate(response.json())
359
359
 
360
- async def list_raw_file_device_mappings(self) -> list[RawFileDeviceMapping]:
361
- """List all raw file device mappings.
360
+ async def get_raw_file_device_mappings(
361
+ self,
362
+ *,
363
+ raw_file_id: UUID | str | None = None,
364
+ device_id: UUID | str | None = None,
365
+ ) -> list[RawFileDeviceMapping]:
366
+ """Get raw file device mappings filtered by raw file or device.
367
+
368
+ At least one of ``raw_file_id`` / ``device_id`` must be provided —
369
+ the server requires a filter and returns 400 otherwise.
370
+
371
+ Args:
372
+ raw_file_id: Match only mappings for this raw file.
373
+ device_id: Match only mappings for this device.
362
374
 
363
375
  Returns:
364
- List of raw file device mapping instances.
376
+ List of matching raw file device mappings (empty if none match).
377
+
378
+ Raises:
379
+ ValueError: If neither ``raw_file_id`` nor ``device_id`` is given.
365
380
  """
366
- response = await self._client.get("/api/v1/raw-file-device-mappings")
381
+ if raw_file_id is None and device_id is None:
382
+ raise ValueError(
383
+ "At least one of raw_file_id or device_id must be provided."
384
+ )
385
+ params: dict[str, str] = {}
386
+ if raw_file_id is not None:
387
+ params["raw_file_id"] = str(raw_file_id)
388
+ if device_id is not None:
389
+ params["device_id"] = str(device_id)
390
+ response = await self._client.get(
391
+ "/api/v1/raw-file-device-mappings", params=params
392
+ )
367
393
  response.raise_for_status()
368
394
  return [RawFileDeviceMapping.model_validate(item) for item in response.json()]
369
395
 
@@ -19,11 +19,15 @@ from .conftest import (
19
19
  SURVEY_ID,
20
20
  make_job_json,
21
21
  make_processing_log_json,
22
+ make_raw_file_device_mapping_json,
22
23
  make_raw_file_json,
23
24
  make_raw_file_with_upload_json,
24
25
  )
25
26
 
26
27
 
28
+ DEVICE_ID = UUID("00000000-0000-0000-0000-000000000099")
29
+
30
+
27
31
  def _mock_response(
28
32
  json_data: dict, status_code: int = 200, headers: dict | None = None
29
33
  ) -> MagicMock:
@@ -297,3 +301,71 @@ async def test_list_processing_logs_accepts_string_uuid():
297
301
  "/api/v1/processing-logs",
298
302
  params={"raw_file_id": str(RAW_FILE_ID)},
299
303
  )
304
+
305
+
306
+ # ── get_raw_file_device_mappings filter kwargs (#23) ────────────────────
307
+
308
+
309
+ @pytest.mark.asyncio
310
+ async def test_get_raw_file_device_mappings_requires_a_filter():
311
+ """Calling with neither filter raises ValueError before touching the wire."""
312
+ client = AsyncMock()
313
+ api = SonarWizAsyncApi(client)
314
+
315
+ with pytest.raises(ValueError, match="raw_file_id or device_id"):
316
+ await api.get_raw_file_device_mappings()
317
+
318
+ client.get.assert_not_called()
319
+
320
+
321
+ @pytest.mark.asyncio
322
+ async def test_get_raw_file_device_mappings_filters_by_raw_file_id():
323
+ """raw_file_id filter is sent as a query param; UUID stringified."""
324
+ client = AsyncMock()
325
+ client.get.return_value = _mock_response(
326
+ [make_raw_file_device_mapping_json(device_id=DEVICE_ID)]
327
+ )
328
+
329
+ api = SonarWizAsyncApi(client)
330
+ mappings = await api.get_raw_file_device_mappings(raw_file_id=RAW_FILE_ID)
331
+
332
+ client.get.assert_awaited_once_with(
333
+ "/api/v1/raw-file-device-mappings",
334
+ params={"raw_file_id": str(RAW_FILE_ID)},
335
+ )
336
+ assert len(mappings) == 1
337
+ assert mappings[0].raw_file_id == RAW_FILE_ID
338
+ assert mappings[0].device_id == DEVICE_ID
339
+
340
+
341
+ @pytest.mark.asyncio
342
+ async def test_get_raw_file_device_mappings_filters_by_device_id():
343
+ """device_id filter is sent alone when raw_file_id is omitted."""
344
+ client = AsyncMock()
345
+ client.get.return_value = _mock_response([])
346
+
347
+ api = SonarWizAsyncApi(client)
348
+ mappings = await api.get_raw_file_device_mappings(device_id=DEVICE_ID)
349
+
350
+ client.get.assert_awaited_once_with(
351
+ "/api/v1/raw-file-device-mappings",
352
+ params={"device_id": str(DEVICE_ID)},
353
+ )
354
+ assert mappings == []
355
+
356
+
357
+ @pytest.mark.asyncio
358
+ async def test_get_raw_file_device_mappings_accepts_string_uuids():
359
+ """String UUIDs are accepted and stringified the same way."""
360
+ client = AsyncMock()
361
+ client.get.return_value = _mock_response([])
362
+
363
+ api = SonarWizAsyncApi(client)
364
+ await api.get_raw_file_device_mappings(
365
+ raw_file_id=str(RAW_FILE_ID), device_id=str(DEVICE_ID)
366
+ )
367
+
368
+ client.get.assert_awaited_once_with(
369
+ "/api/v1/raw-file-device-mappings",
370
+ params={"raw_file_id": str(RAW_FILE_ID), "device_id": str(DEVICE_ID)},
371
+ )
@@ -20,11 +20,15 @@ from .conftest import (
20
20
  SURVEY_ID,
21
21
  make_job_json,
22
22
  make_processing_log_json,
23
+ make_raw_file_device_mapping_json,
23
24
  make_raw_file_json,
24
25
  make_raw_file_with_upload_json,
25
26
  )
26
27
 
27
28
 
29
+ DEVICE_ID = UUID("00000000-0000-0000-0000-000000000099")
30
+
31
+
28
32
  def _mock_response(
29
33
  json_data: dict, status_code: int = 200, headers: dict | None = None
30
34
  ) -> MagicMock:
@@ -317,3 +321,67 @@ def test_list_processing_logs_partial_filter_only_includes_provided():
317
321
  params={"survey_id": str(SURVEY_ID)},
318
322
  )
319
323
  assert logs == []
324
+
325
+
326
+ # ── get_raw_file_device_mappings filter kwargs (#23) ────────────────────
327
+
328
+
329
+ def test_get_raw_file_device_mappings_requires_a_filter():
330
+ """Calling with neither filter raises ValueError before touching the wire."""
331
+ client = MagicMock()
332
+ api = SonarWizApi(client)
333
+
334
+ with pytest.raises(ValueError, match="raw_file_id or device_id"):
335
+ api.get_raw_file_device_mappings()
336
+
337
+ client.get.assert_not_called()
338
+
339
+
340
+ def test_get_raw_file_device_mappings_filters_by_raw_file_id():
341
+ """raw_file_id filter is sent as a query param; UUID stringified."""
342
+ client = MagicMock()
343
+ client.get.return_value = _mock_response(
344
+ [make_raw_file_device_mapping_json(device_id=DEVICE_ID)]
345
+ )
346
+
347
+ api = SonarWizApi(client)
348
+ mappings = api.get_raw_file_device_mappings(raw_file_id=RAW_FILE_ID)
349
+
350
+ client.get.assert_called_once_with(
351
+ "/api/v1/raw-file-device-mappings",
352
+ params={"raw_file_id": str(RAW_FILE_ID)},
353
+ )
354
+ assert len(mappings) == 1
355
+ assert mappings[0].raw_file_id == RAW_FILE_ID
356
+ assert mappings[0].device_id == DEVICE_ID
357
+
358
+
359
+ def test_get_raw_file_device_mappings_filters_by_device_id():
360
+ """device_id filter is sent alone when raw_file_id is omitted."""
361
+ client = MagicMock()
362
+ client.get.return_value = _mock_response([])
363
+
364
+ api = SonarWizApi(client)
365
+ mappings = api.get_raw_file_device_mappings(device_id=DEVICE_ID)
366
+
367
+ client.get.assert_called_once_with(
368
+ "/api/v1/raw-file-device-mappings",
369
+ params={"device_id": str(DEVICE_ID)},
370
+ )
371
+ assert mappings == []
372
+
373
+
374
+ def test_get_raw_file_device_mappings_accepts_string_uuids():
375
+ """String UUIDs are accepted and stringified the same way."""
376
+ client = MagicMock()
377
+ client.get.return_value = _mock_response([])
378
+
379
+ api = SonarWizApi(client)
380
+ api.get_raw_file_device_mappings(
381
+ raw_file_id=str(RAW_FILE_ID), device_id=str(DEVICE_ID)
382
+ )
383
+
384
+ client.get.assert_called_once_with(
385
+ "/api/v1/raw-file-device-mappings",
386
+ params={"raw_file_id": str(RAW_FILE_ID), "device_id": str(DEVICE_ID)},
387
+ )