hiddenlayer-sdk 1.0.0__py3-none-any.whl → 1.1.0__py3-none-any.whl
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.
- hiddenlayer/sdk/constants.py +1 -0
- hiddenlayer/sdk/models.py +2 -2
- hiddenlayer/sdk/rest/__init__.py +1 -1
- hiddenlayer/sdk/rest/api/sensor_api.py +11 -23
- hiddenlayer/sdk/rest/models/__init__.py +1 -1
- hiddenlayer/sdk/rest/models/file_scan_report_v3.py +42 -5
- hiddenlayer/sdk/rest/models/file_scan_reports_v3.py +95 -0
- hiddenlayer/sdk/rest/models/scan_report_v3.py +3 -3
- hiddenlayer/sdk/rest/models/sensor_sor_model_card_response.py +1 -1
- hiddenlayer/sdk/services/model.py +46 -1
- hiddenlayer/sdk/services/model_scan.py +1 -1
- hiddenlayer/sdk/version.py +1 -1
- {hiddenlayer_sdk-1.0.0.dist-info → hiddenlayer_sdk-1.1.0.dist-info}/METADATA +2 -2
- {hiddenlayer_sdk-1.0.0.dist-info → hiddenlayer_sdk-1.1.0.dist-info}/RECORD +17 -17
- {hiddenlayer_sdk-1.0.0.dist-info → hiddenlayer_sdk-1.1.0.dist-info}/WHEEL +1 -1
- hiddenlayer/sdk/rest/models/file_results_inner.py +0 -121
- {hiddenlayer_sdk-1.0.0.dist-info → hiddenlayer_sdk-1.1.0.dist-info}/LICENSE +0 -0
- {hiddenlayer_sdk-1.0.0.dist-info → hiddenlayer_sdk-1.1.0.dist-info}/top_level.txt +0 -0
hiddenlayer/sdk/constants.py
CHANGED
hiddenlayer/sdk/models.py
CHANGED
@@ -9,7 +9,7 @@ from hiddenlayer.sdk.rest.models import (
|
|
9
9
|
ModelInventoryInfo,
|
10
10
|
ScanReportV3,
|
11
11
|
)
|
12
|
-
from hiddenlayer.sdk.rest.models.
|
12
|
+
from hiddenlayer.sdk.rest.models.file_scan_report_v3 import FileScanReportV3
|
13
13
|
from hiddenlayer.sdk.rest.models.sarif210 import Sarif210
|
14
14
|
|
15
15
|
|
@@ -50,7 +50,7 @@ class EmptyScanResults(ScanResults):
|
|
50
50
|
start_time: datetime = datetime.now()
|
51
51
|
end_time: Optional[datetime] = datetime.now()
|
52
52
|
severity: Optional[StrictStr] = ""
|
53
|
-
file_results: Optional[List[
|
53
|
+
file_results: Optional[List[FileScanReportV3]] = []
|
54
54
|
|
55
55
|
|
56
56
|
class Sarif(Sarif210):
|
hiddenlayer/sdk/rest/__init__.py
CHANGED
@@ -54,8 +54,8 @@ from hiddenlayer.sdk.rest.models.external_properties import ExternalProperties
|
|
54
54
|
from hiddenlayer.sdk.rest.models.external_property_file_reference import ExternalPropertyFileReference
|
55
55
|
from hiddenlayer.sdk.rest.models.external_property_file_references import ExternalPropertyFileReferences
|
56
56
|
from hiddenlayer.sdk.rest.models.file_details_v3 import FileDetailsV3
|
57
|
-
from hiddenlayer.sdk.rest.models.file_results_inner import FileResultsInner
|
58
57
|
from hiddenlayer.sdk.rest.models.file_scan_report_v3 import FileScanReportV3
|
58
|
+
from hiddenlayer.sdk.rest.models.file_scan_reports_v3 import FileScanReportsV3
|
59
59
|
from hiddenlayer.sdk.rest.models.fix import Fix
|
60
60
|
from hiddenlayer.sdk.rest.models.get_multipart_upload_response import GetMultipartUploadResponse
|
61
61
|
from hiddenlayer.sdk.rest.models.graph import Graph
|
@@ -17,7 +17,7 @@ from typing import Any, Dict, List, Optional, Tuple, Union
|
|
17
17
|
from typing_extensions import Annotated
|
18
18
|
|
19
19
|
from pydantic import Field, StrictFloat, StrictInt, StrictStr, field_validator
|
20
|
-
from typing import Any,
|
20
|
+
from typing import Any, Optional, Union
|
21
21
|
from typing_extensions import Annotated
|
22
22
|
from hiddenlayer.sdk.rest.models.create_sensor_request import CreateSensorRequest
|
23
23
|
from hiddenlayer.sdk.rest.models.get_multipart_upload_response import GetMultipartUploadResponse
|
@@ -334,7 +334,7 @@ class SensorApi:
|
|
334
334
|
_content_type: Optional[StrictStr] = None,
|
335
335
|
_headers: Optional[Dict[StrictStr, Any]] = None,
|
336
336
|
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
|
337
|
-
) ->
|
337
|
+
) -> None:
|
338
338
|
"""Complete Multipart Upload
|
339
339
|
|
340
340
|
|
@@ -374,7 +374,7 @@ class SensorApi:
|
|
374
374
|
)
|
375
375
|
|
376
376
|
_response_types_map: Dict[str, Optional[str]] = {
|
377
|
-
'200':
|
377
|
+
'200': None,
|
378
378
|
'400': None,
|
379
379
|
}
|
380
380
|
response_data = self.api_client.call_api(
|
@@ -405,7 +405,7 @@ class SensorApi:
|
|
405
405
|
_content_type: Optional[StrictStr] = None,
|
406
406
|
_headers: Optional[Dict[StrictStr, Any]] = None,
|
407
407
|
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
|
408
|
-
) -> ApiResponse[
|
408
|
+
) -> ApiResponse[None]:
|
409
409
|
"""Complete Multipart Upload
|
410
410
|
|
411
411
|
|
@@ -445,7 +445,7 @@ class SensorApi:
|
|
445
445
|
)
|
446
446
|
|
447
447
|
_response_types_map: Dict[str, Optional[str]] = {
|
448
|
-
'200':
|
448
|
+
'200': None,
|
449
449
|
'400': None,
|
450
450
|
}
|
451
451
|
response_data = self.api_client.call_api(
|
@@ -516,7 +516,7 @@ class SensorApi:
|
|
516
516
|
)
|
517
517
|
|
518
518
|
_response_types_map: Dict[str, Optional[str]] = {
|
519
|
-
'200':
|
519
|
+
'200': None,
|
520
520
|
'400': None,
|
521
521
|
}
|
522
522
|
response_data = self.api_client.call_api(
|
@@ -559,12 +559,6 @@ class SensorApi:
|
|
559
559
|
# process the body parameter
|
560
560
|
|
561
561
|
|
562
|
-
# set the HTTP header `Accept`
|
563
|
-
_header_params['Accept'] = self.api_client.select_header_accept(
|
564
|
-
[
|
565
|
-
'application/json'
|
566
|
-
]
|
567
|
-
)
|
568
562
|
|
569
563
|
|
570
564
|
# authentication setting
|
@@ -1998,7 +1992,7 @@ class SensorApi:
|
|
1998
1992
|
_content_type: Optional[StrictStr] = None,
|
1999
1993
|
_headers: Optional[Dict[StrictStr, Any]] = None,
|
2000
1994
|
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
|
2001
|
-
) ->
|
1995
|
+
) -> None:
|
2002
1996
|
"""Upload part
|
2003
1997
|
|
2004
1998
|
|
@@ -2044,7 +2038,7 @@ class SensorApi:
|
|
2044
2038
|
)
|
2045
2039
|
|
2046
2040
|
_response_types_map: Dict[str, Optional[str]] = {
|
2047
|
-
'200':
|
2041
|
+
'200': None,
|
2048
2042
|
'400': None,
|
2049
2043
|
}
|
2050
2044
|
response_data = self.api_client.call_api(
|
@@ -2077,7 +2071,7 @@ class SensorApi:
|
|
2077
2071
|
_content_type: Optional[StrictStr] = None,
|
2078
2072
|
_headers: Optional[Dict[StrictStr, Any]] = None,
|
2079
2073
|
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
|
2080
|
-
) -> ApiResponse[
|
2074
|
+
) -> ApiResponse[None]:
|
2081
2075
|
"""Upload part
|
2082
2076
|
|
2083
2077
|
|
@@ -2123,7 +2117,7 @@ class SensorApi:
|
|
2123
2117
|
)
|
2124
2118
|
|
2125
2119
|
_response_types_map: Dict[str, Optional[str]] = {
|
2126
|
-
'200':
|
2120
|
+
'200': None,
|
2127
2121
|
'400': None,
|
2128
2122
|
}
|
2129
2123
|
response_data = self.api_client.call_api(
|
@@ -2202,7 +2196,7 @@ class SensorApi:
|
|
2202
2196
|
)
|
2203
2197
|
|
2204
2198
|
_response_types_map: Dict[str, Optional[str]] = {
|
2205
|
-
'200':
|
2199
|
+
'200': None,
|
2206
2200
|
'400': None,
|
2207
2201
|
}
|
2208
2202
|
response_data = self.api_client.call_api(
|
@@ -2251,12 +2245,6 @@ class SensorApi:
|
|
2251
2245
|
_body_params = body
|
2252
2246
|
|
2253
2247
|
|
2254
|
-
# set the HTTP header `Accept`
|
2255
|
-
_header_params['Accept'] = self.api_client.select_header_accept(
|
2256
|
-
[
|
2257
|
-
'application/json'
|
2258
|
-
]
|
2259
|
-
)
|
2260
2248
|
|
2261
2249
|
# set the HTTP header `Content-Type`
|
2262
2250
|
if _content_type:
|
@@ -32,8 +32,8 @@ from hiddenlayer.sdk.rest.models.external_properties import ExternalProperties
|
|
32
32
|
from hiddenlayer.sdk.rest.models.external_property_file_reference import ExternalPropertyFileReference
|
33
33
|
from hiddenlayer.sdk.rest.models.external_property_file_references import ExternalPropertyFileReferences
|
34
34
|
from hiddenlayer.sdk.rest.models.file_details_v3 import FileDetailsV3
|
35
|
-
from hiddenlayer.sdk.rest.models.file_results_inner import FileResultsInner
|
36
35
|
from hiddenlayer.sdk.rest.models.file_scan_report_v3 import FileScanReportV3
|
36
|
+
from hiddenlayer.sdk.rest.models.file_scan_reports_v3 import FileScanReportsV3
|
37
37
|
from hiddenlayer.sdk.rest.models.fix import Fix
|
38
38
|
from hiddenlayer.sdk.rest.models.get_multipart_upload_response import GetMultipartUploadResponse
|
39
39
|
from hiddenlayer.sdk.rest.models.graph import Graph
|
@@ -17,9 +17,11 @@ import pprint
|
|
17
17
|
import re # noqa: F401
|
18
18
|
import json
|
19
19
|
|
20
|
-
from
|
20
|
+
from datetime import datetime
|
21
|
+
from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator
|
21
22
|
from typing import Any, ClassVar, Dict, List, Optional
|
22
|
-
from hiddenlayer.sdk.rest.models.
|
23
|
+
from hiddenlayer.sdk.rest.models.file_details_v3 import FileDetailsV3
|
24
|
+
from hiddenlayer.sdk.rest.models.scan_detection_v3 import ScanDetectionV3
|
23
25
|
from typing import Optional, Set
|
24
26
|
from typing_extensions import Self
|
25
27
|
|
@@ -27,8 +29,23 @@ class FileScanReportV3(BaseModel):
|
|
27
29
|
"""
|
28
30
|
FileScanReportV3
|
29
31
|
""" # noqa: E501
|
30
|
-
|
31
|
-
|
32
|
+
file_instance_id: StrictStr = Field(description="unique ID of the file")
|
33
|
+
file_location: StrictStr = Field(description="full file path")
|
34
|
+
start_time: datetime = Field(description="time the scan started")
|
35
|
+
end_time: datetime = Field(description="time the scan ended")
|
36
|
+
details: FileDetailsV3
|
37
|
+
status: StrictStr = Field(description="status of the scan")
|
38
|
+
seen: datetime = Field(description="time the scan was seen at")
|
39
|
+
detections: Optional[List[ScanDetectionV3]] = None
|
40
|
+
file_results: Optional[List[FileScanReportV3]] = None
|
41
|
+
__properties: ClassVar[List[str]] = ["file_instance_id", "file_location", "start_time", "end_time", "details", "status", "seen", "detections", "file_results"]
|
42
|
+
|
43
|
+
@field_validator('status')
|
44
|
+
def status_validate_enum(cls, value):
|
45
|
+
"""Validates the enum"""
|
46
|
+
if value not in set(['skipped', 'pending', 'running', 'done', 'failed', 'canceled']):
|
47
|
+
raise ValueError("must be one of enum values ('skipped', 'pending', 'running', 'done', 'failed', 'canceled')")
|
48
|
+
return value
|
32
49
|
|
33
50
|
model_config = ConfigDict(
|
34
51
|
populate_by_name=True,
|
@@ -69,6 +86,16 @@ class FileScanReportV3(BaseModel):
|
|
69
86
|
exclude=excluded_fields,
|
70
87
|
exclude_none=True,
|
71
88
|
)
|
89
|
+
# override the default output from pydantic by calling `to_dict()` of details
|
90
|
+
if self.details:
|
91
|
+
_dict['details'] = self.details.to_dict()
|
92
|
+
# override the default output from pydantic by calling `to_dict()` of each item in detections (list)
|
93
|
+
_items = []
|
94
|
+
if self.detections:
|
95
|
+
for _item in self.detections:
|
96
|
+
if _item:
|
97
|
+
_items.append(_item.to_dict())
|
98
|
+
_dict['detections'] = _items
|
72
99
|
# override the default output from pydantic by calling `to_dict()` of each item in file_results (list)
|
73
100
|
_items = []
|
74
101
|
if self.file_results:
|
@@ -88,8 +115,18 @@ class FileScanReportV3(BaseModel):
|
|
88
115
|
return cls.model_validate(obj)
|
89
116
|
|
90
117
|
_obj = cls.model_validate({
|
91
|
-
"
|
118
|
+
"file_instance_id": obj.get("file_instance_id"),
|
119
|
+
"file_location": obj.get("file_location"),
|
120
|
+
"start_time": obj.get("start_time"),
|
121
|
+
"end_time": obj.get("end_time"),
|
122
|
+
"details": FileDetailsV3.from_dict(obj["details"]) if obj.get("details") is not None else None,
|
123
|
+
"status": obj.get("status"),
|
124
|
+
"seen": obj.get("seen"),
|
125
|
+
"detections": [ScanDetectionV3.from_dict(_item) for _item in obj["detections"]] if obj.get("detections") is not None else None,
|
126
|
+
"file_results": [FileScanReportV3.from_dict(_item) for _item in obj["file_results"]] if obj.get("file_results") is not None else None
|
92
127
|
})
|
93
128
|
return _obj
|
94
129
|
|
130
|
+
# TODO: Rewrite to not use raise_errors
|
131
|
+
FileScanReportV3.model_rebuild(raise_errors=False)
|
95
132
|
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
"""
|
4
|
+
HiddenLayer ModelScan V2
|
5
|
+
|
6
|
+
HiddenLayer ModelScan API for scanning of models
|
7
|
+
|
8
|
+
The version of the OpenAPI document: 1
|
9
|
+
Generated by OpenAPI Generator (https://openapi-generator.tech)
|
10
|
+
|
11
|
+
Do not edit the class manually.
|
12
|
+
""" # noqa: E501
|
13
|
+
|
14
|
+
|
15
|
+
from __future__ import annotations
|
16
|
+
import pprint
|
17
|
+
import re # noqa: F401
|
18
|
+
import json
|
19
|
+
|
20
|
+
from pydantic import BaseModel, ConfigDict
|
21
|
+
from typing import Any, ClassVar, Dict, List, Optional
|
22
|
+
from hiddenlayer.sdk.rest.models.file_scan_report_v3 import FileScanReportV3
|
23
|
+
from typing import Optional, Set
|
24
|
+
from typing_extensions import Self
|
25
|
+
|
26
|
+
class FileScanReportsV3(BaseModel):
|
27
|
+
"""
|
28
|
+
FileScanReportsV3
|
29
|
+
""" # noqa: E501
|
30
|
+
file_results: Optional[List[FileScanReportV3]] = None
|
31
|
+
__properties: ClassVar[List[str]] = ["file_results"]
|
32
|
+
|
33
|
+
model_config = ConfigDict(
|
34
|
+
populate_by_name=True,
|
35
|
+
validate_assignment=True,
|
36
|
+
protected_namespaces=(),
|
37
|
+
)
|
38
|
+
|
39
|
+
|
40
|
+
def to_str(self) -> str:
|
41
|
+
"""Returns the string representation of the model using alias"""
|
42
|
+
return pprint.pformat(self.model_dump(by_alias=True))
|
43
|
+
|
44
|
+
def to_json(self) -> str:
|
45
|
+
"""Returns the JSON representation of the model using alias"""
|
46
|
+
# TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
|
47
|
+
return json.dumps(self.to_dict())
|
48
|
+
|
49
|
+
@classmethod
|
50
|
+
def from_json(cls, json_str: str) -> Optional[Self]:
|
51
|
+
"""Create an instance of FileScanReportsV3 from a JSON string"""
|
52
|
+
return cls.from_dict(json.loads(json_str))
|
53
|
+
|
54
|
+
def to_dict(self) -> Dict[str, Any]:
|
55
|
+
"""Return the dictionary representation of the model using alias.
|
56
|
+
|
57
|
+
This has the following differences from calling pydantic's
|
58
|
+
`self.model_dump(by_alias=True)`:
|
59
|
+
|
60
|
+
* `None` is only added to the output dict for nullable fields that
|
61
|
+
were set at model initialization. Other fields with value `None`
|
62
|
+
are ignored.
|
63
|
+
"""
|
64
|
+
excluded_fields: Set[str] = set([
|
65
|
+
])
|
66
|
+
|
67
|
+
_dict = self.model_dump(
|
68
|
+
by_alias=True,
|
69
|
+
exclude=excluded_fields,
|
70
|
+
exclude_none=True,
|
71
|
+
)
|
72
|
+
# override the default output from pydantic by calling `to_dict()` of each item in file_results (list)
|
73
|
+
_items = []
|
74
|
+
if self.file_results:
|
75
|
+
for _item in self.file_results:
|
76
|
+
if _item:
|
77
|
+
_items.append(_item.to_dict())
|
78
|
+
_dict['file_results'] = _items
|
79
|
+
return _dict
|
80
|
+
|
81
|
+
@classmethod
|
82
|
+
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
|
83
|
+
"""Create an instance of FileScanReportsV3 from a dict"""
|
84
|
+
if obj is None:
|
85
|
+
return None
|
86
|
+
|
87
|
+
if not isinstance(obj, dict):
|
88
|
+
return cls.model_validate(obj)
|
89
|
+
|
90
|
+
_obj = cls.model_validate({
|
91
|
+
"file_results": [FileScanReportV3.from_dict(_item) for _item in obj["file_results"]] if obj.get("file_results") is not None else None
|
92
|
+
})
|
93
|
+
return _obj
|
94
|
+
|
95
|
+
|
@@ -20,7 +20,7 @@ import json
|
|
20
20
|
from datetime import datetime
|
21
21
|
from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr, field_validator
|
22
22
|
from typing import Any, ClassVar, Dict, List, Optional
|
23
|
-
from hiddenlayer.sdk.rest.models.
|
23
|
+
from hiddenlayer.sdk.rest.models.file_scan_report_v3 import FileScanReportV3
|
24
24
|
from hiddenlayer.sdk.rest.models.model_inventory_info import ModelInventoryInfo
|
25
25
|
from typing import Optional, Set
|
26
26
|
from typing_extensions import Self
|
@@ -40,7 +40,7 @@ class ScanReportV3(BaseModel):
|
|
40
40
|
end_time: Optional[datetime] = Field(default=None, description="time the scan ended")
|
41
41
|
status: StrictStr = Field(description="status of the scan")
|
42
42
|
severity: Optional[StrictStr] = Field(default=None, description="detection severity")
|
43
|
-
file_results: Optional[List[
|
43
|
+
file_results: Optional[List[FileScanReportV3]] = None
|
44
44
|
__properties: ClassVar[List[str]] = ["file_count", "files_with_detections_count", "detection_count", "detection_categories", "inventory", "version", "scan_id", "start_time", "end_time", "status", "severity", "file_results"]
|
45
45
|
|
46
46
|
@field_validator('status')
|
@@ -132,7 +132,7 @@ class ScanReportV3(BaseModel):
|
|
132
132
|
"end_time": obj.get("end_time"),
|
133
133
|
"status": obj.get("status"),
|
134
134
|
"severity": obj.get("severity"),
|
135
|
-
"file_results": [
|
135
|
+
"file_results": [FileScanReportV3.from_dict(_item) for _item in obj["file_results"]] if obj.get("file_results") is not None else None
|
136
136
|
})
|
137
137
|
return _obj
|
138
138
|
|
@@ -28,7 +28,7 @@ class SensorSORModelCardResponse(BaseModel):
|
|
28
28
|
SensorSORModelCardResponse
|
29
29
|
""" # noqa: E501
|
30
30
|
model_id: StrictStr
|
31
|
-
created_at: StrictInt = Field(description="Unix
|
31
|
+
created_at: StrictInt = Field(description="Unix Nano Epoch")
|
32
32
|
plaintext_name: StrictStr
|
33
33
|
active_versions: List[StrictInt]
|
34
34
|
source: StrictStr
|
@@ -1,4 +1,6 @@
|
|
1
1
|
import json
|
2
|
+
import random
|
3
|
+
import time
|
2
4
|
from typing import Optional
|
3
5
|
|
4
6
|
from hiddenlayer.sdk.constants import ApiErrors
|
@@ -37,6 +39,49 @@ class ModelAPI:
|
|
37
39
|
)
|
38
40
|
)
|
39
41
|
|
42
|
+
def create_or_get(self, *, model_name: str, model_version: Optional[int]) -> Model:
|
43
|
+
"""
|
44
|
+
Creates a model in the HiddenLayer Platform if it does not exist.
|
45
|
+
If the model and version already exists, returns the existing model.
|
46
|
+
|
47
|
+
:params model_name: Name of the model
|
48
|
+
:params model_version: Version of the model
|
49
|
+
|
50
|
+
:returns: HiddenLayer ModelID
|
51
|
+
"""
|
52
|
+
try:
|
53
|
+
return self.create(model_name=model_name, model_version=model_version)
|
54
|
+
except ApiException as e:
|
55
|
+
if e.status == 400 and str(e.body).find(ApiErrors.SENSOR_EXISTS) != -1:
|
56
|
+
return self.get_with_retry(
|
57
|
+
model_name=model_name, version=model_version, retry=3
|
58
|
+
)
|
59
|
+
else:
|
60
|
+
raise e
|
61
|
+
|
62
|
+
def get_with_retry(
|
63
|
+
self, *, model_name: str, version: Optional[int], retry: int
|
64
|
+
) -> Model:
|
65
|
+
"""
|
66
|
+
Gets a HiddenLayer model object. If not version is supplied, the latest model is returned.
|
67
|
+
Retries if the model is not found.
|
68
|
+
|
69
|
+
:param model_name: Name of the model.
|
70
|
+
:param version: Version of the model to get.
|
71
|
+
:param retry: Number of retries
|
72
|
+
|
73
|
+
:returns: HiddenLayer Model object
|
74
|
+
"""
|
75
|
+
|
76
|
+
base_delay = 0.1 # seconds
|
77
|
+
for retryCount in range(retry):
|
78
|
+
try:
|
79
|
+
return self.get(model_name=model_name, version=version)
|
80
|
+
except ModelDoesNotExistError:
|
81
|
+
time.sleep(base_delay * 2**retryCount + random.uniform(0, 1))
|
82
|
+
pass
|
83
|
+
raise ModelDoesNotExistError(f"Model {model_name} does not exist")
|
84
|
+
|
40
85
|
def get(self, *, model_name: str, version: Optional[int] = None) -> Model:
|
41
86
|
"""
|
42
87
|
Gets a HiddenLayer model object. If not version is supplied, the latest model is returned.
|
@@ -90,7 +135,7 @@ class ModelAPI:
|
|
90
135
|
)
|
91
136
|
)
|
92
137
|
|
93
|
-
if not models.results:
|
138
|
+
if not models.results or len(models.results) == 0:
|
94
139
|
msg = f"Model {model_name} does not exist"
|
95
140
|
|
96
141
|
if version:
|
@@ -70,7 +70,7 @@ class ModelScanAPI:
|
|
70
70
|
file_path = Path(model_path)
|
71
71
|
|
72
72
|
filesize = file_path.stat().st_size
|
73
|
-
sensor = self._model_api.
|
73
|
+
sensor = self._model_api.create_or_get(
|
74
74
|
model_name=model_name, model_version=model_version
|
75
75
|
)
|
76
76
|
upload = self._sensor_api.begin_multipart_upload(sensor.sensor_id, filesize)
|
hiddenlayer/sdk/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
VERSION = "1.
|
1
|
+
VERSION = "1.1.0"
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.2
|
2
2
|
Name: hiddenlayer-sdk
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.1.0
|
4
4
|
Summary: Official HiddenLayer Python SDK
|
5
5
|
Author-email: HiddenLayer Integrations Team <integrations@hiddenlayer.com>
|
6
6
|
Maintainer-email: HiddenLayer Integrations Team <integrations@hiddenlayer.com>
|
@@ -1,11 +1,11 @@
|
|
1
1
|
hiddenlayer/__init__.py,sha256=Uik1ha6cV_6MkpB0zpKn6f7Zsw7q6W_sh3MgGq2M3vU,3582
|
2
2
|
hiddenlayer/sdk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
-
hiddenlayer/sdk/constants.py,sha256=
|
3
|
+
hiddenlayer/sdk/constants.py,sha256=QwBZAQdF7FW9q4C-O8LyxrpqfJFBBlqRUDMjnJ-ouZQ,320
|
4
4
|
hiddenlayer/sdk/exceptions.py,sha256=LNkD6AvSwNwQjnTDrvY152DmvPKzSejrBsIu-qI44Ec,225
|
5
|
-
hiddenlayer/sdk/models.py,sha256=
|
5
|
+
hiddenlayer/sdk/models.py,sha256=T6GJTFCfBQgBteR0pl0eyYzan-iIFOSpcnlmlCuuQwc,1836
|
6
6
|
hiddenlayer/sdk/utils.py,sha256=Ntao8hfsYuB7obZOanayIlrgJ98IWcPhs3sRi39IDkg,2997
|
7
|
-
hiddenlayer/sdk/version.py,sha256=
|
8
|
-
hiddenlayer/sdk/rest/__init__.py,sha256=
|
7
|
+
hiddenlayer/sdk/version.py,sha256=DFGnvNkISEu0RDsAfc03O0dRz9PfmIb63Kyi-am-trE,18
|
8
|
+
hiddenlayer/sdk/rest/__init__.py,sha256=Egcd1PM10KlYQww3y-HkVz0IqF3jnycvn5lYcE6uXVw,7809
|
9
9
|
hiddenlayer/sdk/rest/api_client.py,sha256=Zd_yX0nQq06z0Ome2KcsNUcETnOxzhQK9js53qsN7aI,26333
|
10
10
|
hiddenlayer/sdk/rest/api_response.py,sha256=eMxw1mpmJcoGZ3gs9z6jM4oYoZ10Gjk333s9sKxGv7s,652
|
11
11
|
hiddenlayer/sdk/rest/configuration.py,sha256=0AzoYBOp3MzQvM9R3AkUWTycx1I3bcvNtn759JQ0fLo,14747
|
@@ -17,8 +17,8 @@ hiddenlayer/sdk/rest/api/health_api.py,sha256=oKHVksIqs_Vt_aQK-n9ZcQfbwW06pVeiYJ
|
|
17
17
|
hiddenlayer/sdk/rest/api/model_scan_api.py,sha256=G32t9LzeDTCUF4QOMYYs3Vjm8bo0a2kZa3FXBAqPo6s,22047
|
18
18
|
hiddenlayer/sdk/rest/api/model_supply_chain_api.py,sha256=kyay-8hob2E5HoGJPFQXYuffsZOKrg4yJ_S3wMuW030,116057
|
19
19
|
hiddenlayer/sdk/rest/api/readiness_api.py,sha256=5SddYxvRA3GuwZ43DoVTRfPBeTkLXyBGbQtIdUyc2FA,10102
|
20
|
-
hiddenlayer/sdk/rest/api/sensor_api.py,sha256=
|
21
|
-
hiddenlayer/sdk/rest/models/__init__.py,sha256
|
20
|
+
hiddenlayer/sdk/rest/api/sensor_api.py,sha256=yEvLUOVkpHAxsMZdoLQLWUW1TimlpKJ1bkRjJsGsAcU,87527
|
21
|
+
hiddenlayer/sdk/rest/models/__init__.py,sha256=-SO-mMt_gSxn-3hRXPeekUXEMe9hweu-ihepPrMNjXU,6811
|
22
22
|
hiddenlayer/sdk/rest/models/address.py,sha256=amsl9GIcBhHswzfA8eQ0jbRw9zVEd6DmtDFSKRyQB9s,5285
|
23
23
|
hiddenlayer/sdk/rest/models/artifact.py,sha256=FSV-aFgOpyZU3khHkbWXajenYLi_Zfn153cZTlz6TAI,8138
|
24
24
|
hiddenlayer/sdk/rest/models/artifact_change.py,sha256=714PhIumUnwj1bBAtaFEFl78zoKbsiJfEGFQtkhFzgI,4136
|
@@ -37,8 +37,8 @@ hiddenlayer/sdk/rest/models/external_properties.py,sha256=_kr2izVVqjDaKAZYM9YljI
|
|
37
37
|
hiddenlayer/sdk/rest/models/external_property_file_reference.py,sha256=CYWp1dkeTyONFxgyL1s9lgEIrL_WRLfCHu2uesTo0hM,3741
|
38
38
|
hiddenlayer/sdk/rest/models/external_property_file_references.py,sha256=exYjkAMMKsWnj5PYAM9JvdrfnvoooeM1_-JKK0HEWtI,14776
|
39
39
|
hiddenlayer/sdk/rest/models/file_details_v3.py,sha256=jnIDdpjngvEP29GTvVAbuAlonaDiIlsorpBKfsk8iH8,5419
|
40
|
-
hiddenlayer/sdk/rest/models/
|
41
|
-
hiddenlayer/sdk/rest/models/
|
40
|
+
hiddenlayer/sdk/rest/models/file_scan_report_v3.py,sha256=SiHmoz13npUwPGxsfWtPIFhuFSBJ__l7MqnOcuUjKX8,5178
|
41
|
+
hiddenlayer/sdk/rest/models/file_scan_reports_v3.py,sha256=eF39zwE-TQjbY0ChH28NyKlF285QqcTX5Hoiwk78FqE,2996
|
42
42
|
hiddenlayer/sdk/rest/models/fix.py,sha256=IMGNyz-obFVq4xTNHxpwnlJhiSLI2ILg1XnmjrbqyFY,4397
|
43
43
|
hiddenlayer/sdk/rest/models/get_multipart_upload_response.py,sha256=mSg6L4R_CoTNKtCNV2wDvCTk0dEkW8E6ChrRjBbdaDc,3049
|
44
44
|
hiddenlayer/sdk/rest/models/graph.py,sha256=iMO4X58bcyPhrtMnnsVlRb2gbYtvkOoW8kLA7uwdQvM,4806
|
@@ -83,12 +83,12 @@ hiddenlayer/sdk/rest/models/scan_job_inventory.py,sha256=OV1KAy1czwndF7h-OZg4KYw
|
|
83
83
|
hiddenlayer/sdk/rest/models/scan_model_details_v3.py,sha256=U63IEpPWJNnZfKoW4-G51m05iXjwoT8cXyP3Va-x3NI,3195
|
84
84
|
hiddenlayer/sdk/rest/models/scan_model_ids_v3.py,sha256=FSJn2oVqEKd0YOF3xsKs1xnSgpYuVT5WBIEwAm5DcKY,2681
|
85
85
|
hiddenlayer/sdk/rest/models/scan_model_request.py,sha256=vjIE1onx_OTS-wcpuFWcPpMe-wp9IU1fM7oWVJxBkEk,2451
|
86
|
-
hiddenlayer/sdk/rest/models/scan_report_v3.py,sha256=
|
86
|
+
hiddenlayer/sdk/rest/models/scan_report_v3.py,sha256=C3dMv1ndMLGerBB1bWgYnG7cjS2BhucljsU8-Ne2YAA,5700
|
87
87
|
hiddenlayer/sdk/rest/models/scan_results.py,sha256=02__33uy5wf_LMDoJfaSnNr2wMv4b59IcVq9F9suWUA,4031
|
88
88
|
hiddenlayer/sdk/rest/models/scan_results_v2.py,sha256=-JCwgKrbjpAhye0uAQGq9rg2M6L6cHL3dqkoM_tmDnc,4494
|
89
89
|
hiddenlayer/sdk/rest/models/security_posture.py,sha256=QJAJzaqrL1R69-jUkLX8Hpjz7-aCw99doUIAgPR6n7w,2619
|
90
90
|
hiddenlayer/sdk/rest/models/sensor_sor_model_card_query_response.py,sha256=axRm4bobSm-VfsBS9qRLo5IBT07OXfej24lEY-u6z2s,3303
|
91
|
-
hiddenlayer/sdk/rest/models/sensor_sor_model_card_response.py,sha256
|
91
|
+
hiddenlayer/sdk/rest/models/sensor_sor_model_card_response.py,sha256=-tV9VWuN-bqOkOCuGcXT-QmKTqmeVe01jvEFt2Mmo0A,4694
|
92
92
|
hiddenlayer/sdk/rest/models/sensor_sor_query_filter.py,sha256=t1ZdI4iwNk-mPjGX1j1oVCwrJ9qMAmEkMAxVkDE38yg,3406
|
93
93
|
hiddenlayer/sdk/rest/models/sensor_sor_query_request.py,sha256=QdCmGShcIpQUVbFgLtzxtk9ucrmrwNfTLLwe78chuuY,3740
|
94
94
|
hiddenlayer/sdk/rest/models/special_locations.py,sha256=FU5Y9nHrth5hixkeleSkxB3a9ZYALC4TI8BQXV4tWCw,3322
|
@@ -109,10 +109,10 @@ hiddenlayer/sdk/rest/models/web_request.py,sha256=0LKMRsAIg7oVOPso8DiaFgfsozpdKv
|
|
109
109
|
hiddenlayer/sdk/rest/models/web_response.py,sha256=iwGQ5WjqAB4qGwe9nzGOwtxB1OSUc024pXSOaZM3Cdc,4746
|
110
110
|
hiddenlayer/sdk/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
111
111
|
hiddenlayer/sdk/services/aidr_predictive.py,sha256=aD2anFzWQzfLsR13NwwdQjt_X_iAlOkmss_yHy-154U,2958
|
112
|
-
hiddenlayer/sdk/services/model.py,sha256=
|
113
|
-
hiddenlayer/sdk/services/model_scan.py,sha256=
|
114
|
-
hiddenlayer_sdk-1.
|
115
|
-
hiddenlayer_sdk-1.
|
116
|
-
hiddenlayer_sdk-1.
|
117
|
-
hiddenlayer_sdk-1.
|
118
|
-
hiddenlayer_sdk-1.
|
112
|
+
hiddenlayer/sdk/services/model.py,sha256=qoVrwgL7E0raCUI0bNyim4SrmDEGBmcU1UaoJ-JNoCg,4871
|
113
|
+
hiddenlayer/sdk/services/model_scan.py,sha256=xGHveChHA6pHArSNF8YKXFOi0FqaH9BnzfuKC_6VyBY,17123
|
114
|
+
hiddenlayer_sdk-1.1.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
115
|
+
hiddenlayer_sdk-1.1.0.dist-info/METADATA,sha256=8M5hvwdG5HDkwRvIAiKDQJf3vSGCoex7itoWrd8baUk,17342
|
116
|
+
hiddenlayer_sdk-1.1.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
117
|
+
hiddenlayer_sdk-1.1.0.dist-info/top_level.txt,sha256=8BxcmGvEN1RqsMvTWg9Q0vDmtBGcTmatnme6nzyPj2U,12
|
118
|
+
hiddenlayer_sdk-1.1.0.dist-info/RECORD,,
|
@@ -1,121 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
"""
|
4
|
-
HiddenLayer ModelScan V2
|
5
|
-
|
6
|
-
HiddenLayer ModelScan API for scanning of models
|
7
|
-
|
8
|
-
The version of the OpenAPI document: 1
|
9
|
-
Generated by OpenAPI Generator (https://openapi-generator.tech)
|
10
|
-
|
11
|
-
Do not edit the class manually.
|
12
|
-
""" # noqa: E501
|
13
|
-
|
14
|
-
|
15
|
-
from __future__ import annotations
|
16
|
-
import pprint
|
17
|
-
import re # noqa: F401
|
18
|
-
import json
|
19
|
-
|
20
|
-
from datetime import datetime
|
21
|
-
from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator
|
22
|
-
from typing import Any, ClassVar, Dict, List, Optional
|
23
|
-
from hiddenlayer.sdk.rest.models.file_details_v3 import FileDetailsV3
|
24
|
-
from hiddenlayer.sdk.rest.models.scan_detection_v3 import ScanDetectionV3
|
25
|
-
from typing import Optional, Set
|
26
|
-
from typing_extensions import Self
|
27
|
-
|
28
|
-
class FileResultsInner(BaseModel):
|
29
|
-
"""
|
30
|
-
FileResultsInner
|
31
|
-
""" # noqa: E501
|
32
|
-
file_instance_id: StrictStr = Field(description="unique ID of the file")
|
33
|
-
file_location: StrictStr = Field(description="full file path")
|
34
|
-
start_time: datetime = Field(description="time the scan started")
|
35
|
-
end_time: datetime = Field(description="time the scan ended")
|
36
|
-
details: FileDetailsV3
|
37
|
-
status: StrictStr = Field(description="status of the scan")
|
38
|
-
seen: datetime = Field(description="time the scan was seen at")
|
39
|
-
detections: Optional[List[ScanDetectionV3]] = None
|
40
|
-
__properties: ClassVar[List[str]] = ["file_instance_id", "file_location", "start_time", "end_time", "details", "status", "seen", "detections"]
|
41
|
-
|
42
|
-
@field_validator('status')
|
43
|
-
def status_validate_enum(cls, value):
|
44
|
-
"""Validates the enum"""
|
45
|
-
if value not in set(['skipped', 'pending', 'running', 'done', 'failed', 'canceled']):
|
46
|
-
raise ValueError("must be one of enum values ('skipped', 'pending', 'running', 'done', 'failed', 'canceled')")
|
47
|
-
return value
|
48
|
-
|
49
|
-
model_config = ConfigDict(
|
50
|
-
populate_by_name=True,
|
51
|
-
validate_assignment=True,
|
52
|
-
protected_namespaces=(),
|
53
|
-
)
|
54
|
-
|
55
|
-
|
56
|
-
def to_str(self) -> str:
|
57
|
-
"""Returns the string representation of the model using alias"""
|
58
|
-
return pprint.pformat(self.model_dump(by_alias=True))
|
59
|
-
|
60
|
-
def to_json(self) -> str:
|
61
|
-
"""Returns the JSON representation of the model using alias"""
|
62
|
-
# TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
|
63
|
-
return json.dumps(self.to_dict())
|
64
|
-
|
65
|
-
@classmethod
|
66
|
-
def from_json(cls, json_str: str) -> Optional[Self]:
|
67
|
-
"""Create an instance of FileResultsInner from a JSON string"""
|
68
|
-
return cls.from_dict(json.loads(json_str))
|
69
|
-
|
70
|
-
def to_dict(self) -> Dict[str, Any]:
|
71
|
-
"""Return the dictionary representation of the model using alias.
|
72
|
-
|
73
|
-
This has the following differences from calling pydantic's
|
74
|
-
`self.model_dump(by_alias=True)`:
|
75
|
-
|
76
|
-
* `None` is only added to the output dict for nullable fields that
|
77
|
-
were set at model initialization. Other fields with value `None`
|
78
|
-
are ignored.
|
79
|
-
"""
|
80
|
-
excluded_fields: Set[str] = set([
|
81
|
-
])
|
82
|
-
|
83
|
-
_dict = self.model_dump(
|
84
|
-
by_alias=True,
|
85
|
-
exclude=excluded_fields,
|
86
|
-
exclude_none=True,
|
87
|
-
)
|
88
|
-
# override the default output from pydantic by calling `to_dict()` of details
|
89
|
-
if self.details:
|
90
|
-
_dict['details'] = self.details.to_dict()
|
91
|
-
# override the default output from pydantic by calling `to_dict()` of each item in detections (list)
|
92
|
-
_items = []
|
93
|
-
if self.detections:
|
94
|
-
for _item in self.detections:
|
95
|
-
if _item:
|
96
|
-
_items.append(_item.to_dict())
|
97
|
-
_dict['detections'] = _items
|
98
|
-
return _dict
|
99
|
-
|
100
|
-
@classmethod
|
101
|
-
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
|
102
|
-
"""Create an instance of FileResultsInner from a dict"""
|
103
|
-
if obj is None:
|
104
|
-
return None
|
105
|
-
|
106
|
-
if not isinstance(obj, dict):
|
107
|
-
return cls.model_validate(obj)
|
108
|
-
|
109
|
-
_obj = cls.model_validate({
|
110
|
-
"file_instance_id": obj.get("file_instance_id"),
|
111
|
-
"file_location": obj.get("file_location"),
|
112
|
-
"start_time": obj.get("start_time"),
|
113
|
-
"end_time": obj.get("end_time"),
|
114
|
-
"details": FileDetailsV3.from_dict(obj["details"]) if obj.get("details") is not None else None,
|
115
|
-
"status": obj.get("status"),
|
116
|
-
"seen": obj.get("seen"),
|
117
|
-
"detections": [ScanDetectionV3.from_dict(_item) for _item in obj["detections"]] if obj.get("detections") is not None else None
|
118
|
-
})
|
119
|
-
return _obj
|
120
|
-
|
121
|
-
|
File without changes
|
File without changes
|