clarity-api-sdk-python 0.3.36__tar.gz → 0.4.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.
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/PKG-INFO +1 -1
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/pyproject.toml +1 -1
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/clarity_api_sdk_python.egg-info/PKG-INFO +1 -1
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/clarity_api_sdk_python.egg-info/SOURCES.txt +2 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/api/sonar_wiz_api.py +121 -13
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/api/sonar_wiz_async_api.py +124 -14
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/cli/main.py +209 -59
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/raw_file_device_mapping.py +43 -2
- clarity_api_sdk_python-0.4.0/src/cti/model/raw_file_state.py +21 -0
- clarity_api_sdk_python-0.4.0/src/cti/model/user_layer.py +125 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/tests/test_cli.py +225 -71
- clarity_api_sdk_python-0.4.0/tests/test_raw_file_device_mapping_model.py +110 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/tests/test_sdk_async_methods.py +122 -17
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/tests/test_sdk_methods.py +97 -20
- clarity_api_sdk_python-0.3.36/src/cti/model/raw_file_state.py +0 -12
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/README.md +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/setup.cfg +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/clarity_api_sdk_python.egg-info/dependency_links.txt +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/clarity_api_sdk_python.egg-info/entry_points.txt +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/clarity_api_sdk_python.egg-info/requires.txt +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/clarity_api_sdk_python.egg-info/top_level.txt +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/__init__.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/api/__init__.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/api/async_client.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/api/client.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/api/session.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/cli/__init__.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/cli/__main__.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/cli/client.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/logger/__init__.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/logger/logger.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/main.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/main_api.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/__init__.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/altitude_source.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/attitude_source.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/deferred_object_deletion.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/depth_source.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/device.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/device_type.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/final_product.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/hierarchy.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/layback_algorithm.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/layback_source.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/layback_type.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/organization.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/platform.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/platform_type.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/position_source.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/processing_job.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/processing_log.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/project.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/projection_option.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/raw_file.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/raw_file_configuration.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/s3.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/sidescan_ping_source.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/source.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/survey.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/target.py +0 -0
- {clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/model/tow_system.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: clarity-api-sdk-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: clarity-api-sdk-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
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
|
|
@@ -51,6 +51,8 @@ src/cti/model/source.py
|
|
|
51
51
|
src/cti/model/survey.py
|
|
52
52
|
src/cti/model/target.py
|
|
53
53
|
src/cti/model/tow_system.py
|
|
54
|
+
src/cti/model/user_layer.py
|
|
54
55
|
tests/test_cli.py
|
|
56
|
+
tests/test_raw_file_device_mapping_model.py
|
|
55
57
|
tests/test_sdk_async_methods.py
|
|
56
58
|
tests/test_sdk_methods.py
|
|
@@ -99,6 +99,10 @@ from cti.model.target import TargetUpdate
|
|
|
99
99
|
from cti.model.tow_system import TowSystem
|
|
100
100
|
from cti.model.tow_system import TowSystemCreate
|
|
101
101
|
from cti.model.tow_system import TowSystemUpdate
|
|
102
|
+
from cti.model.user_layer import UserLayer
|
|
103
|
+
from cti.model.user_layer import UserLayerCreate
|
|
104
|
+
from cti.model.user_layer import UserLayerUpdate
|
|
105
|
+
from cti.model.user_layer import UserLayerWithUpload
|
|
102
106
|
|
|
103
107
|
from .client import ClarityApiClient
|
|
104
108
|
|
|
@@ -1975,13 +1979,34 @@ class SonarWizApi:
|
|
|
1975
1979
|
response.raise_for_status()
|
|
1976
1980
|
return ProcessingLog.model_validate(response.json())
|
|
1977
1981
|
|
|
1978
|
-
def list_processing_logs(
|
|
1979
|
-
|
|
1982
|
+
def list_processing_logs(
|
|
1983
|
+
self,
|
|
1984
|
+
*,
|
|
1985
|
+
raw_file_id: UUID | str | None = None,
|
|
1986
|
+
survey_id: UUID | str | None = None,
|
|
1987
|
+
processing_step: str | None = None,
|
|
1988
|
+
) -> list[ProcessingLog]:
|
|
1989
|
+
"""List processing logs, optionally filtered.
|
|
1990
|
+
|
|
1991
|
+
Filters compose: each provided filter narrows the result set.
|
|
1992
|
+
|
|
1993
|
+
Args:
|
|
1994
|
+
raw_file_id: Match only logs for this raw file.
|
|
1995
|
+
survey_id: Match only logs for this survey.
|
|
1996
|
+
processing_step: Match only logs with this processing step
|
|
1997
|
+
(e.g. ``"scan"``, ``"ingest"``, ``"products"``).
|
|
1980
1998
|
|
|
1981
1999
|
Returns:
|
|
1982
|
-
List of processing
|
|
2000
|
+
List of matching processing logs (empty list if none match).
|
|
1983
2001
|
"""
|
|
1984
|
-
|
|
2002
|
+
params: dict[str, str] = {}
|
|
2003
|
+
if raw_file_id is not None:
|
|
2004
|
+
params["raw_file_id"] = str(raw_file_id)
|
|
2005
|
+
if survey_id is not None:
|
|
2006
|
+
params["survey_id"] = str(survey_id)
|
|
2007
|
+
if processing_step is not None:
|
|
2008
|
+
params["processing_step"] = processing_step
|
|
2009
|
+
response = self._client.get("/api/v1/processing-logs", params=params or None)
|
|
1985
2010
|
response.raise_for_status()
|
|
1986
2011
|
return [ProcessingLog.model_validate(item) for item in response.json()]
|
|
1987
2012
|
|
|
@@ -2004,6 +2029,81 @@ class SonarWizApi:
|
|
|
2004
2029
|
response.raise_for_status()
|
|
2005
2030
|
return ProcessingLog.model_validate(response.json())
|
|
2006
2031
|
|
|
2032
|
+
# ── User Layers ──────────────────────────────────────────────────────
|
|
2033
|
+
|
|
2034
|
+
def create_user_layer(self, user_layer: UserLayerCreate) -> UserLayerWithUpload:
|
|
2035
|
+
"""Create a new user layer and initiate upload.
|
|
2036
|
+
|
|
2037
|
+
Args:
|
|
2038
|
+
user_layer: User layer creation data.
|
|
2039
|
+
|
|
2040
|
+
Returns:
|
|
2041
|
+
Created user layer instance with upload information.
|
|
2042
|
+
"""
|
|
2043
|
+
response = self._client.post(
|
|
2044
|
+
"/api/v1/user-layers/upload",
|
|
2045
|
+
json=user_layer.model_dump(mode="json"),
|
|
2046
|
+
)
|
|
2047
|
+
response.raise_for_status()
|
|
2048
|
+
return UserLayerWithUpload.model_validate(response.json())
|
|
2049
|
+
|
|
2050
|
+
def get_user_layer(self, user_layer_id: UUID) -> UserLayer:
|
|
2051
|
+
"""Fetch a user layer by ID.
|
|
2052
|
+
|
|
2053
|
+
Args:
|
|
2054
|
+
user_layer_id: User layer UUID to fetch.
|
|
2055
|
+
|
|
2056
|
+
Returns:
|
|
2057
|
+
UserLayer instance.
|
|
2058
|
+
"""
|
|
2059
|
+
response = self._client.get(f"/api/v1/user-layers/{user_layer_id}")
|
|
2060
|
+
response.raise_for_status()
|
|
2061
|
+
return UserLayer.model_validate(response.json())
|
|
2062
|
+
|
|
2063
|
+
def list_user_layers(self, project_id: UUID) -> list[UserLayer]:
|
|
2064
|
+
"""List all user layers for a project.
|
|
2065
|
+
|
|
2066
|
+
Args:
|
|
2067
|
+
project_id: Project UUID to filter by.
|
|
2068
|
+
|
|
2069
|
+
Returns:
|
|
2070
|
+
List of user layer instances.
|
|
2071
|
+
"""
|
|
2072
|
+
response = self._client.get(
|
|
2073
|
+
"/api/v1/user-layers",
|
|
2074
|
+
params={"project_id": str(project_id)},
|
|
2075
|
+
)
|
|
2076
|
+
response.raise_for_status()
|
|
2077
|
+
return [UserLayer.model_validate(item) for item in response.json()]
|
|
2078
|
+
|
|
2079
|
+
def update_user_layer(
|
|
2080
|
+
self, user_layer_id: UUID, user_layer: UserLayerUpdate
|
|
2081
|
+
) -> UserLayer:
|
|
2082
|
+
"""Update a user layer.
|
|
2083
|
+
|
|
2084
|
+
Args:
|
|
2085
|
+
user_layer_id: User layer UUID to update.
|
|
2086
|
+
user_layer: User layer update data.
|
|
2087
|
+
|
|
2088
|
+
Returns:
|
|
2089
|
+
Updated user layer instance.
|
|
2090
|
+
"""
|
|
2091
|
+
response = self._client.patch(
|
|
2092
|
+
f"/api/v1/user-layers/{user_layer_id}",
|
|
2093
|
+
json=user_layer.model_dump(mode="json", exclude_none=True),
|
|
2094
|
+
)
|
|
2095
|
+
response.raise_for_status()
|
|
2096
|
+
return UserLayer.model_validate(response.json())
|
|
2097
|
+
|
|
2098
|
+
def delete_user_layer(self, user_layer_id: UUID) -> None:
|
|
2099
|
+
"""Delete a user layer.
|
|
2100
|
+
|
|
2101
|
+
Args:
|
|
2102
|
+
user_layer_id: User layer UUID to delete.
|
|
2103
|
+
"""
|
|
2104
|
+
response = self._client.delete(f"/api/v1/user-layers/{user_layer_id}")
|
|
2105
|
+
response.raise_for_status()
|
|
2106
|
+
|
|
2007
2107
|
# ── Processing Jobs ──────────────────────────────────────────────────
|
|
2008
2108
|
|
|
2009
2109
|
def create_job(self, job_data: ProcessingJobCreate) -> ProcessingJob:
|
|
@@ -2116,7 +2216,9 @@ class SonarWizApi:
|
|
|
2116
2216
|
response.raise_for_status()
|
|
2117
2217
|
configs = [RawFileConfiguration.model_validate(c) for c in response.json()]
|
|
2118
2218
|
if not configs:
|
|
2119
|
-
raise ValueError(
|
|
2219
|
+
raise ValueError(
|
|
2220
|
+
f"No raw file configuration found for survey {survey_id}"
|
|
2221
|
+
)
|
|
2120
2222
|
raw_file_configuration_id = configs[0].raw_file_configuration_id
|
|
2121
2223
|
|
|
2122
2224
|
# Initiate multipart upload
|
|
@@ -2156,7 +2258,9 @@ class SonarWizApi:
|
|
|
2156
2258
|
f"/api/v1/rawfiles/{raw_file.raw_file_id}/upload-parts/{part_number}/url"
|
|
2157
2259
|
)
|
|
2158
2260
|
url_response.raise_for_status()
|
|
2159
|
-
presigned_url = PartPresignedURL.model_validate(
|
|
2261
|
+
presigned_url = PartPresignedURL.model_validate(
|
|
2262
|
+
url_response.json()
|
|
2263
|
+
).url
|
|
2160
2264
|
|
|
2161
2265
|
# The server generates presigned URLs using its S3_ENDPOINT_URL,
|
|
2162
2266
|
# which may be a Docker-internal hostname (e.g. minio:9000).
|
|
@@ -2210,23 +2314,27 @@ class SonarWizApi:
|
|
|
2210
2314
|
)
|
|
2211
2315
|
return completed
|
|
2212
2316
|
|
|
2213
|
-
def
|
|
2214
|
-
"""
|
|
2215
|
-
|
|
2216
|
-
Creates a processing job and dispatches it via SQS.
|
|
2317
|
+
def process(self, survey_id: UUID, target_phase: str = "products") -> ProcessingJob:
|
|
2318
|
+
"""Dispatch a pipeline run for a survey.
|
|
2217
2319
|
|
|
2218
2320
|
Args:
|
|
2219
2321
|
survey_id: Survey to process.
|
|
2322
|
+
target_phase: Pipeline phase to run up to. Defaults to "products"
|
|
2323
|
+
(full pipeline). "scan" runs only setup → scan. The engine's
|
|
2324
|
+
pull-chain resolves any required predecessor phases.
|
|
2220
2325
|
|
|
2221
2326
|
Returns:
|
|
2222
2327
|
The created ProcessingJob.
|
|
2223
2328
|
"""
|
|
2224
|
-
response = self._client.post(
|
|
2329
|
+
response = self._client.post(
|
|
2330
|
+
"/api/v1/process",
|
|
2331
|
+
json={"survey_id": str(survey_id), "target_phase": target_phase},
|
|
2332
|
+
)
|
|
2225
2333
|
response.raise_for_status()
|
|
2226
2334
|
data = response.json()
|
|
2227
2335
|
|
|
2228
|
-
# The
|
|
2229
|
-
# Fetch the full job record.
|
|
2336
|
+
# The /process endpoint returns a dict with job_id, not a full
|
|
2337
|
+
# ProcessingJob. Fetch the full job record.
|
|
2230
2338
|
if job_id := data.get("job_id"):
|
|
2231
2339
|
return self.get_job(job_id)
|
|
2232
2340
|
|
{clarity_api_sdk_python-0.3.36 → clarity_api_sdk_python-0.4.0}/src/cti/api/sonar_wiz_async_api.py
RENAMED
|
@@ -97,6 +97,10 @@ from cti.model.target import TargetUpdate
|
|
|
97
97
|
from cti.model.tow_system import TowSystem
|
|
98
98
|
from cti.model.tow_system import TowSystemCreate
|
|
99
99
|
from cti.model.tow_system import TowSystemUpdate
|
|
100
|
+
from cti.model.user_layer import UserLayer
|
|
101
|
+
from cti.model.user_layer import UserLayerCreate
|
|
102
|
+
from cti.model.user_layer import UserLayerUpdate
|
|
103
|
+
from cti.model.user_layer import UserLayerWithUpload
|
|
100
104
|
|
|
101
105
|
from .async_client import ClarityApiAsyncClient
|
|
102
106
|
|
|
@@ -2023,13 +2027,36 @@ class SonarWizAsyncApi:
|
|
|
2023
2027
|
response.raise_for_status()
|
|
2024
2028
|
return ProcessingLog.model_validate(response.json())
|
|
2025
2029
|
|
|
2026
|
-
async def list_processing_logs(
|
|
2027
|
-
|
|
2030
|
+
async def list_processing_logs(
|
|
2031
|
+
self,
|
|
2032
|
+
*,
|
|
2033
|
+
raw_file_id: UUID | str | None = None,
|
|
2034
|
+
survey_id: UUID | str | None = None,
|
|
2035
|
+
processing_step: str | None = None,
|
|
2036
|
+
) -> list[ProcessingLog]:
|
|
2037
|
+
"""List processing logs, optionally filtered.
|
|
2038
|
+
|
|
2039
|
+
Filters compose: each provided filter narrows the result set.
|
|
2040
|
+
|
|
2041
|
+
Args:
|
|
2042
|
+
raw_file_id: Match only logs for this raw file.
|
|
2043
|
+
survey_id: Match only logs for this survey.
|
|
2044
|
+
processing_step: Match only logs with this processing step
|
|
2045
|
+
(e.g. ``"scan"``, ``"ingest"``, ``"products"``).
|
|
2028
2046
|
|
|
2029
2047
|
Returns:
|
|
2030
|
-
List of processing
|
|
2048
|
+
List of matching processing logs (empty list if none match).
|
|
2031
2049
|
"""
|
|
2032
|
-
|
|
2050
|
+
params: dict[str, str] = {}
|
|
2051
|
+
if raw_file_id is not None:
|
|
2052
|
+
params["raw_file_id"] = str(raw_file_id)
|
|
2053
|
+
if survey_id is not None:
|
|
2054
|
+
params["survey_id"] = str(survey_id)
|
|
2055
|
+
if processing_step is not None:
|
|
2056
|
+
params["processing_step"] = processing_step
|
|
2057
|
+
response = await self._client.get(
|
|
2058
|
+
"/api/v1/processing-logs", params=params or None
|
|
2059
|
+
)
|
|
2033
2060
|
response.raise_for_status()
|
|
2034
2061
|
return [ProcessingLog.model_validate(item) for item in response.json()]
|
|
2035
2062
|
|
|
@@ -2052,6 +2079,83 @@ class SonarWizAsyncApi:
|
|
|
2052
2079
|
response.raise_for_status()
|
|
2053
2080
|
return ProcessingLog.model_validate(response.json())
|
|
2054
2081
|
|
|
2082
|
+
# ── User Layers ──────────────────────────────────────────────────────
|
|
2083
|
+
|
|
2084
|
+
async def create_user_layer(
|
|
2085
|
+
self, user_layer: UserLayerCreate
|
|
2086
|
+
) -> UserLayerWithUpload:
|
|
2087
|
+
"""Create a new user layer and initiate upload.
|
|
2088
|
+
|
|
2089
|
+
Args:
|
|
2090
|
+
user_layer: User layer creation data.
|
|
2091
|
+
|
|
2092
|
+
Returns:
|
|
2093
|
+
Created user layer instance with upload information.
|
|
2094
|
+
"""
|
|
2095
|
+
response = await self._client.post(
|
|
2096
|
+
"/api/v1/user-layers/upload",
|
|
2097
|
+
json=user_layer.model_dump(mode="json"),
|
|
2098
|
+
)
|
|
2099
|
+
response.raise_for_status()
|
|
2100
|
+
return UserLayerWithUpload.model_validate(response.json())
|
|
2101
|
+
|
|
2102
|
+
async def get_user_layer(self, user_layer_id: UUID) -> UserLayer:
|
|
2103
|
+
"""Fetch a user layer by ID.
|
|
2104
|
+
|
|
2105
|
+
Args:
|
|
2106
|
+
user_layer_id: User layer UUID to fetch.
|
|
2107
|
+
|
|
2108
|
+
Returns:
|
|
2109
|
+
UserLayer instance.
|
|
2110
|
+
"""
|
|
2111
|
+
response = await self._client.get(f"/api/v1/user-layers/{user_layer_id}")
|
|
2112
|
+
response.raise_for_status()
|
|
2113
|
+
return UserLayer.model_validate(response.json())
|
|
2114
|
+
|
|
2115
|
+
async def list_user_layers(self, project_id: UUID) -> list[UserLayer]:
|
|
2116
|
+
"""List all user layers for a project.
|
|
2117
|
+
|
|
2118
|
+
Args:
|
|
2119
|
+
project_id: Project UUID to filter by.
|
|
2120
|
+
|
|
2121
|
+
Returns:
|
|
2122
|
+
List of user layer instances.
|
|
2123
|
+
"""
|
|
2124
|
+
response = await self._client.get(
|
|
2125
|
+
"/api/v1/user-layers",
|
|
2126
|
+
params={"project_id": str(project_id)},
|
|
2127
|
+
)
|
|
2128
|
+
response.raise_for_status()
|
|
2129
|
+
return [UserLayer.model_validate(item) for item in response.json()]
|
|
2130
|
+
|
|
2131
|
+
async def update_user_layer(
|
|
2132
|
+
self, user_layer_id: UUID, user_layer: UserLayerUpdate
|
|
2133
|
+
) -> UserLayer:
|
|
2134
|
+
"""Update a user layer.
|
|
2135
|
+
|
|
2136
|
+
Args:
|
|
2137
|
+
user_layer_id: User layer UUID to update.
|
|
2138
|
+
user_layer: User layer update data.
|
|
2139
|
+
|
|
2140
|
+
Returns:
|
|
2141
|
+
Updated user layer instance.
|
|
2142
|
+
"""
|
|
2143
|
+
response = await self._client.patch(
|
|
2144
|
+
f"/api/v1/user-layers/{user_layer_id}",
|
|
2145
|
+
json=user_layer.model_dump(mode="json", exclude_none=True),
|
|
2146
|
+
)
|
|
2147
|
+
response.raise_for_status()
|
|
2148
|
+
return UserLayer.model_validate(response.json())
|
|
2149
|
+
|
|
2150
|
+
async def delete_user_layer(self, user_layer_id: UUID) -> None:
|
|
2151
|
+
"""Delete a user layer.
|
|
2152
|
+
|
|
2153
|
+
Args:
|
|
2154
|
+
user_layer_id: User layer UUID to delete.
|
|
2155
|
+
"""
|
|
2156
|
+
response = await self._client.delete(f"/api/v1/user-layers/{user_layer_id}")
|
|
2157
|
+
response.raise_for_status()
|
|
2158
|
+
|
|
2055
2159
|
# ── Processing Jobs ──────────────────────────────────────────────────
|
|
2056
2160
|
|
|
2057
2161
|
async def create_job(self, job_data: ProcessingJobCreate) -> ProcessingJob:
|
|
@@ -2164,7 +2268,9 @@ class SonarWizAsyncApi:
|
|
|
2164
2268
|
response.raise_for_status()
|
|
2165
2269
|
configs = [RawFileConfiguration.model_validate(c) for c in response.json()]
|
|
2166
2270
|
if not configs:
|
|
2167
|
-
raise ValueError(
|
|
2271
|
+
raise ValueError(
|
|
2272
|
+
f"No raw file configuration found for survey {survey_id}"
|
|
2273
|
+
)
|
|
2168
2274
|
raw_file_configuration_id = configs[0].raw_file_configuration_id
|
|
2169
2275
|
|
|
2170
2276
|
# Initiate multipart upload
|
|
@@ -2206,7 +2312,9 @@ class SonarWizAsyncApi:
|
|
|
2206
2312
|
f"/api/v1/rawfiles/{raw_file.raw_file_id}/upload-parts/{part_number}/url"
|
|
2207
2313
|
)
|
|
2208
2314
|
url_response.raise_for_status()
|
|
2209
|
-
presigned_url = PartPresignedURL.model_validate(
|
|
2315
|
+
presigned_url = PartPresignedURL.model_validate(
|
|
2316
|
+
url_response.json()
|
|
2317
|
+
).url
|
|
2210
2318
|
|
|
2211
2319
|
# Upload directly to S3/MinIO (not through API client)
|
|
2212
2320
|
put_response = await s3_client.put(presigned_url, content=chunk)
|
|
@@ -2246,27 +2354,29 @@ class SonarWizAsyncApi:
|
|
|
2246
2354
|
)
|
|
2247
2355
|
return completed
|
|
2248
2356
|
|
|
2249
|
-
async def
|
|
2250
|
-
self, survey_id: UUID
|
|
2357
|
+
async def process(
|
|
2358
|
+
self, survey_id: UUID, target_phase: str = "products"
|
|
2251
2359
|
) -> ProcessingJob:
|
|
2252
|
-
"""
|
|
2253
|
-
|
|
2254
|
-
Creates a processing job and dispatches it via SQS.
|
|
2360
|
+
"""Dispatch a pipeline run for a survey.
|
|
2255
2361
|
|
|
2256
2362
|
Args:
|
|
2257
2363
|
survey_id: Survey to process.
|
|
2364
|
+
target_phase: Pipeline phase to run up to. Defaults to "products"
|
|
2365
|
+
(full pipeline). "scan" runs only setup → scan. The engine's
|
|
2366
|
+
pull-chain resolves any required predecessor phases.
|
|
2258
2367
|
|
|
2259
2368
|
Returns:
|
|
2260
2369
|
The created ProcessingJob.
|
|
2261
2370
|
"""
|
|
2262
2371
|
response = await self._client.post(
|
|
2263
|
-
|
|
2372
|
+
"/api/v1/process",
|
|
2373
|
+
json={"survey_id": str(survey_id), "target_phase": target_phase},
|
|
2264
2374
|
)
|
|
2265
2375
|
response.raise_for_status()
|
|
2266
2376
|
data = response.json()
|
|
2267
2377
|
|
|
2268
|
-
# The
|
|
2269
|
-
# Fetch the full job record.
|
|
2378
|
+
# The /process endpoint returns a dict with job_id, not a full
|
|
2379
|
+
# ProcessingJob. Fetch the full job record.
|
|
2270
2380
|
if job_id := data.get("job_id"):
|
|
2271
2381
|
return await self.get_job(job_id)
|
|
2272
2382
|
|