autoassembler 0.3.1__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 (198) hide show
  1. autoassembler/.fernignore +7 -0
  2. autoassembler/__init__.py +537 -0
  3. autoassembler/_custom/__init__.py +56 -0
  4. autoassembler/_custom/assemblies.py +226 -0
  5. autoassembler/_custom/assemblies_api.py +188 -0
  6. autoassembler/_custom/credentials.py +248 -0
  7. autoassembler/_custom/http.py +42 -0
  8. autoassembler/_custom/operations.py +258 -0
  9. autoassembler/_custom/planning.py +598 -0
  10. autoassembler/_custom/planning_api.py +225 -0
  11. autoassembler/_default_clients.py +32 -0
  12. autoassembler/_version.py +8 -0
  13. autoassembler/alpha/__init__.py +63 -0
  14. autoassembler/alpha/client.py +82 -0
  15. autoassembler/alpha/jobs/__init__.py +39 -0
  16. autoassembler/alpha/jobs/client.py +338 -0
  17. autoassembler/alpha/jobs/raw_client.py +641 -0
  18. autoassembler/alpha/jobs/types/__init__.py +42 -0
  19. autoassembler/alpha/jobs/types/cancel_job_jobs_response.py +12 -0
  20. autoassembler/alpha/jobs/types/list_jobs_jobs_response.py +30 -0
  21. autoassembler/alpha/jobs/types/list_jobs_jobs_response_pagination.py +22 -0
  22. autoassembler/alpha/jobs/types/retry_job_jobs_response.py +16 -0
  23. autoassembler/alpha/planning/__init__.py +49 -0
  24. autoassembler/alpha/planning/client.py +201 -0
  25. autoassembler/alpha/planning/raw_client.py +268 -0
  26. autoassembler/alpha/planning/types/__init__.py +47 -0
  27. autoassembler/alpha/planning/types/apply_ops_planning_request_namespace.py +5 -0
  28. autoassembler/alpha/planning/types/apply_ops_planning_request_ops_item.py +13 -0
  29. autoassembler/alpha/planning/types/apply_ops_planning_request_ops_item_op.py +58 -0
  30. autoassembler/alpha/planning/types/apply_ops_planning_response.py +13 -0
  31. autoassembler/alpha/raw_client.py +13 -0
  32. autoassembler/assemblies/__init__.py +73 -0
  33. autoassembler/assemblies/client.py +1177 -0
  34. autoassembler/assemblies/raw_client.py +1557 -0
  35. autoassembler/assemblies/types/__init__.py +71 -0
  36. autoassembler/assemblies/types/delete_assembly_response.py +12 -0
  37. autoassembler/assemblies/types/download_assembly_cad_request_namespace.py +5 -0
  38. autoassembler/assemblies/types/get_assembly_info_request_namespace.py +5 -0
  39. autoassembler/assemblies/types/get_status_request_namespace.py +5 -0
  40. autoassembler/assemblies/types/get_status_response.py +16 -0
  41. autoassembler/assemblies/types/get_status_response_progress.py +13 -0
  42. autoassembler/assemblies/types/get_status_response_status.py +7 -0
  43. autoassembler/assemblies/types/get_structure_request_namespace.py +5 -0
  44. autoassembler/assemblies/types/list_assembly_versions_request_namespace.py +5 -0
  45. autoassembler/assemblies/types/list_connections_request_namespace.py +5 -0
  46. autoassembler/assemblies/types/process_request_namespace.py +5 -0
  47. autoassembler/assemblies/types/update_assembly_info_request_namespace.py +5 -0
  48. autoassembler/auth/__init__.py +34 -0
  49. autoassembler/auth/client.py +282 -0
  50. autoassembler/auth/raw_client.py +413 -0
  51. autoassembler/auth/types/__init__.py +36 -0
  52. autoassembler/auth/types/create_access_token_request_grant_type.py +7 -0
  53. autoassembler/base_client.py +328 -0
  54. autoassembler/client.py +262 -0
  55. autoassembler/core/__init__.py +127 -0
  56. autoassembler/core/api_error.py +23 -0
  57. autoassembler/core/client_wrapper.py +147 -0
  58. autoassembler/core/datetime_utils.py +70 -0
  59. autoassembler/core/file.py +67 -0
  60. autoassembler/core/force_multipart.py +18 -0
  61. autoassembler/core/http_client.py +965 -0
  62. autoassembler/core/http_response.py +63 -0
  63. autoassembler/core/http_sse/__init__.py +42 -0
  64. autoassembler/core/http_sse/_api.py +455 -0
  65. autoassembler/core/http_sse/_decoders.py +74 -0
  66. autoassembler/core/http_sse/_exceptions.py +7 -0
  67. autoassembler/core/http_sse/_models.py +17 -0
  68. autoassembler/core/jsonable_encoder.py +133 -0
  69. autoassembler/core/logging.py +107 -0
  70. autoassembler/core/parse_error.py +36 -0
  71. autoassembler/core/pydantic_utilities.py +486 -0
  72. autoassembler/core/query_encoder.py +58 -0
  73. autoassembler/core/remove_none_from_dict.py +11 -0
  74. autoassembler/core/request_options.py +40 -0
  75. autoassembler/core/serialization.py +347 -0
  76. autoassembler/environment.py +7 -0
  77. autoassembler/errors/__init__.py +56 -0
  78. autoassembler/errors/bad_request_error.py +10 -0
  79. autoassembler/errors/conflict_error.py +10 -0
  80. autoassembler/errors/forbidden_error.py +11 -0
  81. autoassembler/errors/internal_server_error.py +11 -0
  82. autoassembler/errors/not_found_error.py +11 -0
  83. autoassembler/errors/unauthorized_error.py +10 -0
  84. autoassembler/errors/unprocessable_entity_error.py +11 -0
  85. autoassembler/operation.py +196 -0
  86. autoassembler/operations/__init__.py +4 -0
  87. autoassembler/operations/client.py +209 -0
  88. autoassembler/operations/raw_client.py +343 -0
  89. autoassembler/planning/__init__.py +70 -0
  90. autoassembler/planning/client.py +1174 -0
  91. autoassembler/planning/raw_client.py +1349 -0
  92. autoassembler/planning/types/__init__.py +68 -0
  93. autoassembler/planning/types/adapt_request_namespace.py +5 -0
  94. autoassembler/planning/types/create_mpp_request_body.py +8 -0
  95. autoassembler/planning/types/create_mpp_request_namespace.py +5 -0
  96. autoassembler/planning/types/delete_mpp_request_namespace.py +5 -0
  97. autoassembler/planning/types/delete_mpp_response.py +12 -0
  98. autoassembler/planning/types/evaluate_dfa_request_namespace.py +5 -0
  99. autoassembler/planning/types/get_mpp_request_namespace.py +5 -0
  100. autoassembler/planning/types/get_mpp_response.py +27 -0
  101. autoassembler/planning/types/list_mpps_request_namespace.py +5 -0
  102. autoassembler/planning/types/plan_request_namespace.py +5 -0
  103. autoassembler/planning/types/validate_request_namespace.py +5 -0
  104. autoassembler/py.typed +0 -0
  105. autoassembler/sessions/__init__.py +4 -0
  106. autoassembler/sessions/client.py +102 -0
  107. autoassembler/sessions/raw_client.py +126 -0
  108. autoassembler/types/__init__.py +344 -0
  109. autoassembler/types/access_token_response.py +14 -0
  110. autoassembler/types/active_session.py +25 -0
  111. autoassembler/types/active_session_namespace.py +5 -0
  112. autoassembler/types/adapt_mpp_accepted.py +26 -0
  113. autoassembler/types/assembly.py +30 -0
  114. autoassembler/types/assembly_connection.py +21 -0
  115. autoassembler/types/assembly_connection_relationship.py +5 -0
  116. autoassembler/types/assembly_connections_response.py +13 -0
  117. autoassembler/types/assembly_diff_metadata.py +35 -0
  118. autoassembler/types/assembly_diff_response.py +34 -0
  119. autoassembler/types/assembly_info.py +36 -0
  120. autoassembler/types/assembly_json_response.py +15 -0
  121. autoassembler/types/assembly_process_metadata.py +32 -0
  122. autoassembler/types/assembly_process_response.py +18 -0
  123. autoassembler/types/assembly_search_hit.py +31 -0
  124. autoassembler/types/assembly_version_summary.py +27 -0
  125. autoassembler/types/conflict_error_body.py +19 -0
  126. autoassembler/types/conflict_error_body_error.py +5 -0
  127. autoassembler/types/create_mpp_request.py +13 -0
  128. autoassembler/types/device_authorization_response.py +17 -0
  129. autoassembler/types/diff_accepted.py +42 -0
  130. autoassembler/types/diff_context_node.py +20 -0
  131. autoassembler/types/diff_details.py +73 -0
  132. autoassembler/types/diff_error_response.py +38 -0
  133. autoassembler/types/diff_flags.py +74 -0
  134. autoassembler/types/diff_ml_semantics.py +55 -0
  135. autoassembler/types/diff_node.py +26 -0
  136. autoassembler/types/diff_node_pair_with_parts.py +90 -0
  137. autoassembler/types/diff_node_with_parent.py +15 -0
  138. autoassembler/types/diff_reference_target_nodes.py +25 -0
  139. autoassembler/types/diff_report.py +24 -0
  140. autoassembler/types/diff_rigid_alignment.py +30 -0
  141. autoassembler/types/diff_summary.py +121 -0
  142. autoassembler/types/diff_summary_assembly_labels.py +44 -0
  143. autoassembler/types/diff_summary_geometric_diffs.py +24 -0
  144. autoassembler/types/diff_summary_persistent_edges_congruence.py +24 -0
  145. autoassembler/types/diff_summary_persistent_edges_congruence_pose.py +24 -0
  146. autoassembler/types/diff_summary_persistent_nodes_congruence.py +24 -0
  147. autoassembler/types/diff_summary_persistent_nodes_congruence_pose.py +24 -0
  148. autoassembler/types/diff_summary_total_parts.py +24 -0
  149. autoassembler/types/diff_swap.py +65 -0
  150. autoassembler/types/diff_swap_confidence.py +5 -0
  151. autoassembler/types/diff_swap_group.py +92 -0
  152. autoassembler/types/diff_validation_issue.py +38 -0
  153. autoassembler/types/diff_validation_issue_severity.py +5 -0
  154. autoassembler/types/diff_validation_result.py +35 -0
  155. autoassembler/types/diff_warning.py +79 -0
  156. autoassembler/types/diff_warning_reason.py +18 -0
  157. autoassembler/types/diff_warning_severity.py +5 -0
  158. autoassembler/types/error_response.py +30 -0
  159. autoassembler/types/filter.py +19 -0
  160. autoassembler/types/filter_field.py +7 -0
  161. autoassembler/types/filter_operator.py +5 -0
  162. autoassembler/types/job.py +123 -0
  163. autoassembler/types/job_progress.py +24 -0
  164. autoassembler/types/job_status.py +5 -0
  165. autoassembler/types/list_operations_response.py +25 -0
  166. autoassembler/types/manufacturing_process_plan.py +57 -0
  167. autoassembler/types/mpp_adapt_metadata.py +48 -0
  168. autoassembler/types/mpp_adapt_response.py +22 -0
  169. autoassembler/types/mpp_evaluate_dfa_metadata.py +47 -0
  170. autoassembler/types/mpp_evaluate_dfa_response.py +22 -0
  171. autoassembler/types/mpp_plan_metadata.py +47 -0
  172. autoassembler/types/mpp_plan_response.py +22 -0
  173. autoassembler/types/mpp_summary.py +20 -0
  174. autoassembler/types/mpp_validate_metadata.py +47 -0
  175. autoassembler/types/mpp_validate_response.py +22 -0
  176. autoassembler/types/o_auth_error_response.py +14 -0
  177. autoassembler/types/o_auth_error_response_error.py +18 -0
  178. autoassembler/types/operation.py +27 -0
  179. autoassembler/types/operation_error.py +21 -0
  180. autoassembler/types/operation_metadata.py +148 -0
  181. autoassembler/types/operation_response.py +94 -0
  182. autoassembler/types/process_assembly_accepted.py +14 -0
  183. autoassembler/types/process_assembly_response.py +55 -0
  184. autoassembler/types/process_assembly_skipped.py +14 -0
  185. autoassembler/types/search_assemblies_response.py +14 -0
  186. autoassembler/types/seq_plan_accepted.py +24 -0
  187. autoassembler/types/sever.py +33 -0
  188. autoassembler/types/sever_kind.py +5 -0
  189. autoassembler/types/sever_source.py +5 -0
  190. autoassembler/types/sort.py +8 -0
  191. autoassembler/types/upload_response.py +19 -0
  192. autoassembler/types/user_info.py +19 -0
  193. autoassembler/types/user_info_response.py +23 -0
  194. autoassembler/types/user_info_response_providers.py +14 -0
  195. autoassembler-0.3.1.dist-info/METADATA +209 -0
  196. autoassembler-0.3.1.dist-info/RECORD +198 -0
  197. autoassembler-0.3.1.dist-info/WHEEL +4 -0
  198. autoassembler-0.3.1.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,1349 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+ from json.decoder import JSONDecodeError
