UncountablePythonSDK 0.0.24__py3-none-any.whl → 0.0.26__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.
Potentially problematic release.
This version of UncountablePythonSDK might be problematic. Click here for more details.
- {UncountablePythonSDK-0.0.24.dist-info → UncountablePythonSDK-0.0.26.dist-info}/METADATA +1 -1
- {UncountablePythonSDK-0.0.24.dist-info → UncountablePythonSDK-0.0.26.dist-info}/RECORD +42 -26
- examples/create_entity.py +3 -4
- pkgs/argument_parser/argument_parser.py +41 -6
- pkgs/type_spec/builder.py +6 -1
- pkgs/type_spec/emit_open_api.py +14 -5
- pkgs/type_spec/emit_open_api_util.py +1 -0
- type_spec/external/api/entity/list_entities.yaml +2 -2
- type_spec/external/api/entity/lock_entity.yaml +21 -0
- type_spec/external/api/entity/unlock_entity.yaml +18 -0
- type_spec/external/api/field_options/upsert_field_options.yaml +37 -0
- type_spec/external/api/id_source/list_id_source.yaml +2 -2
- type_spec/external/api/inputs/get_input_data.yaml +2 -2
- type_spec/external/api/inputs/get_input_names.yaml +2 -2
- type_spec/external/api/inputs/set_input_category.yaml +23 -0
- type_spec/external/api/inputs/set_input_subcategories.yaml +23 -0
- type_spec/external/api/material_families/update_entity_material_families.yaml +33 -0
- type_spec/external/api/outputs/get_output_data.yaml +2 -2
- type_spec/external/api/outputs/get_output_names.yaml +2 -2
- type_spec/external/api/project/get_projects_data.yaml +2 -2
- type_spec/external/api/recipe_metadata/get_recipe_metadata_data.yaml +2 -2
- type_spec/external/api/recipes/create_recipe.yaml +3 -0
- type_spec/external/api/recipes/get_recipes_data.yaml +2 -2
- type_spec/external/api/recipes/unarchive_recipes.yaml +17 -0
- uncountable/core/__init__.py +3 -2
- uncountable/core/client.py +83 -20
- uncountable/core/types.py +7 -13
- uncountable/types/__init__.py +14 -0
- uncountable/types/api/entity/lock_entity.py +38 -0
- uncountable/types/api/entity/unlock_entity.py +37 -0
- uncountable/types/api/field_options/__init__.py +1 -0
- uncountable/types/api/field_options/upsert_field_options.py +45 -0
- uncountable/types/api/inputs/set_input_category.py +37 -0
- uncountable/types/api/inputs/set_input_subcategories.py +38 -0
- uncountable/types/api/material_families/__init__.py +1 -0
- uncountable/types/api/material_families/update_entity_material_families.py +41 -0
- uncountable/types/api/recipes/create_recipe.py +1 -0
- uncountable/types/api/recipes/unarchive_recipes.py +34 -0
- uncountable/types/async_batch_processor.py +3 -0
- uncountable/types/client_base.py +192 -18
- {UncountablePythonSDK-0.0.24.dist-info → UncountablePythonSDK-0.0.26.dist-info}/WHEEL +0 -0
- {UncountablePythonSDK-0.0.24.dist-info → UncountablePythonSDK-0.0.26.dist-info}/top_level.txt +0 -0
|
@@ -13,10 +13,10 @@ Arguments:
|
|
|
13
13
|
desc: "The material family ID to get the output values from"
|
|
14
14
|
offset?:
|
|
15
15
|
type: Integer
|
|
16
|
-
desc:
|
|
16
|
+
desc: Used for pagination, where the number of results returned exceeds the limit. Results are always ordered by the output ID. [Pagination More Info](#pagination)
|
|
17
17
|
limit?:
|
|
18
18
|
type: Integer
|
|
19
|
-
desc:
|
|
19
|
+
desc: The maximum number of results to return. By default this is set to 20,000 and it cannot be set higher than 20,000. [Pagination More Info](#pagination)
|
|
20
20
|
|
|
21
21
|
OutputWithName:
|
|
22
22
|
type: Object
|
|
@@ -12,10 +12,10 @@ Arguments:
|
|
|
12
12
|
desc: "The projects to get the data from"
|
|
13
13
|
offset?:
|
|
14
14
|
type: Optional<Integer>
|
|
15
|
-
desc:
|
|
15
|
+
desc: Used for pagination. All pagination is done in order of Project ID. [Pagination More Info](#pagination)
|
|
16
16
|
limit?:
|
|
17
17
|
type: Optional<Integer>
|
|
18
|
-
desc:
|
|
18
|
+
desc: The number of data points to return. If not filled in, it will be set to 100, and cannot be set higher than 100. [Pagination More Info](#pagination)
|
|
19
19
|
|
|
20
20
|
ProjectDetailed:
|
|
21
21
|
type: Object
|
|
@@ -16,10 +16,10 @@ Arguments:
|
|
|
16
16
|
desc: "The recipe metadata IDs to get the data from. If this is not filled in, all metadata from a material family will be returned (in paginated form)."
|
|
17
17
|
offset?:
|
|
18
18
|
type: Optional<Integer>
|
|
19
|
-
desc:
|
|
19
|
+
desc: Used for pagination, where the number of results returned exceeds the limit. Results are always ordered by the metadata ID. [Pagination More Info](#pagination)
|
|
20
20
|
limit?:
|
|
21
21
|
type: Optional<Integer>
|
|
22
|
-
desc:
|
|
22
|
+
desc: The maximum number of results to return. By default this is set to 1,000 and it cannot be set higher than 1,000. [Pagination More Info](#pagination)
|
|
23
23
|
|
|
24
24
|
FullRecipeMetadataField:
|
|
25
25
|
type: Object
|
|
@@ -16,6 +16,9 @@ Arguments:
|
|
|
16
16
|
material_family_id:
|
|
17
17
|
type: ObjectId
|
|
18
18
|
desc: The material family for the recipe
|
|
19
|
+
project_id?:
|
|
20
|
+
type: ObjectId
|
|
21
|
+
desc: The identifier of the project to create the recipe in
|
|
19
22
|
workflow_id:
|
|
20
23
|
type: ObjectId
|
|
21
24
|
desc: The identifier of the workflow to create the recipe with
|
|
@@ -15,10 +15,10 @@ Arguments:
|
|
|
15
15
|
desc: "The projects to get the data from. Either these or recipe_ids must be filled in"
|
|
16
16
|
offset?:
|
|
17
17
|
type: Optional<Integer>
|
|
18
|
-
desc:
|
|
18
|
+
desc: Used for pagination. All pagination is done in order of Recipe ID. [Pagination More Info](#pagination)
|
|
19
19
|
limit?:
|
|
20
20
|
type: Optional<Integer>
|
|
21
|
-
desc:
|
|
21
|
+
desc: The number of data points to return. If not filled in, it will be set to 100, and cannot be set higher than 100. [Pagination More Info](#pagination)
|
|
22
22
|
|
|
23
23
|
RecipeOutput:
|
|
24
24
|
type: Object
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
$endpoint:
|
|
2
|
+
is_sdk: true
|
|
3
|
+
method: post
|
|
4
|
+
path: ${external}/recipes/unarchive
|
|
5
|
+
function: main.site.app.external.recipes.unarchive_recipes.unarchive_recipes
|
|
6
|
+
desc: Unarchive/restore the provided recipes
|
|
7
|
+
|
|
8
|
+
Arguments:
|
|
9
|
+
type: Object
|
|
10
|
+
properties:
|
|
11
|
+
recipes:
|
|
12
|
+
type: List<identifier.IdentifierKey>
|
|
13
|
+
desc: Identifier for the recipe
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
Data:
|
|
17
|
+
type: Object
|
uncountable/core/__init__.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
from .client import
|
|
1
|
+
from .client import Client
|
|
2
|
+
from .types import AuthDetailsApiKey, AuthDetailsOAuth
|
|
2
3
|
from .file_upload import MediaFileUpload, UploadedFile
|
|
3
4
|
from .async_batch import AsyncBatchProcessor
|
|
4
5
|
|
|
5
|
-
__all__: list[str] = ["AuthDetailsApiKey", "AsyncBatchProcessor", "Client", "MediaFileUpload", "UploadedFile"]
|
|
6
|
+
__all__: list[str] = ["AuthDetailsApiKey", "AuthDetailsOAuth", "AsyncBatchProcessor", "Client", "MediaFileUpload", "UploadedFile"]
|
uncountable/core/client.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import base64
|
|
2
|
+
from datetime import datetime, timedelta
|
|
2
3
|
import json
|
|
3
4
|
import typing
|
|
4
5
|
from dataclasses import dataclass
|
|
@@ -14,7 +15,7 @@ from pkgs.serialization_util.serialization_helpers import JsonValue
|
|
|
14
15
|
from uncountable.types.client_base import APIRequest, ClientMethods
|
|
15
16
|
|
|
16
17
|
from .file_upload import FileUpload, FileUploader, UploadedFile
|
|
17
|
-
from .types import AuthDetails, AuthDetailsApiKey
|
|
18
|
+
from .types import AuthDetails, AuthDetailsApiKey, AuthDetailsOAuth
|
|
18
19
|
|
|
19
20
|
DT = typing.TypeVar("DT")
|
|
20
21
|
|
|
@@ -48,11 +49,13 @@ class HTTPPostRequest(HTTPRequestBase):
|
|
|
48
49
|
HTTPRequest = HTTPPostRequest | HTTPGetRequest
|
|
49
50
|
|
|
50
51
|
|
|
51
|
-
|
|
52
52
|
@dataclass(kw_only=True)
|
|
53
|
-
class ClientConfig
|
|
53
|
+
class ClientConfig:
|
|
54
54
|
allow_insecure_tls: bool = False
|
|
55
|
-
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
OAUTH_REFRESH_WINDOW_SECONDS = 60 * 5
|
|
58
|
+
|
|
56
59
|
|
|
57
60
|
class APIResponseError(BaseException):
|
|
58
61
|
status_code: int
|
|
@@ -107,19 +110,60 @@ class SDKError(BaseException):
|
|
|
107
110
|
return f"internal SDK error, please contact Uncountable support: {self.message}"
|
|
108
111
|
|
|
109
112
|
|
|
113
|
+
@dataclass(kw_only=True)
|
|
114
|
+
class OAuthBearerTokenCache:
|
|
115
|
+
token: str
|
|
116
|
+
expires_at: datetime
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@dataclass(kw_only=True)
|
|
120
|
+
class GetOauthBearerTokenData:
|
|
121
|
+
access_token: str
|
|
122
|
+
expires_in: int
|
|
123
|
+
token_type: str
|
|
124
|
+
scope: str
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
oauth_bearer_token_data_parser = CachedParser(GetOauthBearerTokenData)
|
|
128
|
+
|
|
129
|
+
|
|
110
130
|
class Client(ClientMethods):
|
|
111
131
|
_parser_map: dict[type, CachedParser] = {}
|
|
112
132
|
_auth_details: AuthDetails
|
|
113
133
|
_base_url: str
|
|
114
134
|
_file_uploader: FileUploader
|
|
115
135
|
_cfg: ClientConfig
|
|
136
|
+
_oauth_bearer_token_cache: OAuthBearerTokenCache | None = None
|
|
116
137
|
|
|
117
|
-
def __init__(
|
|
138
|
+
def __init__(
|
|
139
|
+
self,
|
|
140
|
+
*,
|
|
141
|
+
base_url: str,
|
|
142
|
+
auth_details: AuthDetails,
|
|
143
|
+
config: ClientConfig | None = None,
|
|
144
|
+
):
|
|
118
145
|
self._auth_details = auth_details
|
|
119
146
|
self._base_url = base_url
|
|
120
147
|
self._file_uploader = FileUploader(self._base_url, self._auth_details)
|
|
121
148
|
self._cfg = config or ClientConfig()
|
|
122
149
|
|
|
150
|
+
def _get_response_json(self, response: requests.Response) -> dict[str, JsonValue]:
|
|
151
|
+
if response.status_code < 200 or response.status_code > 299:
|
|
152
|
+
extra_details: dict[str, JsonValue] | None = None
|
|
153
|
+
try:
|
|
154
|
+
data = response.json()
|
|
155
|
+
if "error" in data:
|
|
156
|
+
extra_details = data["error"]
|
|
157
|
+
except JSONDecodeError:
|
|
158
|
+
pass
|
|
159
|
+
raise APIResponseError.construct_error(
|
|
160
|
+
status_code=response.status_code, extra_details=extra_details
|
|
161
|
+
)
|
|
162
|
+
try:
|
|
163
|
+
return response.json()
|
|
164
|
+
except JSONDecodeError:
|
|
165
|
+
raise SDKError("unable to process response")
|
|
166
|
+
|
|
123
167
|
def do_request(self, *, api_request: APIRequest, return_type: type[DT]) -> DT:
|
|
124
168
|
http_request = self._build_http_request(api_request=api_request)
|
|
125
169
|
match http_request:
|
|
@@ -128,7 +172,7 @@ class Client(ClientMethods):
|
|
|
128
172
|
http_request.url,
|
|
129
173
|
headers=http_request.headers,
|
|
130
174
|
params=http_request.query_params,
|
|
131
|
-
verify=not self._cfg.allow_insecure_tls
|
|
175
|
+
verify=not self._cfg.allow_insecure_tls,
|
|
132
176
|
)
|
|
133
177
|
case HTTPPostRequest():
|
|
134
178
|
response = requests.post(
|
|
@@ -136,26 +180,16 @@ class Client(ClientMethods):
|
|
|
136
180
|
headers=http_request.headers,
|
|
137
181
|
data=http_request.body,
|
|
138
182
|
params=http_request.query_params,
|
|
139
|
-
verify=not self._cfg.allow_insecure_tls
|
|
183
|
+
verify=not self._cfg.allow_insecure_tls,
|
|
140
184
|
)
|
|
141
185
|
case _:
|
|
142
186
|
typing.assert_never(http_request)
|
|
143
|
-
|
|
144
|
-
extra_details: dict[str, JsonValue] | None = None
|
|
145
|
-
try:
|
|
146
|
-
data = response.json()
|
|
147
|
-
if "error" in data:
|
|
148
|
-
extra_details = data["error"]
|
|
149
|
-
except JSONDecodeError:
|
|
150
|
-
pass
|
|
151
|
-
raise APIResponseError.construct_error(
|
|
152
|
-
status_code=response.status_code, extra_details=extra_details
|
|
153
|
-
)
|
|
187
|
+
response_data = self._get_response_json(response)
|
|
154
188
|
cached_parser = self._get_cached_parser(return_type)
|
|
155
189
|
try:
|
|
156
|
-
data =
|
|
190
|
+
data = response_data["data"]
|
|
157
191
|
return cached_parser.parse_api(data)
|
|
158
|
-
except ValueError | JSONDecodeError:
|
|
192
|
+
except ValueError | JSONDecodeError | KeyError:
|
|
159
193
|
raise SDKError("unable to process response")
|
|
160
194
|
|
|
161
195
|
def _get_cached_parser(self, data_type: type[DT]) -> CachedParser[DT]:
|
|
@@ -163,6 +197,32 @@ class Client(ClientMethods):
|
|
|
163
197
|
self._parser_map[data_type] = CachedParser(data_type)
|
|
164
198
|
return self._parser_map[data_type]
|
|
165
199
|
|
|
200
|
+
def _get_oauth_bearer_token(self, *, oauth_details: AuthDetailsOAuth) -> str:
|
|
201
|
+
if (
|
|
202
|
+
self._oauth_bearer_token_cache is None
|
|
203
|
+
or (
|
|
204
|
+
self._oauth_bearer_token_cache.expires_at - datetime.now()
|
|
205
|
+
).total_seconds()
|
|
206
|
+
< OAUTH_REFRESH_WINDOW_SECONDS
|
|
207
|
+
):
|
|
208
|
+
refresh_url = urljoin(self._base_url, "/token/get_bearer_token")
|
|
209
|
+
response = requests.post(
|
|
210
|
+
refresh_url,
|
|
211
|
+
data={
|
|
212
|
+
"client_secret": oauth_details.refresh_token,
|
|
213
|
+
"scope": oauth_details.scope,
|
|
214
|
+
"grant_type": "client_credentials",
|
|
215
|
+
},
|
|
216
|
+
)
|
|
217
|
+
data = self._get_response_json(response)
|
|
218
|
+
token_data = oauth_bearer_token_data_parser.parse_storage(data)
|
|
219
|
+
self._oauth_bearer_token_cache = OAuthBearerTokenCache(
|
|
220
|
+
token=token_data.access_token,
|
|
221
|
+
expires_at=datetime.now() + timedelta(seconds=token_data.expires_in),
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
return self._oauth_bearer_token_cache.token
|
|
225
|
+
|
|
166
226
|
def _build_auth_headers(self) -> dict[str, str]:
|
|
167
227
|
match self._auth_details:
|
|
168
228
|
case AuthDetailsApiKey():
|
|
@@ -170,6 +230,9 @@ class Client(ClientMethods):
|
|
|
170
230
|
f"{self._auth_details.api_id}:{self._auth_details.api_secret_key}".encode()
|
|
171
231
|
).decode("utf-8")
|
|
172
232
|
return {"Authorization": f"Basic {encoded}"}
|
|
233
|
+
case AuthDetailsOAuth():
|
|
234
|
+
token = self._get_oauth_bearer_token(oauth_details=self._auth_details)
|
|
235
|
+
return {"Authorization": f"Bearer {token}"}
|
|
173
236
|
typing.assert_never(self._auth_details)
|
|
174
237
|
|
|
175
238
|
def _build_http_request(self, *, api_request: APIRequest) -> HTTPRequest:
|
uncountable/core/types.py
CHANGED
|
@@ -1,16 +1,4 @@
|
|
|
1
|
-
import base64
|
|
2
|
-
import json
|
|
3
|
-
import typing
|
|
4
1
|
from dataclasses import dataclass
|
|
5
|
-
from enum import StrEnum
|
|
6
|
-
from urllib.parse import urljoin
|
|
7
|
-
|
|
8
|
-
import aiohttp
|
|
9
|
-
import requests
|
|
10
|
-
|
|
11
|
-
from pkgs.argument_parser import CachedParser
|
|
12
|
-
from pkgs.serialization_util import serialize_for_api
|
|
13
|
-
from uncountable.types.client_base import APIRequest, ClientMethods
|
|
14
2
|
|
|
15
3
|
|
|
16
4
|
@dataclass(kw_only=True)
|
|
@@ -19,4 +7,10 @@ class AuthDetailsApiKey:
|
|
|
19
7
|
api_secret_key: str
|
|
20
8
|
|
|
21
9
|
|
|
22
|
-
|
|
10
|
+
@dataclass(kw_only=True)
|
|
11
|
+
class AuthDetailsOAuth:
|
|
12
|
+
refresh_token: str
|
|
13
|
+
scope: str = "unc.rnd"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
AuthDetails = AuthDetailsApiKey | AuthDetailsOAuth
|
uncountable/types/__init__.py
CHANGED
|
@@ -48,6 +48,7 @@ from . import input_attributes as input_attributes_t
|
|
|
48
48
|
from . import inputs as inputs_t
|
|
49
49
|
from .api.entity import list_entities as list_entities_t
|
|
50
50
|
from .api.id_source import list_id_source as list_id_source_t
|
|
51
|
+
from .api.entity import lock_entity as lock_entity_t
|
|
51
52
|
from .api.id_source import match_id_source as match_id_source_t
|
|
52
53
|
from . import outputs as outputs_t
|
|
53
54
|
from . import permissions as permissions_t
|
|
@@ -66,13 +67,19 @@ from . import response as response_t
|
|
|
66
67
|
from .api.triggers import run_trigger as run_trigger_t
|
|
67
68
|
from .api.permissions import set_core_permissions as set_core_permissions_t
|
|
68
69
|
from .api.inputs import set_input_attribute_values as set_input_attribute_values_t
|
|
70
|
+
from .api.inputs import set_input_category as set_input_category_t
|
|
71
|
+
from .api.inputs import set_input_subcategories as set_input_subcategories_t
|
|
69
72
|
from .api.recipes import set_recipe_inputs as set_recipe_inputs_t
|
|
70
73
|
from .api.recipes import set_recipe_metadata as set_recipe_metadata_t
|
|
71
74
|
from .api.recipes import set_recipe_outputs as set_recipe_outputs_t
|
|
72
75
|
from .api.recipes import set_recipe_tags as set_recipe_tags_t
|
|
73
76
|
from .api.entity import set_values as set_values_t
|
|
74
77
|
from .api.entity import transition_entity_phase as transition_entity_phase_t
|
|
78
|
+
from .api.recipes import unarchive_recipes as unarchive_recipes_t
|
|
75
79
|
from . import units as units_t
|
|
80
|
+
from .api.entity import unlock_entity as unlock_entity_t
|
|
81
|
+
from .api.material_families import update_entity_material_families as update_entity_material_families_t
|
|
82
|
+
from .api.field_options import upsert_field_options as upsert_field_options_t
|
|
76
83
|
from . import users as users_t
|
|
77
84
|
from . import workflows as workflows_t
|
|
78
85
|
|
|
@@ -123,6 +130,7 @@ __all__: list[str] = [
|
|
|
123
130
|
"inputs_t",
|
|
124
131
|
"list_entities_t",
|
|
125
132
|
"list_id_source_t",
|
|
133
|
+
"lock_entity_t",
|
|
126
134
|
"match_id_source_t",
|
|
127
135
|
"outputs_t",
|
|
128
136
|
"permissions_t",
|
|
@@ -141,13 +149,19 @@ __all__: list[str] = [
|
|
|
141
149
|
"run_trigger_t",
|
|
142
150
|
"set_core_permissions_t",
|
|
143
151
|
"set_input_attribute_values_t",
|
|
152
|
+
"set_input_category_t",
|
|
153
|
+
"set_input_subcategories_t",
|
|
144
154
|
"set_recipe_inputs_t",
|
|
145
155
|
"set_recipe_metadata_t",
|
|
146
156
|
"set_recipe_outputs_t",
|
|
147
157
|
"set_recipe_tags_t",
|
|
148
158
|
"set_values_t",
|
|
149
159
|
"transition_entity_phase_t",
|
|
160
|
+
"unarchive_recipes_t",
|
|
150
161
|
"units_t",
|
|
162
|
+
"unlock_entity_t",
|
|
163
|
+
"update_entity_material_families_t",
|
|
164
|
+
"upsert_field_options_t",
|
|
151
165
|
"users_t",
|
|
152
166
|
"workflows_t",
|
|
153
167
|
]
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
2
|
+
# flake8: noqa: F821
|
|
3
|
+
# ruff: noqa: E402
|
|
4
|
+
# fmt: off
|
|
5
|
+
# isort: skip_file
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
import typing # noqa: F401
|
|
8
|
+
import datetime # noqa: F401
|
|
9
|
+
from decimal import Decimal # noqa: F401
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from ... import async_batch as async_batch_t
|
|
12
|
+
from ... import entity as entity_t
|
|
13
|
+
from ... import identifier as identifier_t
|
|
14
|
+
|
|
15
|
+
__all__: list[str] = [
|
|
16
|
+
"Arguments",
|
|
17
|
+
"Data",
|
|
18
|
+
"ENDPOINT_METHOD",
|
|
19
|
+
"ENDPOINT_PATH",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
ENDPOINT_METHOD = "POST"
|
|
23
|
+
ENDPOINT_PATH = "api/external/entity/external_lock_entity"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
27
|
+
@dataclass(kw_only=True)
|
|
28
|
+
class Arguments:
|
|
29
|
+
entity_key: identifier_t.IdentifierKey
|
|
30
|
+
entity_type: entity_t.EntityType
|
|
31
|
+
globally_removable: typing.Optional[bool] = None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
35
|
+
@dataclass(kw_only=True)
|
|
36
|
+
class Data(async_batch_t.AsyncBatchActionReturn):
|
|
37
|
+
pass
|
|
38
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
2
|
+
# flake8: noqa: F821
|
|
3
|
+
# ruff: noqa: E402
|
|
4
|
+
# fmt: off
|
|
5
|
+
# isort: skip_file
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
import typing # noqa: F401
|
|
8
|
+
import datetime # noqa: F401
|
|
9
|
+
from decimal import Decimal # noqa: F401
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from ... import async_batch as async_batch_t
|
|
12
|
+
from ... import entity as entity_t
|
|
13
|
+
from ... import identifier as identifier_t
|
|
14
|
+
|
|
15
|
+
__all__: list[str] = [
|
|
16
|
+
"Arguments",
|
|
17
|
+
"Data",
|
|
18
|
+
"ENDPOINT_METHOD",
|
|
19
|
+
"ENDPOINT_PATH",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
ENDPOINT_METHOD = "POST"
|
|
23
|
+
ENDPOINT_PATH = "api/external/entity/external_unlock_entity"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
27
|
+
@dataclass(kw_only=True)
|
|
28
|
+
class Arguments:
|
|
29
|
+
entity_key: identifier_t.IdentifierKey
|
|
30
|
+
entity_type: entity_t.EntityType
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
34
|
+
@dataclass(kw_only=True)
|
|
35
|
+
class Data(async_batch_t.AsyncBatchActionReturn):
|
|
36
|
+
pass
|
|
37
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
2
|
+
# flake8: noqa: F821
|
|
3
|
+
# ruff: noqa: E402
|
|
4
|
+
# fmt: off
|
|
5
|
+
# isort: skip_file
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
import typing # noqa: F401
|
|
8
|
+
import datetime # noqa: F401
|
|
9
|
+
from decimal import Decimal # noqa: F401
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from ... import identifier as identifier_t
|
|
12
|
+
|
|
13
|
+
__all__: list[str] = [
|
|
14
|
+
"Arguments",
|
|
15
|
+
"Data",
|
|
16
|
+
"ENDPOINT_METHOD",
|
|
17
|
+
"ENDPOINT_PATH",
|
|
18
|
+
"FieldOption",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
ENDPOINT_METHOD = "POST"
|
|
22
|
+
ENDPOINT_PATH = "api/external/field_options/upsert_field_options"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
26
|
+
@dataclass(kw_only=True)
|
|
27
|
+
class FieldOption:
|
|
28
|
+
option_id: str
|
|
29
|
+
option_value: typing.Optional[str] = None
|
|
30
|
+
archived: typing.Optional[bool] = None
|
|
31
|
+
subsets: typing.Optional[list[str]] = None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
35
|
+
@dataclass(kw_only=True)
|
|
36
|
+
class Arguments:
|
|
37
|
+
option_set_key: identifier_t.IdentifierKey
|
|
38
|
+
field_options: list[FieldOption]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
42
|
+
@dataclass(kw_only=True)
|
|
43
|
+
class Data:
|
|
44
|
+
pass
|
|
45
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
2
|
+
# flake8: noqa: F821
|
|
3
|
+
# ruff: noqa: E402
|
|
4
|
+
# fmt: off
|
|
5
|
+
# isort: skip_file
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
import typing # noqa: F401
|
|
8
|
+
import datetime # noqa: F401
|
|
9
|
+
from decimal import Decimal # noqa: F401
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from ... import identifier as identifier_t
|
|
12
|
+
from ... import response as response_t
|
|
13
|
+
|
|
14
|
+
__all__: list[str] = [
|
|
15
|
+
"Arguments",
|
|
16
|
+
"Data",
|
|
17
|
+
"ENDPOINT_METHOD",
|
|
18
|
+
"ENDPOINT_PATH",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
ENDPOINT_METHOD = "POST"
|
|
22
|
+
ENDPOINT_PATH = "api/external/inputs/external_set_input_category"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
26
|
+
@dataclass(kw_only=True)
|
|
27
|
+
class Arguments:
|
|
28
|
+
input_key: identifier_t.IdentifierKey
|
|
29
|
+
category_id: int
|
|
30
|
+
material_family_ids: typing.Optional[list[int]] = None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
34
|
+
@dataclass(kw_only=True)
|
|
35
|
+
class Data(response_t.Response):
|
|
36
|
+
pass
|
|
37
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
2
|
+
# flake8: noqa: F821
|
|
3
|
+
# ruff: noqa: E402
|
|
4
|
+
# fmt: off
|
|
5
|
+
# isort: skip_file
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
import typing # noqa: F401
|
|
8
|
+
import datetime # noqa: F401
|
|
9
|
+
from decimal import Decimal # noqa: F401
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from ... import identifier as identifier_t
|
|
12
|
+
from ... import post_base as post_base_t
|
|
13
|
+
from ... import response as response_t
|
|
14
|
+
|
|
15
|
+
__all__: list[str] = [
|
|
16
|
+
"Arguments",
|
|
17
|
+
"Data",
|
|
18
|
+
"ENDPOINT_METHOD",
|
|
19
|
+
"ENDPOINT_PATH",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
ENDPOINT_METHOD = "POST"
|
|
23
|
+
ENDPOINT_PATH = "api/external/inputs/external_set_input_subcategories"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
27
|
+
@dataclass(kw_only=True)
|
|
28
|
+
class Arguments:
|
|
29
|
+
input_key: identifier_t.IdentifierKey
|
|
30
|
+
subcategory_ids: list[int]
|
|
31
|
+
update_type: post_base_t.UpdateType
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
35
|
+
@dataclass(kw_only=True)
|
|
36
|
+
class Data(response_t.Response):
|
|
37
|
+
pass
|
|
38
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
2
|
+
# flake8: noqa: F821
|
|
3
|
+
# ruff: noqa: E402
|
|
4
|
+
# fmt: off
|
|
5
|
+
# isort: skip_file
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
import typing # noqa: F401
|
|
8
|
+
import datetime # noqa: F401
|
|
9
|
+
from decimal import Decimal # noqa: F401
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from ... import base as base_t
|
|
12
|
+
from ... import entity as entity_t
|
|
13
|
+
from ... import identifier as identifier_t
|
|
14
|
+
from ... import post_base as post_base_t
|
|
15
|
+
from ... import response as response_t
|
|
16
|
+
|
|
17
|
+
__all__: list[str] = [
|
|
18
|
+
"Arguments",
|
|
19
|
+
"Data",
|
|
20
|
+
"ENDPOINT_METHOD",
|
|
21
|
+
"ENDPOINT_PATH",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
ENDPOINT_METHOD = "POST"
|
|
25
|
+
ENDPOINT_PATH = "api/external/material_families/external_update_entity_material_families"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
29
|
+
@dataclass(kw_only=True)
|
|
30
|
+
class Arguments:
|
|
31
|
+
entity_key: identifier_t.IdentifierKey
|
|
32
|
+
entity_type: typing.Union[typing.Literal[entity_t.EntityType.RECIPE_METADATA], typing.Literal[entity_t.EntityType.INGREDIENT], typing.Literal[entity_t.EntityType.OUTPUT], typing.Literal[entity_t.EntityType.CONDITION_PARAMETER], typing.Literal[entity_t.EntityType.INGREDIENT_ATTRIBUTE]]
|
|
33
|
+
material_family_ids: list[base_t.ObjectId]
|
|
34
|
+
update_type: post_base_t.UpdateType
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
38
|
+
@dataclass(kw_only=True)
|
|
39
|
+
class Data(response_t.Response):
|
|
40
|
+
pass
|
|
41
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
@@ -30,6 +30,7 @@ class Arguments:
|
|
|
30
30
|
material_family_id: base_t.ObjectId
|
|
31
31
|
workflow_id: base_t.ObjectId
|
|
32
32
|
name: typing.Optional[str] = None
|
|
33
|
+
project_id: typing.Optional[base_t.ObjectId] = None
|
|
33
34
|
workflow_variant_id: typing.Optional[typing.Optional[base_t.ObjectId]] = None
|
|
34
35
|
recipe_metadata: typing.Optional[list[recipe_metadata_t.MetadataValue]] = None
|
|
35
36
|
identifiers: typing.Optional[recipe_identifiers_t.RecipeIdentifiers] = None
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
2
|
+
# flake8: noqa: F821
|
|
3
|
+
# ruff: noqa: E402
|
|
4
|
+
# fmt: off
|
|
5
|
+
# isort: skip_file
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
import typing # noqa: F401
|
|
8
|
+
import datetime # noqa: F401
|
|
9
|
+
from decimal import Decimal # noqa: F401
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from ... import identifier as identifier_t
|
|
12
|
+
|
|
13
|
+
__all__: list[str] = [
|
|
14
|
+
"Arguments",
|
|
15
|
+
"Data",
|
|
16
|
+
"ENDPOINT_METHOD",
|
|
17
|
+
"ENDPOINT_PATH",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
ENDPOINT_METHOD = "POST"
|
|
21
|
+
ENDPOINT_PATH = "api/external/recipes/unarchive"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
25
|
+
@dataclass(kw_only=True)
|
|
26
|
+
class Arguments:
|
|
27
|
+
recipes: list[identifier_t.IdentifierKey]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
31
|
+
@dataclass(kw_only=True)
|
|
32
|
+
class Data:
|
|
33
|
+
pass
|
|
34
|
+
# DO NOT MODIFY -- This file is generated by type_spec
|
|
@@ -38,6 +38,7 @@ class AsyncBatchProcessorBase(ABC):
|
|
|
38
38
|
material_family_id: base_t.ObjectId,
|
|
39
39
|
workflow_id: base_t.ObjectId,
|
|
40
40
|
name: typing.Optional[str] = None,
|
|
41
|
+
project_id: typing.Optional[base_t.ObjectId] = None,
|
|
41
42
|
workflow_variant_id: typing.Optional[typing.Optional[base_t.ObjectId]] = None,
|
|
42
43
|
recipe_metadata: typing.Optional[list[recipe_metadata_t.MetadataValue]] = None,
|
|
43
44
|
identifiers: typing.Optional[recipe_identifiers_t.RecipeIdentifiers] = None,
|
|
@@ -48,6 +49,7 @@ class AsyncBatchProcessorBase(ABC):
|
|
|
48
49
|
|
|
49
50
|
:param name: The name for the recipe
|
|
50
51
|
:param material_family_id: The material family for the recipe
|
|
52
|
+
:param project_id: The identifier of the project to create the recipe in
|
|
51
53
|
:param workflow_id: The identifier of the workflow to create the recipe with
|
|
52
54
|
:param workflow_variant_id: The identifier of the workflow variant to create the recipe with
|
|
53
55
|
:param recipe_metadata: Metadata values to populate the recipe with
|
|
@@ -58,6 +60,7 @@ class AsyncBatchProcessorBase(ABC):
|
|
|
58
60
|
args = create_recipe_t.Arguments(
|
|
59
61
|
name=name,
|
|
60
62
|
material_family_id=material_family_id,
|
|
63
|
+
project_id=project_id,
|
|
61
64
|
workflow_id=workflow_id,
|
|
62
65
|
workflow_variant_id=workflow_variant_id,
|
|
63
66
|
recipe_metadata=recipe_metadata,
|