stepxmlclient 1.0.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.
Files changed (70) hide show
  1. stepxmlclient/__init__.py +22 -0
  2. stepxmlclient/client.py +373 -0
  3. stepxmlclient/creator.py +317 -0
  4. stepxmlclient/model/__init__.py +418 -0
  5. stepxmlclient/model/asset.py +250 -0
  6. stepxmlclient/model/attribute.py +288 -0
  7. stepxmlclient/model/business.py +233 -0
  8. stepxmlclient/model/classification.py +409 -0
  9. stepxmlclient/model/complex_elements.py +260 -0
  10. stepxmlclient/model/deletion.py +87 -0
  11. stepxmlclient/model/entity.py +368 -0
  12. stepxmlclient/model/metadata.py +199 -0
  13. stepxmlclient/model/organization.py +167 -0
  14. stepxmlclient/model/product.py +519 -0
  15. stepxmlclient/model/relations.py +105 -0
  16. stepxmlclient/model/replacement.py +417 -0
  17. stepxmlclient/parser.py +2805 -0
  18. stepxmlclient/rest_client/__init__.py +16 -0
  19. stepxmlclient/rest_client/base.py +388 -0
  20. stepxmlclient/rest_client/client.py +127 -0
  21. stepxmlclient/rest_client/exceptions.py +97 -0
  22. stepxmlclient/rest_client/models/__init__.py +175 -0
  23. stepxmlclient/rest_client/models/asset.py +253 -0
  24. stepxmlclient/rest_client/models/attribute.py +112 -0
  25. stepxmlclient/rest_client/models/background_process.py +23 -0
  26. stepxmlclient/rest_client/models/batch.py +41 -0
  27. stepxmlclient/rest_client/models/classification.py +57 -0
  28. stepxmlclient/rest_client/models/collection.py +26 -0
  29. stepxmlclient/rest_client/models/common.py +192 -0
  30. stepxmlclient/rest_client/models/context.py +16 -0
  31. stepxmlclient/rest_client/models/data_type_group.py +15 -0
  32. stepxmlclient/rest_client/models/entity.py +63 -0
  33. stepxmlclient/rest_client/models/event_processor.py +15 -0
  34. stepxmlclient/rest_client/models/import_export.py +43 -0
  35. stepxmlclient/rest_client/models/integration_endpoint.py +16 -0
  36. stepxmlclient/rest_client/models/product.py +200 -0
  37. stepxmlclient/rest_client/models/relations.py +280 -0
  38. stepxmlclient/rest_client/models/system_information.py +11 -0
  39. stepxmlclient/rest_client/models/user.py +28 -0
  40. stepxmlclient/rest_client/models/workflow.py +30 -0
  41. stepxmlclient/rest_client/operations/__init__.py +54 -0
  42. stepxmlclient/rest_client/operations/assets.py +652 -0
  43. stepxmlclient/rest_client/operations/attributes.py +252 -0
  44. stepxmlclient/rest_client/operations/background_processes.py +84 -0
  45. stepxmlclient/rest_client/operations/batch.py +28 -0
  46. stepxmlclient/rest_client/operations/classifications.py +248 -0
  47. stepxmlclient/rest_client/operations/collection_groups.py +46 -0
  48. stepxmlclient/rest_client/operations/collections.py +67 -0
  49. stepxmlclient/rest_client/operations/contexts.py +88 -0
  50. stepxmlclient/rest_client/operations/data_type_groups.py +68 -0
  51. stepxmlclient/rest_client/operations/entities.py +295 -0
  52. stepxmlclient/rest_client/operations/event_processors.py +109 -0
  53. stepxmlclient/rest_client/operations/exports.py +153 -0
  54. stepxmlclient/rest_client/operations/gateway.py +53 -0
  55. stepxmlclient/rest_client/operations/inbound.py +472 -0
  56. stepxmlclient/rest_client/operations/outbound.py +64 -0
  57. stepxmlclient/rest_client/operations/products.py +489 -0
  58. stepxmlclient/rest_client/operations/relations.py +349 -0
  59. stepxmlclient/rest_client/operations/reports.py +27 -0
  60. stepxmlclient/rest_client/operations/system_information.py +28 -0
  61. stepxmlclient/rest_client/operations/user_groups.py +79 -0
  62. stepxmlclient/rest_client/operations/users.py +119 -0
  63. stepxmlclient/rest_client/operations/workflow_tasks.py +61 -0
  64. stepxmlclient/rest_client/operations/workflows.py +50 -0
  65. stepxmlclient/upload.py +293 -0
  66. stepxmlclient-1.0.0.dist-info/METADATA +666 -0
  67. stepxmlclient-1.0.0.dist-info/RECORD +70 -0
  68. stepxmlclient-1.0.0.dist-info/WHEEL +5 -0
  69. stepxmlclient-1.0.0.dist-info/licenses/LICENSE +21 -0
  70. stepxmlclient-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,252 @@