5
+
6
+ from ..core.api_error import ApiError
7
+ from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
8
+ from ..core.http_response import AsyncHttpResponse, HttpResponse
9
+ from ..core.jsonable_encoder import encode_path_param
10
+ from ..core.parse_error import ParsingError
11
+ from ..core.pydantic_utilities import parse_obj_as
12
+ from ..core.request_options import RequestOptions
13
+ from ..core.serialization import convert_and_respect_annotation_metadata
14
+ from ..errors.bad_request_error import BadRequestError
15
+ from ..errors.conflict_error import ConflictError
16
+ from ..errors.forbidden_error import ForbiddenError
17
+ from ..errors.not_found_error import NotFoundError
18
+ from ..errors.unprocessable_entity_error import UnprocessableEntityError
19
+ from ..types.adapt_mpp_accepted import AdaptMppAccepted
20
+ from ..types.diff_report import DiffReport
21
+ from ..types.error_response import ErrorResponse
22
+ from ..types.manufacturing_process_plan import ManufacturingProcessPlan
23
+ from ..types.mpp_summary import MppSummary
24
+ from ..types.seq_plan_accepted import SeqPlanAccepted
25
+ from .types.adapt_request_namespace import AdaptRequestNamespace
26
+ from .types.create_mpp_request_body import CreateMppRequestBody
27
+ from .types.create_mpp_request_namespace import CreateMppRequestNamespace
28
+ from .types.delete_mpp_request_namespace import DeleteMppRequestNamespace
29
+ from .types.delete_mpp_response import DeleteMppResponse
30
+ from .types.evaluate_dfa_request_namespace import EvaluateDfaRequestNamespace
31
+ from .types.get_mpp_request_namespace import GetMppRequestNamespace
32
+ from .types.get_mpp_response import GetMppResponse
33
+ from .types.list_mpps_request_namespace import ListMppsRequestNamespace
34
+ from .types.plan_request_namespace import PlanRequestNamespace
35
+ from .types.validate_request_namespace import ValidateRequestNamespace
36
+ from pydantic import ValidationError
37
+
38
+ # this is used as the default value for optional parameters
39
+ OMIT = typing.cast(typing.Any, ...)
40
+
41
+
42
+ class RawPlanningClient:
43
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
44
+ self._client_wrapper = client_wrapper
45
+
46
+ def list_mpps(
47
+ self, namespace: ListMppsRequestNamespace, id: str, *, request_options: typing.Optional[RequestOptions] = None
48
+ ) -> HttpResponse[typing.List[MppSummary]]:
49
+ """
50
+ Parameters
51
+ ----------
52
+ namespace : ListMppsRequestNamespace
53
+ Assembly URL namespace. `user`, `shared`, and `public` are routed through the same assembly lookup.
54
+
55
+ id : str
56
+ Assembly ID.
57
+
58
+ request_options : typing.Optional[RequestOptions]
59
+ Request-specific configuration.
60
+
61
+ Returns
62
+ -------
63
+ HttpResponse[typing.List[MppSummary]]
64
+ Process plan summaries for the assembly.
65
+ """
66
+ _response = self._client_wrapper.httpx_client.request(
67
+ f"api/v4/assemblies/{encode_path_param(namespace)}/{encode_path_param(id)}/mpps",
68
+ method="GET",
69
+ request_options=request_options,
70
+ )
71
+ try:
72
+ if 200 <= _response.status_code < 300:
73
+ _data = typing.cast(
74
+ typing.List[MppSummary],
75
+ parse_obj_as(
76
+ type_=typing.List[MppSummary], # type: ignore
77
+ object_=_response.json(),
78
+ ),
79
+ )
80
+ return HttpResponse(response=_response, data=_data)
81
+ _response_json = _response.json()
82
+ except JSONDecodeError:
83
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
84
+ except ValidationError as e:
85
+ raise ParsingError(
86
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
87
+ )
88
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
89
+
90
+ def create_mpp(
91
+ self,
92
+ namespace: CreateMppRequestNamespace,
93
+ id: str,
94
+ *,
95
+ request: CreateMppRequestBody,
96
+ request_options: typing.Optional[RequestOptions] = None,
97
+ ) -> HttpResponse[ManufacturingProcessPlan]:
98
+ """
99
+ Parameters
100
+ ----------
101
+ namespace : CreateMppRequestNamespace
102
+ Assembly URL namespace. `user`, `shared`, and `public` are routed through the same assembly lookup.
103
+
104
+ id : str
105
+ Assembly ID.
106
+
107
+ request : CreateMppRequestBody
108
+
109
+ request_options : typing.Optional[RequestOptions]
110
+ Request-specific configuration.
111
+
112
+ Returns
113
+ -------
114
+ HttpResponse[ManufacturingProcessPlan]
115
+ Created process plan document.
116
+ """
117
+ _response = self._client_wrapper.httpx_client.request(
118
+ f"api/v4/assemblies/{encode_path_param(namespace)}/{encode_path_param(id)}/mpps",
119
+ method="POST",
120
+ json=convert_and_respect_annotation_metadata(
121
+ object_=request, annotation=CreateMppRequestBody, direction="write"
122
+ ),
123
+ headers={
124
+ "content-type": "application/json",
125
+ },
126
+ request_options=request_options,
127
+ omit=OMIT,
128
+ )
129
+ try:
130
+ if 200 <= _response.status_code < 300:
131
+ _data = typing.cast(
132
+ ManufacturingProcessPlan,
133
+ parse_obj_as(
134
+ type_=ManufacturingProcessPlan, # type: ignore
135
+ object_=_response.json(),
136
+ ),
137
+ )
138
+ return HttpResponse(response=_response, data=_data)
139
+ _response_json = _response.json()
140
+ except JSONDecodeError:
141
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
142
+ except ValidationError as e:
143
+ raise ParsingError(
144
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
145
+ )
146
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
147
+
148
+ def adapt(
149
+ self,
150
+ namespace: AdaptRequestNamespace,
151
+ id: str,
152
+ *,
153
+ reference_mpp_id: str,
154
+ diff: DiffReport,
155
+ name: typing.Optional[str] = OMIT,
156
+ request_options: typing.Optional[RequestOptions] = None,
157
+ ) -> HttpResponse[AdaptMppAccepted]:
158
+ """
159
+ Creates a process plan for the target assembly by adapting a reference assembly's
160
+ process plan. Runs asynchronously and returns immediately with the
161
+ new `mppId` and `jobId`.
162
+
163
+ Parameters
164
+ ----------
165
+ namespace : AdaptRequestNamespace
166
+ Assembly URL namespace. `user`, `shared`, and `public` are routed through the same assembly lookup.
167
+
168
+ id : str
169
+ Assembly ID.
170
+
171
+ reference_mpp_id : str
172
+ Process plan for the reference assembly to adapt from.
173
+
174
+ diff : DiffReport
175
+
176
+ name : typing.Optional[str]
177
+ Optional name for the adapted process plan.
178
+
179
+ request_options : typing.Optional[RequestOptions]
180
+ Request-specific configuration.
181
+
182
+ Returns
183
+ -------
184
+ HttpResponse[AdaptMppAccepted]
185
+ Adaptation queued, with the operation tracking it.
186
+ """
187
+ _response = self._client_wrapper.httpx_client.request(
188
+ f"api/v4/assemblies/{encode_path_param(namespace)}/{encode_path_param(id)}/mpps:adapt",
189
+ method="POST",
190
+ json={
191
+ "referenceMppId": reference_mpp_id,
192
+ "name": name,
193
+ "diff": convert_and_respect_annotation_metadata(object_=diff, annotation=DiffReport, direction="write"),
194
+ },
195
+ headers={
196
+ "content-type": "application/json",
197
+ },
198
+ request_options=request_options,
199
+ omit=OMIT,
200
+ )
201
+ try:
202
+ if 200 <= _response.status_code < 300:
203
+ _data = typing.cast(
204
+ AdaptMppAccepted,
205
+ parse_obj_as(
206
+ type_=AdaptMppAccepted, # type: ignore
207
+ object_=_response.json(),
208
+ ),
209
+ )
210
+ return HttpResponse(response=_response, data=_data)
211
+ if _response.status_code == 400:
212
+ raise BadRequestError(
213
+ headers=dict(_response.headers),
214
+ body=typing.cast(
215
+ typing.Any,
216
+ parse_obj_as(
217
+ type_=typing.Any, # type: ignore
218
+ object_=_response.json(),
219
+ ),
220
+ ),
221
+ )
222
+ if _response.status_code == 403:
223
+ raise ForbiddenError(
224
+ headers=dict(_response.headers),
225
+ body=typing.cast(
226
+ ErrorResponse,
227
+ parse_obj_as(
228
+ type_=ErrorResponse, # type: ignore
229
+ object_=_response.json(),
230
+ ),
231
+ ),
232
+ )
233
+ if _response.status_code == 404:
234
+ raise NotFoundError(
235
+ headers=dict(_response.headers),
236
+ body=typing.cast(
237
+ ErrorResponse,
238
+ parse_obj_as(
239
+ type_=ErrorResponse, # type: ignore
240
+ object_=_response.json(),
241
+ ),
242
+ ),
243
+ )
244
+ if _response.status_code == 422:
245
+ raise UnprocessableEntityError(
246
+ headers=dict(_response.headers),
247
+ body=typing.cast(
248
+ ErrorResponse,
249
+ parse_obj_as(
250
+ type_=ErrorResponse, # type: ignore
251
+ object_=_response.json(),
252
+ ),
253
+ ),
254
+ )
255
+ _response_json = _response.json()
256
+ except JSONDecodeError:
257
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
258
+ except ValidationError as e:
259
+ raise ParsingError(
260
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
261
+ )
262
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
263
+
264
+ def get_mpp(
265
+ self,
266
+ namespace: GetMppRequestNamespace,
267
+ id: str,
268
+ mpp_id: str,
269
+ *,
270
+ request_options: typing.Optional[RequestOptions] = None,
271
+ ) -> HttpResponse[GetMppResponse]:
272
+ """
273
+ Parameters
274
+ ----------
275
+ namespace : GetMppRequestNamespace
276
+ Assembly URL namespace. `user`, `shared`, and `public` are routed through the same assembly lookup.
277
+
278
+ id : str
279
+ Assembly ID.
280
+
281
+ mpp_id : str
282
+ Manufacturing Process Plan ID.
283
+
284
+ request_options : typing.Optional[RequestOptions]
285
+ Request-specific configuration.
286
+
287
+ Returns
288
+ -------
289
+ HttpResponse[GetMppResponse]
290
+ Process plan document wrapper.
291
+ """
292
+ _response = self._client_wrapper.httpx_client.request(
293
+ f"api/v4/assemblies/{encode_path_param(namespace)}/{encode_path_param(id)}/mpps/{encode_path_param(mpp_id)}",
294
+ method="GET",
295
+ request_options=request_options,
296
+ )
297
+ try:
298
+ if 200 <= _response.status_code < 300:
299
+ _data = typing.cast(
300
+ GetMppResponse,
301
+ parse_obj_as(
302
+ type_=GetMppResponse, # type: ignore
303
+ object_=_response.json(),
304
+ ),
305
+ )
306
+ return HttpResponse(response=_response, data=_data)
307
+ _response_json = _response.json()
308
+ except JSONDecodeError:
309
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
310
+ except ValidationError as e:
311
+ raise ParsingError(
312
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
313
+ )
314
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
315
+
316
+ def delete_mpp(
317
+ self,
318
+ namespace: DeleteMppRequestNamespace,
319
+ id: str,
320
+ mpp_id: str,
321
+ *,
322
+ request_options: typing.Optional[RequestOptions] = None,
323
+ ) -> HttpResponse[DeleteMppResponse]:
324
+ """
325
+ Parameters
326
+ ----------
327
+ namespace : DeleteMppRequestNamespace
328
+ Assembly URL namespace. `user`, `shared`, and `public` are routed through the same assembly lookup.
329
+
330
+ id : str
331
+ Assembly ID.
332
+
333
+ mpp_id : str
334
+ Manufacturing Process Plan ID.
335
+
336
+ request_options : typing.Optional[RequestOptions]
337
+ Request-specific configuration.
338
+
339
+ Returns
340
+ -------
341
+ HttpResponse[DeleteMppResponse]
342
+ Delete status.
343
+ """
344
+ _response = self._client_wrapper.httpx_client.request(
345
+ f"api/v4/assemblies/{encode_path_param(namespace)}/{encode_path_param(id)}/mpps/{encode_path_param(mpp_id)}",
346
+ method="DELETE",
347
+ request_options=request_options,
348
+ )
349
+ try:
350
+ if 200 <= _response.status_code < 300:
351
+ _data = typing.cast(
352
+ DeleteMppResponse,
353
+ parse_obj_as(
354
+ type_=DeleteMppResponse, # type: ignore
355
+ object_=_response.json(),
356
+ ),
357
+ )
358
+ return HttpResponse(response=_response, data=_data)
359
+ _response_json = _response.json()
360
+ except JSONDecodeError:
361
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
362
+ except ValidationError as e:
363
+ raise ParsingError(
364
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
365
+ )
366
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
367
+
368
+ def plan(
369
+ self,
370
+ namespace: PlanRequestNamespace,
371
+ id: str,
372
+ mpp_id: str,
373
+ *,
374
+ station_ids: typing.Sequence[str],
375
+ overwrite: typing.Optional[bool] = OMIT,
376
+ request_options: typing.Optional[RequestOptions] = None,
377
+ ) -> HttpResponse[SeqPlanAccepted]:
378
+ """
379
+ Plans the Station graph from scratch, computing a suitable process plan (Step graph)
380
+ for each of the requested stations. The run overwrites any pre-existing plan; deciding which
381
+ stations have to be re-planned is the caller's responsibility.
382
+ Pass `overwrite: false` to have a station that already has a plan left alone instead.
383
+
384
+ **Async** — returns 202 immediately.
385
+
386
+ Parameters
387
+ ----------
388
+ namespace : PlanRequestNamespace
389
+ Assembly URL namespace. `user`, `shared`, and `public` are routed through the same assembly lookup.
390
+
391
+ id : str
392
+ Assembly ID.
393
+
394
+ mpp_id : str
395
+ Manufacturing Process Plan ID.
396
+
397
+ station_ids : typing.Sequence[str]
398
+ IDs of the Station nodes to plan. All must exist in the process plan's station graph and have a supported input/output boundary.
399
+
400
+ overwrite : typing.Optional[bool]
401
+ Whether the run may replace a plan a requested station already has. Checked per station, so one station never blocks another.
402
+
403
+ request_options : typing.Optional[RequestOptions]
404
+ Request-specific configuration.
405
+
406
+ Returns
407
+ -------
408
+ HttpResponse[SeqPlanAccepted]
409
+ Planning jobs accepted and running in the background.
410
+ """
411
+ _response = self._client_wrapper.httpx_client.request(
412
+ f"api/v4/assemblies/{encode_path_param(namespace)}/{encode_path_param(id)}/mpps/{encode_path_param(mpp_id)}:seq-plan",
413
+ method="POST",
414
+ json={
415
+ "stationIds": station_ids,
416
+ "overwrite": overwrite,
417
+ },
418
+ headers={
419
+ "content-type": "application/json",
420
+ },
421
+ request_options=request_options,
422
+ omit=OMIT,
423
+ )
424
+ try:
425
+ if 200 <= _response.status_code < 300:
426
+ _data = typing.cast(
427
+ SeqPlanAccepted,
428
+ parse_obj_as(
429
+ type_=SeqPlanAccepted, # type: ignore
430
+ object_=_response.json(),
431
+ ),
432
+ )
433
+ return HttpResponse(response=_response, data=_data)
434
+ if _response.status_code == 400:
435
+ raise BadRequestError(
436
+ headers=dict(_response.headers),
437
+ body=typing.cast(
438
+ typing.Any,
439
+ parse_obj_as(
440
+ type_=typing.Any, # type: ignore
441
+ object_=_response.json(),
442
+ ),
443
+ ),
444
+ )
445
+ if _response.status_code == 404:
446
+ raise NotFoundError(
447
+ headers=dict(_response.headers),
448
+ body=typing.cast(
449
+ ErrorResponse,
450
+ parse_obj_as(
451
+ type_=ErrorResponse, # type: ignore
452
+ object_=_response.json(),
453
+ ),
454
+ ),
455
+ )
456
+ if _response.status_code == 409:
457
+ raise ConflictError(
458
+ headers=dict(_response.headers),
459
+ body=typing.cast(
460
+ typing.Any,
461
+ parse_obj_as(
462
+ type_=typing.Any, # type: ignore
463
+ object_=_response.json(),
464
+ ),
465
+ ),
466
+ )
467
+ _response_json = _response.json()
468
+ except JSONDecodeError:
469
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
470
+ except ValidationError as e:
471
+ raise ParsingError(
472
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
473
+ )
474
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
475
+
476
+ def validate(
477
+ self,
478
+ namespace: ValidateRequestNamespace,
479
+ id: str,
480
+ mpp_id: str,
481
+ *,
482
+ station_ids: typing.Sequence[str],
483
+ fix_directions: typing.Optional[bool] = OMIT,
484
+ request_options: typing.Optional[RequestOptions] = None,
485
+ ) -> HttpResponse[SeqPlanAccepted]:
486
+ """
487
+ **Feasibility validation** — checks structural consistency of the entire process plan,
488
+ then validates geometrical feasibility of assembly steps for the requested
489
+ stations. When a blocked step has a workspace-free alternative direction,
490
+ `fixDirections` (off by default) writes it onto the step graph and the
491
+ persisted verdict reflects the repaired plan.
492
+
493
+ **Async** — returns 202 with `{ queued }`.
494
+
495
+ Parameters
496
+ ----------
497
+ namespace : ValidateRequestNamespace
498
+ Assembly URL namespace. `user`, `shared`, and `public` are routed through the same assembly lookup.
499
+
500
+ id : str
501
+ Assembly ID.
502
+
503
+ mpp_id : str
504
+ Manufacturing Process Plan ID.
505
+
506
+ station_ids : typing.Sequence[str]
507
+ IDs of the Station nodes to validate. All must exist in the process plan's station graph and stations without persisted assembly steps are accepted and reported as skipped.
508
+
509
+ fix_directions : typing.Optional[bool]
510
+ Apply each blocked step's workspace-free alternative direction onto the step graph, so the persisted verdict describes the repaired plan. Absent, the step graph is untouched.
511
+
512
+ request_options : typing.Optional[RequestOptions]
513
+ Request-specific configuration.
514
+
515
+ Returns
516
+ -------
517
+ HttpResponse[SeqPlanAccepted]
518
+ Validation jobs accepted and running in the background.
519
+ """
520
+ _response = self._client_wrapper.httpx_client.request(
521
+ f"api/v4/assemblies/{encode_path_param(namespace)}/{encode_path_param(id)}/mpps/{encode_path_param(mpp_id)}:validate",
522
+ method="POST",
523
+ json={
524
+ "stationIds": station_ids,
525
+ "fixDirections": fix_directions,
526
+ },
527
+ headers={
528
+ "content-type": "application/json",
529
+ },
530
+ request_options=request_options,
531
+ omit=OMIT,
532
+ )
533
+ try:
534
+ if 200 <= _response.status_code < 300:
535
+ _data = typing.cast(
536
+ SeqPlanAccepted,
537
+ parse_obj_as(
538
+ type_=SeqPlanAccepted, # type: ignore
539
+ object_=_response.json(),
540
+ ),
541
+ )
542
+ return HttpResponse(response=_response, data=_data)
543
+ if _response.status_code == 400:
544
+ raise BadRequestError(
545
+ headers=dict(_response.headers),
546
+ body=typing.cast(
547
+ typing.Any,
548
+ parse_obj_as(
549
+ type_=typing.Any, # type: ignore
550
+ object_=_response.json(),
551
+ ),
552
+ ),
553
+ )
554
+ if _response.status_code == 404:
555
+ raise NotFoundError(
556
+ headers=dict(_response.headers),
557
+ body=typing.cast(
558
+ ErrorResponse,
559
+ parse_obj_as(
560
+ type_=ErrorResponse, # type: ignore
561
+ object_=_response.json(),
562
+ ),
563
+ ),
564
+ )
565
+ if _response.status_code == 422:
566
+ raise UnprocessableEntityError(
567
+ headers=dict(_response.headers),
568
+ body=typing.cast(
569
+ ErrorResponse,
570
+ parse_obj_as(
571
+ type_=ErrorResponse, # type: ignore
572
+ object_=_response.json(),
573
+ ),
574
+ ),
575
+ )
576
+ _response_json = _response.json()
577
+ except JSONDecodeError:
578
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
579
+ except ValidationError as e:
580
+ raise ParsingError(
581
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
582
+ )
583
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
584
+
585
+ def evaluate_dfa(
586
+ self,
587
+ namespace: EvaluateDfaRequestNamespace,
588
+ id: str,
589
+ mpp_id: str,
590
+ *,
591
+ station_ids: typing.Optional[typing.Sequence[str]] = OMIT,
592
+ request_options: typing.Optional[RequestOptions] = None,
593
+ ) -> HttpResponse[SeqPlanAccepted]:
594
+ """
595
+ Projects each sequential assembly addend directly from the persisted Step
596
+ graph into an explicit state-of-assembly transition, evaluates DFA, and
597
+ persists per-station reports under `plan.dfa`. Runs asynchronously.
598
+
599
+ Parameters
600
+ ----------
601
+ namespace : EvaluateDfaRequestNamespace
602
+ Assembly URL namespace. `user`, `shared`, and `public` are routed through the same assembly lookup.
603
+
604
+ id : str
605
+ Assembly ID.
606
+
607
+ mpp_id : str
608
+ Manufacturing Process Plan ID.
609
+
610
+ station_ids : typing.Optional[typing.Sequence[str]]
611
+ Stations to score. Omitted means every station with assembly steps, and then a station that is not ready is skipped rather than refused. A station named here must be planned and hold a feasible validation verdict, or the whole request is refused with 409. Named stations without assembly steps are accepted and reported as skipped.
612
+
613
+ request_options : typing.Optional[RequestOptions]
614
+ Request-specific configuration.
615
+
616
+ Returns
617
+ -------
618
+ HttpResponse[SeqPlanAccepted]
619
+ DFA evaluation accepted (or nothing to evaluate). `skipped` lists requested stations that were not queued — no assembly steps, or, for an unfiltered request, not yet validated.
620
+ """
621
+ _response = self._client_wrapper.httpx_client.request(
622
+ f"api/v4/assemblies/{encode_path_param(namespace)}/{encode_path_param(id)}/mpps/{encode_path_param(mpp_id)}:dfa",
623
+ method="POST",
624
+ json={
625
+ "stationIds": station_ids,
626
+ },
627
+ headers={
628
+ "content-type": "application/json",
629
+ },
630
+ request_options=request_options,
631
+ omit=OMIT,
632
+ )
633
+ try:
634
+ if 200 <= _response.status_code < 300:
635
+ _data = typing.cast(
636
+ SeqPlanAccepted,
637
+ parse_obj_as(
638
+ type_=SeqPlanAccepted, # type: ignore
639
+ object_=_response.json(),
640
+ ),
641
+ )
642
+ return HttpResponse(response=_response, data=_data)
643
+ if _response.status_code == 400:
644
+ raise BadRequestError(
645
+ headers=dict(_response.headers),
646
+ body=typing.cast(
647
+ typing.Any,
648
+ parse_obj_as(
649
+ type_=typing.Any, # type: ignore
650
+ object_=_response.json(),
651
+ ),
652
+ ),
653
+ )
654
+ if _response.status_code == 404:
655
+ raise NotFoundError(
656
+ headers=dict(_response.headers),
657
+ body=typing.cast(
658
+ ErrorResponse,
659
+ parse_obj_as(
660
+ type_=ErrorResponse, # type: ignore
661
+ object_=_response.json(),
662
+ ),
663
+ ),
664
+ )
665
+ if _response.status_code == 409:
666
+ raise ConflictError(
667
+ headers=dict(_response.headers),
668
+ body=typing.cast(
669
+ typing.Any,
670
+ parse_obj_as(
671
+ type_=typing.Any, # type: ignore
672
+ object_=_response.json(),
673
+ ),
674
+ ),
675
+ )
676
+ if _response.status_code == 422:
677
+ raise UnprocessableEntityError(
678
+ headers=dict(_response.headers),
679
+ body=typing.cast(
680
+ ErrorResponse,
681
+ parse_obj_as(
682
+ type_=ErrorResponse, # type: ignore
683
+ object_=_response.json(),
684
+ ),
685
+ ),
686
+ )
687
+ _response_json = _response.json()
688
+ except JSONDecodeError:
689
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
690
+ except ValidationError as e:
691
+ raise ParsingError(
692
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
693
+ )
694
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
695
+
696
+
697
+ class AsyncRawPlanningClient:
698
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
699
+ self._client_wrapper = client_wrapper
700
+
701
+ async def list_mpps(
702
+ self, namespace: ListMppsRequestNamespace, id: str, *, request_options: typing.Optional[RequestOptions] = None
703
+ ) -> AsyncHttpResponse[typing.List[MppSummary]]:
704
+ """
705
+ Parameters
706
+ ----------
707
+ namespace : ListMppsRequestNamespace
708
+ Assembly URL namespace. `user`, `shared`, and `public` are routed through the same assembly lookup.
709
+
710
+ id : str
711
+ Assembly ID.
712
+
713
+ request_options : typing.Optional[RequestOptions]
714
+ Request-specific configuration.
715
+
716
+ Returns
717
+ -------
718
+ AsyncHttpResponse[typing.List[MppSummary]]
719
+ Process plan summaries for the assembly.
720
+ """
721
+ _response = await self._client_wrapper.httpx_client.request(
722
+ f"api/v4/assemblies/{encode_path_param(namespace)}/{encode_path_param(id)}/mpps",
723
+ method="GET",
724
+ request_options=request_options,
725
+ )
726
+ try:
727
+ if 200 <= _response.status_code < 300:
728
+ _data = typing.cast(
729
+ typing.List[MppSummary],
730
+ parse_obj_as(
731
+ type_=typing.List[MppSummary], # type: ignore
732
+ object_=_response.json(),
733
+ ),
734
+ )
735
+ return AsyncHttpResponse(response=_response, data=_data)
736
+ _response_json = _response.json()
737
+ except JSONDecodeError:
738
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
739
+ except ValidationError as e:
740
+ raise ParsingError(
741
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
742
+ )
743
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
744
+
745
+ async def create_mpp(
746
+ self,
747
+ namespace: CreateMppRequestNamespace,
748
+ id: str,
749
+ *,
750
+ request: CreateMppRequestBody,
751
+ request_options: typing.Optional[RequestOptions] = None,
752
+ ) -> AsyncHttpResponse[ManufacturingProcessPlan]:
753
+ """
754
+ Parameters
755
+ ----------
756
+ namespace : CreateMppRequestNamespace
757
+ Assembly URL namespace. `user`, `shared`, and `public` are routed through the same assembly lookup.
758
+
759
+ id : str
760
+ Assembly ID.
761
+
762
+ request : CreateMppRequestBody
763
+
764
+ request_options : typing.Optional[RequestOptions]
765
+ Request-specific configuration.
766
+
767
+ Returns
768
+ -------
769
+ AsyncHttpResponse[ManufacturingProcessPlan]
770
+ Created process plan document.
771
+ """
772
+ _response = await self._client_wrapper.httpx_client.request(
773
+ f"api/v4/assemblies/{encode_path_param(namespace)}/{encode_path_param(id)}/mpps",
774
+ method="POST",
775
+ json=convert_and_respect_annotation_metadata(
776
+ object_=request, annotation=CreateMppRequestBody, direction="write"
777
+ ),
778
+ headers={
779
+ "content-type": "application/json",
780
+ },
781
+ request_options=request_options,
782
+ omit=OMIT,
783
+ )
784
+ try:
785
+ if 200 <= _response.status_code < 300:
786
+ _data = typing.cast(
787
+ ManufacturingProcessPlan,
788
+ parse_obj_as(
789
+ type_=ManufacturingProcessPlan, # type: ignore
790
+ object_=_response.json(),
791
+ ),
792
+ )
793
+ return AsyncHttpResponse(response=_response, data=_data)
794
+ _response_json = _response.json()
795
+ except JSONDecodeError:
796
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
797
+ except ValidationError as e:
798
+ raise ParsingError(
799
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
800
+ )
801
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
802
+
803
+ async def adapt(
804
+ self,
805
+ namespace: AdaptRequestNamespace,
806
+ id: str,
807
+ *,
808
+ reference_mpp_id: str,
809
+ diff: DiffReport,
810
+ name: typing.Optional[str] = OMIT,
811
+ request_options: typing.Optional[RequestOptions] = None,
812
+ ) -> AsyncHttpResponse[AdaptMppAccepted]:
813
+ """
814
+ Creates a process plan for the target assembly by adapting a reference assembly's
815
+ process plan. Runs asynchronously and returns immediately with the
816
+ new `mppId` and `jobId`.
817
+
818
+ Parameters
819
+ ----------
820
+ namespace : AdaptRequestNamespace
821
+ Assembly URL namespace. `user`, `shared`, and `public` are routed through the same assembly lookup.
822
+
823
+ id : str
824
+ Assembly ID.
825
+
826
+ reference_mpp_id : str
827
+ Process plan for the reference assembly to adapt from.
828
+
829
+ diff : DiffReport
830
+
831
+ name : typing.Optional[str]
832
+ Optional name for the adapted process plan.
833
+
834
+ request_options : typing.Optional[RequestOptions]
835
+ Request-specific configuration.
836
+
837
+ Returns
838
+ -------
839
+ AsyncHttpResponse[AdaptMppAccepted]
840
+ Adaptation queued, with the operation tracking it.
841
+ """
842
+ _response = await self._client_wrapper.httpx_client.request(
843
+ f"api/v4/assemblies/{encode_path_param(namespace)}/{encode_path_param(id)}/mpps:adapt",
844
+ method="POST",
845
+ json={
846
+ "referenceMppId": reference_mpp_id,
847
+ "name": name,
848
+ "diff": convert_and_respect_annotation_metadata(object_=diff, annotation=DiffReport, direction="write"),
849
+ },
850
+ headers={
851
+ "content-type": "application/json",
852
+ },
853
+ request_options=request_options,
854
+ omit=OMIT,
855
+ )
856
+ try:
857
+ if 200 <= _response.status_code < 300:
858
+ _data = typing.cast(
859
+ AdaptMppAccepted,
860
+ parse_obj_as(
861
+ type_=AdaptMppAccepted, # type: ignore
862
+ object_=_response.json(),
863
+ ),
864
+ )
865
+ return AsyncHttpResponse(response=_response, data=_data)
866
+ if _response.status_code == 400:
867
+ raise BadRequestError(
868
+ headers=dict(_response.headers),
869
+ body=typing.cast(
870
+ typing.Any,
871
+ parse_obj_as(
872
+ type_=typing.Any, # type: ignore
873
+ object_=_response.json(),
874
+ ),
875
+ ),
876
+ )
877
+ if _response.status_code == 403:
878
+ raise ForbiddenError(
879
+ headers=dict(_response.headers),
880
+ body=typing.cast(
881
+ ErrorResponse,
882
+ parse_obj_as(
883
+ type_=ErrorResponse, # type: ignore
884
+ object_=_response.json(),
885
+ ),
886
+ ),
887
+ )
888
+ if _response.status_code == 404:
889
+ raise NotFoundError(
890
+ headers=dict(_response.headers),
891
+ body=typing.cast(
892
+ ErrorResponse,
893
+ parse_obj_as(
894
+ type_=ErrorResponse, # type: ignore
895
+ object_=_response.json(),
896
+ ),
897
+ ),
898
+ )
899
+ if _response.status_code == 422:
900
+ raise UnprocessableEntityError(
901
+ headers=dict(_response.headers),
902
+ body=typing.cast(
903
+ ErrorResponse,
904
+ parse_obj_as(
905
+ type_=ErrorResponse, # type: ignore
906
+ object_=_response.json(),
907
+ ),
908
+ ),
909
+ )
910
+ _response_json = _response.json()
911
+ except JSONDecodeError:
912
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
913
+ except ValidationError as e:
914
+ raise ParsingError(
915
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
916
+ )
917
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
918
+
919
+ async def get_mpp(
920
+ self,
921
+ namespace: GetMppRequestNamespace,
922
+ id: str,
923
+ mpp_id: str,
924
+ *,
925
+ request_options: typing.Optional[RequestOptions] = None,
926
+ ) -> AsyncHttpResponse[GetMppResponse]:
927
+ """
928
+ Parameters
929
+ ----------
930
+ namespace : GetMppRequestNamespace
931
+ Assembly URL namespace. `user`, `shared`, and `public` are routed through the same assembly lookup.
932
+
933
+ id : str
934
+ Assembly ID.
935
+
936
+ mpp_id : str
937
+ Manufacturing Process Plan ID.
938
+
939
+ request_options : typing.Optional[RequestOptions]
940
+ Request-specific configuration.
941
+
942
+ Returns
943
+ -------
944
+ AsyncHttpResponse[GetMppResponse]
945
+ Process plan document wrapper.
946
+ """
947
+ _response = await self._client_wrapper.httpx_client.request(
948
+ f"api/v4/assemblies/{encode_path_param(namespace)}/{encode_path_param(id)}/mpps/{encode_path_param(mpp_id)}",
949
+ method="GET",
950
+ request_options=request_options,
951
+ )
952
+ try:
953
+ if 200 <= _response.status_code < 300:
954
+ _data = typing.cast(
955
+ GetMppResponse,
956
+ parse_obj_as(
957
+ type_=GetMppResponse, # type: ignore
958
+ object_=_response.json(),
959
+ ),
960
+ )
961
+ return AsyncHttpResponse(response=_response, data=_data)
962
+ _response_json = _response.json()
963
+ except JSONDecodeError:
964
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
965
+ except ValidationError as e:
966
+ raise ParsingError(
967
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
968
+ )
969
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
970
+
971
+ async def delete_mpp(
972
+ self,
973
+ namespace: DeleteMppRequestNamespace,
974
+ id: str,
975
+ mpp_id: str,
976
+ *,
977
+ request_options: typing.Optional[RequestOptions] = None,
978
+ ) -> AsyncHttpResponse[DeleteMppResponse]:
979
+ """
980
+ Parameters
981
+ ----------
982
+ namespace : DeleteMppRequestNamespace
983
+ Assembly URL namespace. `user`, `shared`, and `public` are routed through the same assembly lookup.
984
+
985
+ id : str
986
+ Assembly ID.
987
+
988
+ mpp_id : str
989
+ Manufacturing Process Plan ID.
990
+
991
+ request_options : typing.Optional[RequestOptions]
992
+ Request-specific configuration.
993
+
994
+ Returns
995
+ -------
996
+ AsyncHttpResponse[DeleteMppResponse]
997
+ Delete status.
998
+ """
999
+ _response = await self._client_wrapper.httpx_client.request(
1000
+ f"api/v4/assemblies/{encode_path_param(namespace)}/{encode_path_param(id)}/mpps/{encode_path_param(mpp_id)}",
1001
+ method="DELETE",
1002
+ request_options=request_options,
1003
+ )
1004
+ try:
1005
+ if 200 <= _response.status_code < 300:
1006
+ _data = typing.cast(
1007
+ DeleteMppResponse,
1008
+ parse_obj_as(
1009
+ type_=DeleteMppResponse, # type: ignore
1010
+ object_=_response.json(),
1011
+ ),
1012
+ )
1013
+ return AsyncHttpResponse(response=_response, data=_data)
1014
+ _response_json = _response.json()
1015
+ except JSONDecodeError:
1016
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1017
+ except ValidationError as e:
1018
+ raise ParsingError(
1019
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
1020
+ )
1021
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1022
+
1023
+ async def plan(
1024
+ self,
1025
+ namespace: PlanRequestNamespace,
1026
+ id: str,
1027
+ mpp_id: str,
1028
+ *,
1029
+ station_ids: typing.Sequence[str],
1030
+ overwrite: typing.Optional[bool] = OMIT,
1031
+ request_options: typing.Optional[RequestOptions] = None,
1032
+ ) -> AsyncHttpResponse[SeqPlanAccepted]:
1033
+ """
1034
+ Plans the Station graph from scratch, computing a suitable process plan (Step graph)
1035
+ for each of the requested stations. The run overwrites any pre-existing plan; deciding which
1036
+ stations have to be re-planned is the caller's responsibility.
1037
+ Pass `overwrite: false` to have a station that already has a plan left alone instead.
1038
+
1039
+ **Async** — returns 202 immediately.
1040
+
1041
+ Parameters
1042
+ ----------
1043
+ namespace : PlanRequestNamespace
1044
+ Assembly URL namespace. `user`, `shared`, and `public` are routed through the same assembly lookup.
1045
+
1046
+ id : str
1047
+ Assembly ID.
1048
+
1049
+ mpp_id : str
1050
+ Manufacturing Process Plan ID.
1051
+
1052
+ station_ids : typing.Sequence[str]
1053
+ IDs of the Station nodes to plan. All must exist in the process plan's station graph and have a supported input/output boundary.
1054
+
1055
+ overwrite : typing.Optional[bool]
1056
+ Whether the run may replace a plan a requested station already has. Checked per station, so one station never blocks another.
1057
+
1058
+ request_options : typing.Optional[RequestOptions]
1059
+ Request-specific configuration.
1060
+
1061
+ Returns
1062
+ -------
1063
+ AsyncHttpResponse[SeqPlanAccepted]
1064
+ Planning jobs accepted and running in the background.
1065
+ """
1066
+ _response = await self._client_wrapper.httpx_client.request(
1067
+ f"api/v4/assemblies/{encode_path_param(namespace)}/{encode_path_param(id)}/mpps/{encode_path_param(mpp_id)}:seq-plan",
1068
+ method="POST",
1069
+ json={
1070
+ "stationIds": station_ids,
1071
+ "overwrite": overwrite,
1072
+ },
1073
+ headers={
1074
+ "content-type": "application/json",
1075
+ },
1076
+ request_options=request_options,
1077
+ omit=OMIT,
1078
+ )
1079
+ try:
1080
+ if 200 <= _response.status_code < 300:
1081
+ _data = typing.cast(
1082
+ SeqPlanAccepted,
1083
+ parse_obj_as(
1084
+ type_=SeqPlanAccepted, # type: ignore
1085
+ object_=_response.json(),
1086
+ ),
1087
+ )
1088
+ return AsyncHttpResponse(response=_response, data=_data)
1089
+ if _response.status_code == 400:
1090
+ raise BadRequestError(
1091
+ headers=dict(_response.headers),
1092
+ body=typing.cast(
1093
+ typing.Any,
1094
+ parse_obj_as(
1095
+ type_=typing.Any, # type: ignore
1096
+ object_=_response.json(),
1097
+ ),
1098
+ ),
1099
+ )
1100
+ if _response.status_code == 404:
1101
+ raise NotFoundError(
1102
+ headers=dict(_response.headers),
1103
+ body=typing.cast(
1104
+ ErrorResponse,
1105
+ parse_obj_as(
1106
+ type_=ErrorResponse, # type: ignore
1107
+ object_=_response.json(),
1108
+ ),
1109
+ ),
1110
+ )
1111
+ if _response.status_code == 409:
1112
+ raise ConflictError(
1113
+ headers=dict(_response.headers),
1114
+ body=typing.cast(
1115
+ typing.Any,
1116
+ parse_obj_as(
1117
+ type_=typing.Any, # type: ignore
1118
+ object_=_response.json(),
1119
+ ),
1120
+ ),
1121
+ )
1122
+ _response_json = _response.json()
1123
+ except JSONDecodeError:
1124
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1125
+ except ValidationError as e:
1126
+ raise ParsingError(
1127
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
1128
+ )
1129
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1130
+
1131
+ async def validate(
1132
+ self,
1133
+ namespace: ValidateRequestNamespace,
1134
+ id: str,
1135
+ mpp_id: str,
1136
+ *,
1137
+ station_ids: typing.Sequence[str],
1138
+ fix_directions: typing.Optional[bool] = OMIT,
1139
+ request_options: typing.Optional[RequestOptions] = None,
1140
+ ) -> AsyncHttpResponse[SeqPlanAccepted]:
1141
+ """
1142
+ **Feasibility validation** — checks structural consistency of the entire process plan,
1143
+ then validates geometrical feasibility of assembly steps for the requested
1144
+ stations. When a blocked step has a workspace-free alternative direction,
1145
+ `fixDirections` (off by default) writes it onto the step graph and the
1146
+ persisted verdict reflects the repaired plan.
1147
+
1148
+ **Async** — returns 202 with `{ queued }`.
1149
+
1150
+ Parameters
1151
+ ----------
1152
+ namespace : ValidateRequestNamespace
1153
+ Assembly URL namespace. `user`, `shared`, and `public` are routed through the same assembly lookup.
1154
+
1155
+ id : str
1156
+ Assembly ID.
1157
+
1158
+ mpp_id : str
1159
+ Manufacturing Process Plan ID.
1160
+
1161
+ station_ids : typing.Sequence[str]
1162
+ IDs of the Station nodes to validate. All must exist in the process plan's station graph and stations without persisted assembly steps are accepted and reported as skipped.
1163
+
1164
+ fix_directions : typing.Optional[bool]
1165
+ Apply each blocked step's workspace-free alternative direction onto the step graph, so the persisted verdict describes the repaired plan. Absent, the step graph is untouched.
1166
+
1167
+ request_options : typing.Optional[RequestOptions]
1168
+ Request-specific configuration.
1169
+
1170
+ Returns
1171
+ -------
1172
+ AsyncHttpResponse[SeqPlanAccepted]
1173
+ Validation jobs accepted and running in the background.
1174
+ """
1175
+ _response = await self._client_wrapper.httpx_client.request(
1176
+ f"api/v4/assemblies/{encode_path_param(namespace)}/{encode_path_param(id)}/mpps/{encode_path_param(mpp_id)}:validate",
1177
+ method="POST",
1178
+ json={
1179
+ "stationIds": station_ids,
1180
+ "fixDirections": fix_directions,
1181
+ },
1182
+ headers={
1183
+ "content-type": "application/json",
1184
+ },
1185
+ request_options=request_options,
1186
+ omit=OMIT,
1187
+ )
1188
+ try:
1189
+ if 200 <= _response.status_code < 300:
1190
+ _data = typing.cast(
1191
+ SeqPlanAccepted,
1192
+ parse_obj_as(
1193
+ type_=SeqPlanAccepted, # type: ignore
1194
+ object_=_response.json(),
1195
+ ),
1196
+ )
1197
+ return AsyncHttpResponse(response=_response, data=_data)
1198
+ if _response.status_code == 400:
1199
+ raise BadRequestError(
1200
+ headers=dict(_response.headers),
1201
+ body=typing.cast(
1202
+ typing.Any,
1203
+ parse_obj_as(
1204
+ type_=typing.Any, # type: ignore
1205
+ object_=_response.json(),
1206
+ ),
1207
+ ),
1208
+ )
1209
+ if _response.status_code == 404:
1210
+ raise NotFoundError(
1211
+ headers=dict(_response.headers),
1212
+ body=typing.cast(
1213
+ ErrorResponse,
1214
+ parse_obj_as(
1215
+ type_=ErrorResponse, # type: ignore
1216
+ object_=_response.json(),
1217
+ ),
1218
+ ),
1219
+ )
1220
+ if _response.status_code == 422:
1221
+ raise UnprocessableEntityError(
1222
+ headers=dict(_response.headers),
1223
+ body=typing.cast(
1224
+ ErrorResponse,
1225
+ parse_obj_as(
1226
+ type_=ErrorResponse, # type: ignore
1227
+ object_=_response.json(),
1228
+ ),
1229
+ ),
1230
+ )
1231
+ _response_json = _response.json()
1232
+ except JSONDecodeError:
1233
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1234
+ except ValidationError as e:
1235
+ raise ParsingError(
1236
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
1237
+ )
1238
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1239
+
1240
+ async def evaluate_dfa(
1241
+ self,
1242
+ namespace: EvaluateDfaRequestNamespace,
1243
+ id: str,
1244
+ mpp_id: str,
1245
+ *,
1246
+ station_ids: typing.Optional[typing.Sequence[str]] = OMIT,
1247
+ request_options: typing.Optional[RequestOptions] = None,
1248
+ ) -> AsyncHttpResponse[SeqPlanAccepted]:
1249
+ """
1250
+ Projects each sequential assembly addend directly from the persisted Step
1251
+ graph into an explicit state-of-assembly transition, evaluates DFA, and
1252
+ persists per-station reports under `plan.dfa`. Runs asynchronously.
1253
+
1254
+ Parameters
1255
+ ----------
1256
+ namespace : EvaluateDfaRequestNamespace
1257
+ Assembly URL namespace. `user`, `shared`, and `public` are routed through the same assembly lookup.
1258
+
1259
+ id : str
1260
+ Assembly ID.
1261
+
1262
+ mpp_id : str
1263
+ Manufacturing Process Plan ID.
1264
+
1265
+ station_ids : typing.Optional[typing.Sequence[str]]
1266
+ Stations to score. Omitted means every station with assembly steps, and then a station that is not ready is skipped rather than refused. A station named here must be planned and hold a feasible validation verdict, or the whole request is refused with 409. Named stations without assembly steps are accepted and reported as skipped.
1267
+
1268
+ request_options : typing.Optional[RequestOptions]
1269
+ Request-specific configuration.
1270
+
1271
+ Returns
1272
+ -------
1273
+ AsyncHttpResponse[SeqPlanAccepted]
1274
+ DFA evaluation accepted (or nothing to evaluate). `skipped` lists requested stations that were not queued — no assembly steps, or, for an unfiltered request, not yet validated.
1275
+ """
1276
+ _response = await self._client_wrapper.httpx_client.request(
1277
+ f"api/v4/assemblies/{encode_path_param(namespace)}/{encode_path_param(id)}/mpps/{encode_path_param(mpp_id)}:dfa",
1278
+ method="POST",
1279
+ json={
1280
+ "stationIds": station_ids,
1281
+ },
1282
+ headers={
1283
+ "content-type": "application/json",
1284
+ },
1285
+ request_options=request_options,
1286
+ omit=OMIT,
1287
+ )
1288
+ try:
1289
+ if 200 <= _response.status_code < 300:
1290
+ _data = typing.cast(
1291
+ SeqPlanAccepted,
1292
+ parse_obj_as(
1293
+ type_=SeqPlanAccepted, # type: ignore
1294
+ object_=_response.json(),
1295
+ ),
1296
+ )
1297
+ return AsyncHttpResponse(response=_response, data=_data)
1298
+ if _response.status_code == 400:
1299
+ raise BadRequestError(
1300
+ headers=dict(_response.headers),
1301
+ body=typing.cast(
1302
+ typing.Any,
1303
+ parse_obj_as(
1304
+ type_=typing.Any, # type: ignore
1305
+ object_=_response.json(),
1306
+ ),
1307
+ ),
1308
+ )
1309
+ if _response.status_code == 404:
1310
+ raise NotFoundError(
1311
+ headers=dict(_response.headers),
1312
+ body=typing.cast(
1313
+ ErrorResponse,
1314
+ parse_obj_as(
1315
+ type_=ErrorResponse, # type: ignore
1316
+ object_=_response.json(),
1317
+ ),
1318
+ ),
1319
+ )
1320
+ if _response.status_code == 409:
1321
+ raise ConflictError(
1322
+ headers=dict(_response.headers),
1323
+ body=typing.cast(
1324
+ typing.Any,
1325
+ parse_obj_as(
1326
+ type_=typing.Any, # type: ignore
1327
+ object_=_response.json(),
1328
+ ),
1329
+ ),
1330
+ )
1331
+ if _response.status_code == 422:
1332
+ raise UnprocessableEntityError(
1333
+ headers=dict(_response.headers),
1334
+ body=typing.cast(
1335
+ ErrorResponse,
1336
+ parse_obj_as(
1337
+ type_=ErrorResponse, # type: ignore
1338
+ object_=_response.json(),
1339
+ ),
1340
+ ),
1341
+ )
1342
+ _response_json = _response.json()
1343
+ except JSONDecodeError:
1344
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1345
+ except ValidationError as e:
1346
+ raise ParsingError(
1347
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
1348
+ )
1349
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)