1
+ """Attribute and type-definition operations for STEP REST API v2.
2
+
3
+ Covers Attributes, Lists of Values, Data Container Types, Data Type Groups,
4
+ Object Types, Reference Types, Units, and Unique Keys per the OpenAPI spec.
5
+ """
6
+
7
+ import logging
8
+ from typing import Any, Optional
9
+
10
+ from ..base import BaseOperation, handle_rest_errors
11
+ from ..exceptions import NotFoundError
12
+ from ..models.attribute import (
13
+ AttributeResponse,
14
+ ListOfValueResponse,
15
+ )
16
+
17
+
18
+ class AttributeOperations(BaseOperation):
19
+ """Operations for STEP Attributes and type definitions.
20
+
21
+ Note: The STEP REST API v2 (v1.4.0) only provides GET access for attribute
22
+ and type-definition resources. There is no create, update, or delete for
23
+ attributes via the REST API.
24
+ """
25
+
26
+ def __init__(self, client, logger: Optional[logging.Logger] = None,
27
+ context: str | None = None, workspace: str | None = None):
28
+ super().__init__(client, operation_name="AttributeOperations", logger=logger,
29
+ context=context, workspace=workspace)
30
+
31
+ # ------------------------------------------------------------------
32
+ # Attributes (tag: Attributes)
33
+ # ------------------------------------------------------------------
34
+
35
+ @handle_rest_errors
36
+ def get_attribute(self, attribute_id: str) -> AttributeResponse:
37
+ """Get a single attribute definition by ID.
38
+
39
+ Calls: GET /attributes/{id} → getAttribute
40
+
41
+ Args:
42
+ attribute_id: The attribute ID
43
+
44
+ Returns:
45
+ AttributeResponse with attribute definition
46
+
47
+ Raises:
48
+ ValidationError: If attribute_id is missing
49
+ NotFoundError: If attribute not found
50
+ """
51
+ self._validate_required_params(
52
+ {"attribute_id": attribute_id},
53
+ ["attribute_id"]
54
+ )
55
+ self._log_operation("getAttribute", {"id": attribute_id})
56
+
57
+ try:
58
+ response = self.client.getAttribute(id=attribute_id, **self._build_context_params())
59
+ except Exception as e:
60
+ if "404" in str(e):
61
+ raise NotFoundError(attribute_id, "Attribute")
62
+ raise
63
+
64
+ if isinstance(response, dict):
65
+ return AttributeResponse(**response)
66
+ return response
67
+
68
+ # ------------------------------------------------------------------
69
+ # Lists Of Values (tag: Lists Of Values)
70
+ # ------------------------------------------------------------------
71
+
72
+ @handle_rest_errors
73
+ def get_list_of_values(self, lov_id: str) -> ListOfValueResponse:
74
+ """Get a List of Values by ID.
75
+
76
+ Calls: GET /lists-of-values/{id} → getListOfValuess
77
+
78
+ Args:
79
+ lov_id: The LOV ID
80
+
81
+ Returns:
82
+ ListOfValueResponse with LOV data
83
+
84
+ Raises:
85
+ ValidationError: If lov_id is missing
86
+ NotFoundError: If LOV not found
87
+ """
88
+ self._validate_required_params(
89
+ {"lov_id": lov_id},
90
+ ["lov_id"]
91
+ )
92
+ self._log_operation("getListOfValuess", {"id": lov_id})
93
+
94
+ try:
95
+ response = self.client.getListOfValuess(id=lov_id, **self._build_context_params())
96
+ except Exception as e:
97
+ if "404" in str(e):
98
+ raise NotFoundError(lov_id, "ListOfValues")
99
+ raise
100
+
101
+ if isinstance(response, dict):
102
+ return ListOfValueResponse(**response)
103
+ return response
104
+
105
+ @handle_rest_errors
106
+ def get_list_of_values_entries(self, lov_id: str) -> list[dict[str, Any]]:
107
+ """Get the value entries for a List of Values.
108
+
109
+ Calls: GET /lists-of-values/{id}/value-entries → getListOfValuessEntries
110
+
111
+ Args:
112
+ lov_id: The LOV ID
113
+
114
+ Returns:
115
+ List of value entry dictionaries
116
+
117
+ Raises:
118
+ ValidationError: If lov_id is missing
119
+ NotFoundError: If LOV not found
120
+ """
121
+ self._validate_required_params(
122
+ {"lov_id": lov_id},
123
+ ["lov_id"]
124
+ )
125
+ self._log_operation("getListOfValuessEntries", {"id": lov_id})
126
+
127
+ try:
128
+ response = self.client.getListOfValuessEntries(id=lov_id, **self._build_context_params())
129
+ except Exception as e:
130
+ if "404" in str(e):
131
+ raise NotFoundError(lov_id, "ListOfValues")
132
+ raise
133
+
134
+ return self._coerce_list_payload(response)
135
+
136
+ # ------------------------------------------------------------------
137
+ # Type definitions (various tags — read-only single GET each)
138
+ # ------------------------------------------------------------------
139
+
140
+ @handle_rest_errors
141
+ def get_data_container_type(self, type_id: str) -> dict[str, Any]:
142
+ """Get a data container type definition by ID.
143
+
144
+ Calls: GET /data-container-types/{id} → getDataContainerType
145
+ """
146
+ self._validate_required_params({"type_id": type_id}, ["type_id"])
147
+ self._log_operation("getDataContainerType", {"id": type_id})
148
+ try:
149
+ response = self.client.getDataContainerType(id=type_id, **self._build_context_params())
150
+ except Exception as e:
151
+ if "404" in str(e):
152
+ raise NotFoundError(type_id, "DataContainerType")
153
+ raise
154
+ return response if isinstance(response, dict) else response
155
+
156
+ @handle_rest_errors
157
+ def get_data_type_group(self, group_id: str) -> dict[str, Any]:
158
+ """Get a data type group definition by ID.
159
+
160
+ Calls: GET /data-type-groups/{id} → getDataTypeGroup
161
+ """
162
+ self._validate_required_params({"group_id": group_id}, ["group_id"])
163
+ self._log_operation("getDataTypeGroup", {"id": group_id})
164
+ try:
165
+ response = self.client.getDataTypeGroup(id=group_id, **self._build_context_params())
166
+ except Exception as e:
167
+ if "404" in str(e):
168
+ raise NotFoundError(group_id, "DataTypeGroup")
169
+ raise
170
+ return response if isinstance(response, dict) else response
171
+
172
+ @handle_rest_errors
173
+ def get_object_type(self, type_id: str) -> dict[str, Any]:
174
+ """Get an object type definition by ID.
175
+
176
+ Calls: GET /object-types/{id} → getObjectType
177
+ """
178
+ self._validate_required_params({"type_id": type_id}, ["type_id"])
179
+ self._log_operation("getObjectType", {"id": type_id})
180
+ try:
181
+ response = self.client.getObjectType(id=type_id, **self._build_context_params())
182
+ except Exception as e:
183
+ if "404" in str(e):
184
+ raise NotFoundError(type_id, "ObjectType")
185
+ raise
186
+ return response if isinstance(response, dict) else response
187
+
188
+ @handle_rest_errors
189
+ def get_object_type_children(self, type_id: str) -> list[str]:
190
+ """Get child object types for a given object type.
191
+
192
+ Calls: GET /object-types/{id}/children → getObjectTypeChildren
193
+ """
194
+ self._validate_required_params({"type_id": type_id}, ["type_id"])
195
+ self._log_operation("getObjectTypeChildren", {"id": type_id})
196
+ try:
197
+ response = self.client.getObjectTypeChildren(id=type_id, **self._build_context_params())
198
+ except Exception as e:
199
+ if "404" in str(e):
200
+ raise NotFoundError(type_id, "ObjectType")
201
+ raise
202
+ if isinstance(response, list):
203
+ return response
204
+ return []
205
+
206
+ @handle_rest_errors
207
+ def get_reference_type(self, reference_type_id: str) -> dict[str, Any]:
208
+ """Get a reference type definition by ID.
209
+
210
+ Calls: GET /reference-types/{id} → getReferenceType
211
+ """
212
+ self._validate_required_params({"reference_type_id": reference_type_id}, ["reference_type_id"])
213
+ self._log_operation("getReferenceType", {"id": reference_type_id})
214
+ try:
215
+ response = self.client.getReferenceType(id=reference_type_id, **self._build_context_params())
216
+ except Exception as e:
217
+ if "404" in str(e):
218
+ raise NotFoundError(reference_type_id, "ReferenceType")
219
+ raise
220
+ return response if isinstance(response, dict) else response
221
+
222
+ @handle_rest_errors
223
+ def get_unit(self, unit_id: str) -> dict[str, Any]:
224
+ """Get a unit definition by ID.
225
+
226
+ Calls: GET /units/{id} → getUnit
227
+ """
228
+ self._validate_required_params({"unit_id": unit_id}, ["unit_id"])
229
+ self._log_operation("getUnit", {"id": unit_id})
230
+ try:
231
+ response = self.client.getUnit(id=unit_id, **self._build_context_params())
232
+ except Exception as e:
233
+ if "404" in str(e):
234
+ raise NotFoundError(unit_id, "Unit")
235
+ raise
236
+ return response if isinstance(response, dict) else response
237
+
238
+ @handle_rest_errors
239
+ def get_unique_key(self, key_id: str) -> dict[str, Any]:
240
+ """Get a unique key definition by ID.
241
+
242
+ Calls: GET /unique-keys/{id} → getUniqueKey
243
+ """
244
+ self._validate_required_params({"key_id": key_id}, ["key_id"])
245
+ self._log_operation("getUniqueKey", {"id": key_id})
246
+ try:
247
+ response = self.client.getUniqueKey(id=key_id, **self._build_context_params())
248
+ except Exception as e:
249
+ if "404" in str(e):
250
+ raise NotFoundError(key_id, "UniqueKey")
251
+ raise
252
+ return response if isinstance(response, dict) else response
@@ -0,0 +1,84 @@
1
+ """Background process operations for STEP REST API v2."""
2
+
3
+ from typing import Any
4
+
5
+ from ..base import BaseOperation, handle_rest_errors
6
+ from ..exceptions import NotFoundError
7
+ from ..models.background_process import BackgroundProcessResponse
8
+
9
+
10
+ class BackgroundProcessOperations(BaseOperation):
11
+ def __init__(self, client, logger=None, context=None, workspace=None):
12
+ super().__init__(client, operation_name="BackgroundProcessOperations", logger=logger, context=context, workspace=workspace)
13
+
14
+ @handle_rest_errors
15
+ def get_background_process(self, process_id: str) -> BackgroundProcessResponse:
16
+ self._validate_required_params({"process_id": process_id}, ["process_id"])
17
+ self._log_operation("getBackgroundProcess", {"id": process_id})
18
+ try:
19
+ r = self.client.getBackgroundProcess(id=process_id, **self._build_context_params())
20
+ except Exception as e:
21
+ if "404" in str(e): raise NotFoundError(process_id, "BackgroundProcess")
22
+ raise
23
+ return BackgroundProcessResponse(**r) if isinstance(r, dict) else r
24
+
25
+ @handle_rest_errors
26
+ def get_execution_report(self, process_id: str) -> list[dict[str, Any]]:
27
+ self._validate_required_params({"process_id": process_id}, ["process_id"])
28
+ self._log_operation("getBackgroundProcessExecutionReport", {"id": process_id})
29
+ try:
30
+ r = self.client.getBackgroundProcessExecutionReport(id=process_id, **self._build_context_params())
31
+ except Exception as e:
32
+ if "404" in str(e): raise NotFoundError(process_id, "BackgroundProcess")
33
+ raise
34
+ return r if isinstance(r, list) else []
35
+
36
+ @handle_rest_errors
37
+ def get_attachments_metadata(self, process_id: str) -> list[dict[str, Any]]:
38
+ self._validate_required_params({"process_id": process_id}, ["process_id"])
39
+ self._log_operation("getBackgroundProcessAttachmentsMetadata", {"id": process_id})
40
+ try:
41
+ r = self.client.getBackgroundProcessAttachmentsMetadata(id=process_id, **self._build_context_params())
42
+ except Exception as e:
43
+ if "404" in str(e): raise NotFoundError(process_id, "BackgroundProcess")
44
+ raise
45
+ return r if isinstance(r, list) else []
46
+
47
+ @handle_rest_errors
48
+ def get_attachment_metadata(self, process_id: str, attachment_id: str) -> BackgroundProcessResponse:
49
+ self._validate_required_params({"process_id": process_id, "attachment_id": attachment_id}, ["process_id", "attachment_id"])
50
+ self._log_operation("getBackgroundProcessAttachmentMetadata", {"id": process_id, "attachmentId": attachment_id})
51
+ try:
52
+ r = self.client.getBackgroundProcessAttachmentMetadata(id=process_id, attachmentId=attachment_id, **self._build_context_params())
53
+ except Exception as e:
54
+ if "404" in str(e): raise NotFoundError(process_id, "BackgroundProcess")
55
+ raise
56
+ return BackgroundProcessResponse(**r) if isinstance(r, dict) else r
57
+
58
+ @handle_rest_errors
59
+ def get_attachment_content(self, process_id: str, attachment_id: str) -> bytes:
60
+ self._validate_required_params({"process_id": process_id, "attachment_id": attachment_id}, ["process_id", "attachment_id"])
61
+ self._log_operation("getBackgroundProcessAttachmentContent", {"id": process_id, "attachmentId": attachment_id})
62
+ try:
63
+ r = self.client.getBackgroundProcessAttachmentContent(id=process_id, attachmentId=attachment_id, **self._build_context_params())
64
+ except Exception as e:
65
+ if "404" in str(e): raise NotFoundError(process_id, "BackgroundProcess")
66
+ raise
67
+ return r
68
+
69
+ @handle_rest_errors
70
+ def get_process_types(self) -> list[dict[str, Any]]:
71
+ self._log_operation("getBackgroundProcessTypes", {})
72
+ r = self.client.getBackgroundProcessTypes(**self._build_context_params())
73
+ return r if isinstance(r, list) else []
74
+
75
+ @handle_rest_errors
76
+ def get_processes_of_type(self, type_id: str) -> list[dict[str, Any]]:
77
+ self._validate_required_params({"type_id": type_id}, ["type_id"])
78
+ self._log_operation("getBackgroundProcessesOfType", {"typeId": type_id})
79
+ try:
80
+ r = self.client.getBackgroundProcessesOfType(typeId=type_id, **self._build_context_params())
81
+ except Exception as e:
82
+ if "404" in str(e): raise NotFoundError(type_id, "BackgroundProcessType")
83
+ raise
84
+ return r if isinstance(r, list) else []
@@ -0,0 +1,28 @@
1
+ """Batch operations for STEP REST API v2."""
2
+
3
+ from typing import Any
4
+
5
+ from ..base import BaseOperation, handle_rest_errors
6
+ from ..exceptions import ValidationError
7
+ from ..models.batch import BatchResponse
8
+
9
+
10
+ class BatchOperations(BaseOperation):
11
+ """Operations for STEP Batch execution."""
12
+ def __init__(self, client, logger=None, context=None, workspace=None):
13
+ super().__init__(client, operation_name="BatchOperations", logger=logger, context=context, workspace=workspace)
14
+
15
+ @handle_rest_errors
16
+ def execute_batch_operation(self, data: dict[str, Any]) -> BatchResponse:
17
+ """Execute a batch of operations.
18
+
19
+ Calls: POST /batch/execute -> executeBatchOperation
20
+ """
21
+ self._validate_required_params({"data": data}, ["data"])
22
+ self._log_operation("executeBatchOperation", {})
23
+ try:
24
+ r = self.client.executeBatchOperation(json=data, **self._build_context_params())
25
+ except Exception as e:
26
+ if "400" in str(e): raise ValidationError(str(e))
27
+ raise
28
+ return BatchResponse(**r) if isinstance(r, dict) else r
@@ -0,0 +1,248 @@
1
+ """Classification operations for STEP REST API v2."""
2
+
3
+ import logging
4
+ from typing import Any, Optional
5
+
6
+ from ..base import BaseOperation, handle_rest_errors
7
+ from ..exceptions import NotFoundError, ValidationError
8
+ from ..models.classification import ClassificationListResponse, ClassificationResponse
9
+
10
+
11
+ class ClassificationOperations(BaseOperation):
12
+ """Operations for STEP Classifications."""
13
+
14
+ def __init__(self, client, logger: Optional[logging.Logger] = None,
15
+ context: str | None = None, workspace: str | None = None):
16
+ """Initialize classification operations.
17
+
18
+ Args:
19
+ client: The REST API client
20
+ logger: Optional logger instance
21
+ context: STEP context ID for all API calls
22
+ workspace: STEP workspace ID (defaults to "Main" server-side)
23
+ """
24
+ super().__init__(client, operation_name="ClassificationOperations", logger=logger,
25
+ context=context, workspace=workspace)
26
+
27
+ @handle_rest_errors
28
+ def get_classification(self, classification_id: str,
29
+ key_id: str | None = None,
30
+ include_inherited_data: bool = False) -> ClassificationResponse:
31
+ """Get a single classification by ID.
32
+
33
+ Args:
34
+ classification_id: The classification ID (or alternate key value if key_id is set)
35
+ key_id: Alternate key ID to use for lookup (optional)
36
+ include_inherited_data: Whether to include inherited attribute values (default: False)
37
+
38
+ Returns:
39
+ ClassificationResponse with classification data
40
+
41
+ Raises:
42
+ ValidationError: If classification_id is missing
43
+ NotFoundError: If classification not found
44
+ RestApiError: For other API errors
45
+ """
46
+ self._validate_required_params(
47
+ {"classification_id": classification_id},
48
+ ["classification_id"]
49
+ )
50
+
51
+ query_params: dict[str, Any] = self._build_context_params()
52
+ if key_id:
53
+ query_params["keyId"] = key_id
54
+ if include_inherited_data:
55
+ query_params["includeInheritedData"] = include_inherited_data
56
+ self._log_operation("getClassification", {"classification_id": classification_id})
57
+
58
+ try:
59
+ response = self.client.getClassification(id=classification_id, **query_params)
60
+ except Exception as e:
61
+ if "404" in str(e):
62
+ raise NotFoundError(classification_id, "Classification")
63
+ raise
64
+
65
+ if isinstance(response, dict):
66
+ return ClassificationResponse(**response)
67
+ return response
68
+
69
+ @handle_rest_errors
70
+ def search_classifications(self, condition: dict) -> ClassificationListResponse:
71
+ """Search classifications using a STEP condition query.
72
+
73
+ Args:
74
+ condition: A STEP condition object defining the search criteria.
75
+ Supported conditionTypes: 'and', 'or', 'id', 'name',
76
+ 'textvalue', 'numericvalue', 'objecttype', 'simplebelow',
77
+ 'lovvalue', 'hasreferenceto', 'hasdatacontainerobject'.
78
+
79
+ Returns:
80
+ ClassificationListResponse with matching classifications
81
+
82
+ Raises:
83
+ ValidationError: If condition is invalid
84
+ RestApiError: For API errors
85
+ """
86
+ self._validate_required_params({"condition": condition}, ["condition"])
87
+ body = {"condition": condition}
88
+ self._log_operation("createClassificationSearch", {"condition": condition})
89
+
90
+ response = self.client.createClassificationSearch(json=body, **self._build_context_params())
91
+
92
+ if isinstance(response, dict):
93
+ return ClassificationListResponse(**response)
94
+ return response
95
+
96
+ def search_by_type(self, classification_type: str) -> ClassificationListResponse:
97
+ """Search classifications by object type (convenience method).
98
+
99
+ Args:
100
+ classification_type: The object type ID to filter by
101
+
102
+ Returns:
103
+ ClassificationListResponse filtered by type
104
+ """
105
+ return self.search_classifications(
106
+ condition={"conditionType": "objecttype", "objectType": classification_type}
107
+ )
108
+
109
+
110
+ @handle_rest_errors
111
+ def get_classification_approval_status(self, classification_id: str,
112
+ key_id: str | None = None) -> dict[str, Any]:
113
+ self._validate_required_params({"classification_id": classification_id}, ["classification_id"])
114
+ qp = self._build_context_params()
115
+ if key_id: qp["keyId"] = key_id
116
+ self._log_operation("getClassificationApprovalStatus", {"id": classification_id})
117
+ try:
118
+ r = self.client.getClassificationApprovalStatus(id=classification_id, **qp)
119
+ except Exception as e:
120
+ if "404" in str(e): raise NotFoundError(classification_id, "Classification")
121
+ raise
122
+ return r if isinstance(r, dict) else r
123
+
124
+ @handle_rest_errors
125
+ def approve_classification(self, classification_id: str,
126
+ key_id: str | None = None) -> dict[str, Any]:
127
+ self._validate_required_params({"classification_id": classification_id}, ["classification_id"])
128
+ qp = self._build_context_params()
129
+ if key_id: qp["keyId"] = key_id
130
+ self._log_operation("approveClassification", {"id": classification_id})
131
+ try:
132
+ r = self.client.approveClassification(id=classification_id, **qp)
133
+ except Exception as e:
134
+ if "404" in str(e): raise NotFoundError(classification_id, "Classification")
135
+ raise
136
+ return r if isinstance(r, dict) else r
137
+
138
+ @handle_rest_errors
139
+ def approve_classification_deletion(self, classification_id: str,
140
+ key_id: str | None = None) -> dict[str, Any]:
141
+ self._validate_required_params({"classification_id": classification_id}, ["classification_id"])
142
+ qp = self._build_context_params()
143
+ if key_id: qp["keyId"] = key_id
144
+ self._log_operation("approveClassificationDeletion", {"id": classification_id})
145
+ try:
146
+ r = self.client.approveClassificationDeletion(id=classification_id, **qp)
147
+ except Exception as e:
148
+ if "404" in str(e): raise NotFoundError(classification_id, "Classification")
149
+ raise
150
+ return r if isinstance(r, dict) else r
151
+
152
+ @handle_rest_errors
153
+ def purge_classification(self, classification_id: str,
154
+ key_id: str | None = None) -> dict[str, Any]:
155
+ self._validate_required_params({"classification_id": classification_id}, ["classification_id"])
156
+ qp = self._build_context_params()
157
+ if key_id: qp["keyId"] = key_id
158
+ self._log_operation("purgeClassification", {"id": classification_id})
159
+ try:
160
+ r = self.client.purgeClassification(id=classification_id, **qp)
161
+ except Exception as e:
162
+ if "404" in str(e): raise NotFoundError(classification_id, "Classification")
163
+ raise
164
+ return r if isinstance(r, dict) else r
165
+
166
+ @handle_rest_errors
167
+ def get_classification_assets(self, classification_id: str,
168
+ key_id: str | None = None) -> list[dict[str, Any]]:
169
+ self._validate_required_params({"classification_id": classification_id}, ["classification_id"])
170
+ qp = self._build_context_params()
171
+ if key_id: qp["keyId"] = key_id
172
+ self._log_operation("getClassificationAssets", {"id": classification_id})
173
+ try:
174
+ r = self.client.getClassificationAssets(id=classification_id, **qp)
175
+ except Exception as e:
176
+ if "404" in str(e): raise NotFoundError(classification_id, "Classification")
177
+ raise
178
+ return r if isinstance(r, list) else []
179
+
180
+ @handle_rest_errors
181
+ def get_classification_incoming_references(self, classification_id: str,
182
+ key_id: str | None = None) -> dict[str, Any]:
183
+ self._validate_required_params({"classification_id": classification_id}, ["classification_id"])
184
+ qp = self._build_context_params()
185
+ if key_id: qp["keyId"] = key_id
186
+ self._log_operation("getClassificationIncomingReferences", {"id": classification_id})
187
+ try:
188
+ r = self.client.getClassificationIncomingReferences(id=classification_id, **qp)
189
+ except Exception as e:
190
+ if "404" in str(e): raise NotFoundError(classification_id, "Classification")
191
+ raise
192
+ return r if isinstance(r, dict) else r
193
+
194
+ @handle_rest_errors
195
+ def get_classification_value(self, classification_id: str, attribute_id: str,
196
+ key_id: str | None = None) -> dict[str, Any]:
197
+ self._validate_required_params(
198
+ {"classification_id": classification_id, "attribute_id": attribute_id},
199
+ ["classification_id", "attribute_id"])
200
+ qp = self._build_context_params()
201
+ if key_id: qp["keyId"] = key_id
202
+ self._log_operation("getClassificationValueByAttributeId",
203
+ {"id": classification_id, "attributeId": attribute_id})
204
+ try:
205
+ r = self.client.getClassificationValueByAttributeId(
206
+ id=classification_id, attributeId=attribute_id, **qp)
207
+ except Exception as e:
208
+ if "404" in str(e): raise NotFoundError(classification_id, "Classification")
209
+ raise
210
+ return r if isinstance(r, dict) else r
211
+
212
+ @handle_rest_errors
213
+ def replace_classification_value(self, classification_id: str, attribute_id: str,
214
+ value: dict[str, Any],
215
+ key_id: str | None = None) -> dict[str, Any]:
216
+ self._validate_required_params(
217
+ {"classification_id": classification_id, "attribute_id": attribute_id},
218
+ ["classification_id", "attribute_id"])
219
+ qp = self._build_context_params()
220
+ if key_id: qp["keyId"] = key_id
221
+ self._log_operation("replaceClassificationValueByAttributeId",
222
+ {"id": classification_id, "attributeId": attribute_id})
223
+ try:
224
+ r = self.client.replaceClassificationValueByAttributeId(
225
+ id=classification_id, attributeId=attribute_id, json=value, **qp)
226
+ except Exception as e:
227
+ if "404" in str(e): raise NotFoundError(classification_id, "Classification")
228
+ if "400" in str(e): raise ValidationError(str(e))
229
+ raise
230
+ return r if isinstance(r, dict) else r
231
+
232
+ @handle_rest_errors
233
+ def delete_classification_value(self, classification_id: str, attribute_id: str,
234
+ key_id: str | None = None) -> bool:
235
+ self._validate_required_params(
236
+ {"classification_id": classification_id, "attribute_id": attribute_id},
237
+ ["classification_id", "attribute_id"])
238
+ qp = self._build_context_params()
239
+ if key_id: qp["keyId"] = key_id
240
+ self._log_operation("deleteClassificationValueByAttributeId",
241
+ {"id": classification_id, "attributeId": attribute_id})
242
+ try:
243
+ self.client.deleteClassificationValueByAttributeId(
244
+ id=classification_id, attributeId=attribute_id, **qp)
245
+ return True
246
+ except Exception as e:
247
+ if "404" in str(e): raise NotFoundError(classification_id, "Classification")
248
+ raise
@@ -0,0 +1,46 @@
1
+ """Collection group operations for STEP REST API v2."""
2
+
3
+ from typing import Any
4
+
5
+ from ..base import BaseOperation, handle_rest_errors
6
+ from ..exceptions import NotFoundError
7
+ from ..models.collection import CollectionGroupResponse
8
+
9
+
10
+ class CollectionGroupOperations(BaseOperation):
11
+ """Operations for STEP Collection Groups."""
12
+ def __init__(self, client, logger=None, context=None, workspace=None):
13
+ super().__init__(client, operation_name="CollectionGroupOperations", logger=logger, context=context, workspace=workspace)
14
+
15
+ @handle_rest_errors
16
+ def get_collection_group(self, group_id: str) -> CollectionGroupResponse:
17
+ self._validate_required_params({"group_id": group_id}, ["group_id"])
18
+ self._log_operation("getCollectionGroup", {"id": group_id})
19
+ try:
20
+ r = self.client.getCollectionGroup(id=group_id, **self._build_context_params())
21
+ except Exception as e:
22
+ if "404" in str(e): raise NotFoundError(group_id, "CollectionGroup")
23
+ raise
24
+ return CollectionGroupResponse(**r) if isinstance(r, dict) else r
25
+
26
+ @handle_rest_errors
27
+ def get_collection_group_children(self, group_id: str) -> list[str]:
28
+ self._validate_required_params({"group_id": group_id}, ["group_id"])
29
+ self._log_operation("getCollectionGroupChildren", {"id": group_id})
30
+ try:
31
+ r = self.client.getCollectionGroupChildren(id=group_id, **self._build_context_params())
32
+ except Exception as e:
33
+ if "404" in str(e): raise NotFoundError(group_id, "CollectionGroup")
34
+ raise
35
+ return r if isinstance(r, list) else []
36
+
37
+ @handle_rest_errors
38
+ def get_collection_group_collections(self, group_id: str) -> list[dict[str, Any]]:
39
+ self._validate_required_params({"group_id": group_id}, ["group_id"])
40
+ self._log_operation("getCollectionGroupCollections", {"id": group_id})
41
+ try:
42
+ r = self.client.getCollectionGroupCollections(id=group_id, **self._build_context_params())
43
+ except Exception as e:
44
+ if "404" in str(e): raise NotFoundError(group_id, "CollectionGroup")
45
+ raise
46
+ return r if isinstance(r, list) else []