UncountablePythonSDK 0.0.8__py3-none-any.whl → 0.0.92__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.

Files changed (312) hide show
  1. UncountablePythonSDK-0.0.92.dist-info/METADATA +61 -0
  2. UncountablePythonSDK-0.0.92.dist-info/RECORD +301 -0
  3. {UncountablePythonSDK-0.0.8.dist-info → UncountablePythonSDK-0.0.92.dist-info}/WHEEL +1 -1
  4. {UncountablePythonSDK-0.0.8.dist-info → UncountablePythonSDK-0.0.92.dist-info}/top_level.txt +1 -1
  5. docs/.gitignore +1 -0
  6. docs/conf.py +57 -0
  7. docs/index.md +13 -0
  8. docs/justfile +12 -0
  9. docs/quickstart.md +19 -0
  10. docs/requirements.txt +7 -0
  11. docs/static/favicons/android-chrome-192x192.png +0 -0
  12. docs/static/favicons/android-chrome-512x512.png +0 -0
  13. docs/static/favicons/apple-touch-icon.png +0 -0
  14. docs/static/favicons/browserconfig.xml +9 -0
  15. docs/static/favicons/favicon-16x16.png +0 -0
  16. docs/static/favicons/favicon-32x32.png +0 -0
  17. docs/static/favicons/manifest.json +18 -0
  18. docs/static/favicons/mstile-150x150.png +0 -0
  19. docs/static/favicons/safari-pinned-tab.svg +32 -0
  20. docs/static/logo_blue.png +0 -0
  21. examples/async_batch.py +35 -0
  22. examples/create_entity.py +22 -17
  23. examples/download_files.py +26 -0
  24. examples/edit_recipe_inputs.py +50 -0
  25. examples/integration-server/jobs/materials_auto/example_cron.py +18 -0
  26. examples/integration-server/jobs/materials_auto/example_wh.py +15 -0
  27. examples/integration-server/jobs/materials_auto/profile.yaml +43 -0
  28. examples/integration-server/pyproject.toml +224 -0
  29. examples/invoke_uploader.py +26 -0
  30. examples/set_recipe_metadata_file.py +40 -0
  31. examples/set_recipe_output_file_sdk.py +26 -0
  32. examples/upload_files.py +18 -0
  33. pkgs/argument_parser/__init__.py +5 -0
  34. pkgs/argument_parser/_is_enum.py +1 -6
  35. pkgs/argument_parser/argument_parser.py +232 -76
  36. pkgs/argument_parser/case_convert.py +4 -3
  37. pkgs/filesystem_utils/__init__.py +20 -0
  38. pkgs/filesystem_utils/_blob_session.py +137 -0
  39. pkgs/filesystem_utils/_gdrive_session.py +309 -0
  40. pkgs/filesystem_utils/_local_session.py +69 -0
  41. pkgs/filesystem_utils/_s3_session.py +117 -0
  42. pkgs/filesystem_utils/_sftp_session.py +147 -0
  43. pkgs/filesystem_utils/file_type_utils.py +91 -0
  44. pkgs/filesystem_utils/filesystem_session.py +39 -0
  45. pkgs/py.typed +0 -0
  46. pkgs/serialization/__init__.py +8 -1
  47. pkgs/serialization/annotation.py +64 -0
  48. pkgs/serialization/missing_sentry.py +1 -1
  49. pkgs/serialization/opaque_key.py +1 -1
  50. pkgs/serialization/serial_alias.py +47 -0
  51. pkgs/serialization/serial_class.py +65 -50
  52. pkgs/serialization/serial_generic.py +16 -0
  53. pkgs/serialization/serial_union.py +84 -0
  54. pkgs/serialization/yaml.py +57 -0
  55. pkgs/serialization_util/__init__.py +7 -7
  56. pkgs/serialization_util/_get_type_for_serialization.py +1 -3
  57. pkgs/serialization_util/convert_to_snakecase.py +27 -0
  58. pkgs/serialization_util/dataclasses.py +14 -0
  59. pkgs/serialization_util/serialization_helpers.py +116 -74
  60. pkgs/strenum_compat/strenum_compat.py +1 -9
  61. pkgs/type_spec/actions_registry/__init__.py +0 -0
  62. pkgs/type_spec/actions_registry/__main__.py +126 -0
  63. pkgs/type_spec/actions_registry/emit_typescript.py +182 -0
  64. pkgs/type_spec/builder.py +475 -89
  65. pkgs/type_spec/config.py +24 -19
  66. pkgs/type_spec/emit_io_ts.py +5 -2
  67. pkgs/type_spec/emit_open_api.py +266 -32
  68. pkgs/type_spec/emit_open_api_util.py +32 -13
  69. pkgs/type_spec/emit_python.py +599 -151
  70. pkgs/type_spec/emit_typescript.py +74 -273
  71. pkgs/type_spec/emit_typescript_util.py +239 -5
  72. pkgs/type_spec/load_types.py +55 -10
  73. pkgs/type_spec/open_api_util.py +30 -41
  74. pkgs/type_spec/parts/base.py.prepart +4 -3
  75. pkgs/type_spec/type_info/emit_type_info.py +178 -16
  76. pkgs/type_spec/util.py +11 -11
  77. pkgs/type_spec/value_spec/__main__.py +3 -3
  78. pkgs/type_spec/value_spec/convert_type.py +8 -1
  79. pkgs/type_spec/value_spec/emit_python.py +13 -4
  80. uncountable/__init__.py +1 -2
  81. uncountable/core/__init__.py +12 -2
  82. uncountable/core/async_batch.py +37 -0
  83. uncountable/core/client.py +293 -43
  84. uncountable/core/environment.py +41 -0
  85. uncountable/core/file_upload.py +135 -0
  86. uncountable/core/types.py +17 -0
  87. uncountable/integration/__init__.py +0 -0
  88. uncountable/integration/cli.py +49 -0
  89. uncountable/integration/construct_client.py +51 -0
  90. uncountable/integration/cron.py +29 -0
  91. uncountable/integration/db/__init__.py +0 -0
  92. uncountable/integration/db/connect.py +18 -0
  93. uncountable/integration/db/session.py +25 -0
  94. uncountable/integration/entrypoint.py +13 -0
  95. uncountable/integration/executors/__init__.py +0 -0
  96. uncountable/integration/executors/executors.py +148 -0
  97. uncountable/integration/executors/generic_upload_executor.py +284 -0
  98. uncountable/integration/executors/script_executor.py +25 -0
  99. uncountable/integration/job.py +87 -0
  100. uncountable/integration/queue_runner/__init__.py +0 -0
  101. uncountable/integration/queue_runner/command_server/__init__.py +24 -0
  102. uncountable/integration/queue_runner/command_server/command_client.py +68 -0
  103. uncountable/integration/queue_runner/command_server/command_server.py +64 -0
  104. uncountable/integration/queue_runner/command_server/protocol/__init__.py +0 -0
  105. uncountable/integration/queue_runner/command_server/protocol/command_server.proto +22 -0
  106. uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.py +40 -0
  107. uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.pyi +38 -0
  108. uncountable/integration/queue_runner/command_server/protocol/command_server_pb2_grpc.py +129 -0
  109. uncountable/integration/queue_runner/command_server/types.py +52 -0
  110. uncountable/integration/queue_runner/datastore/__init__.py +3 -0
  111. uncountable/integration/queue_runner/datastore/datastore_sqlite.py +93 -0
  112. uncountable/integration/queue_runner/datastore/interface.py +19 -0
  113. uncountable/integration/queue_runner/datastore/model.py +17 -0
  114. uncountable/integration/queue_runner/job_scheduler.py +163 -0
  115. uncountable/integration/queue_runner/queue_runner.py +26 -0
  116. uncountable/integration/queue_runner/types.py +7 -0
  117. uncountable/integration/queue_runner/worker.py +119 -0
  118. uncountable/integration/scan_profiles.py +67 -0
  119. uncountable/integration/scheduler.py +150 -0
  120. uncountable/integration/secret_retrieval/__init__.py +3 -0
  121. uncountable/integration/secret_retrieval/retrieve_secret.py +93 -0
  122. uncountable/integration/server.py +117 -0
  123. uncountable/integration/telemetry.py +209 -0
  124. uncountable/integration/webhook_server/entrypoint.py +170 -0
  125. uncountable/types/__init__.py +136 -20
  126. uncountable/types/api/batch/execute_batch.py +15 -7
  127. uncountable/types/api/batch/execute_batch_load_async.py +42 -0
  128. uncountable/types/api/chemical/__init__.py +1 -0
  129. uncountable/types/api/chemical/convert_chemical_formats.py +63 -0
  130. uncountable/types/api/entity/create_entities.py +23 -11
  131. uncountable/types/api/entity/create_entity.py +21 -12
  132. uncountable/types/api/entity/get_entities_data.py +18 -8
  133. uncountable/types/api/entity/grant_entity_permissions.py +48 -0
  134. uncountable/types/api/entity/list_entities.py +27 -12
  135. uncountable/types/api/entity/lock_entity.py +45 -0
  136. uncountable/types/api/entity/resolve_entity_ids.py +17 -7
  137. uncountable/types/api/entity/set_entity_field_values.py +44 -0
  138. uncountable/types/api/entity/set_values.py +14 -7
  139. uncountable/types/api/entity/transition_entity_phase.py +80 -0
  140. uncountable/types/api/entity/unlock_entity.py +44 -0
  141. uncountable/types/api/equipment/__init__.py +1 -0
  142. uncountable/types/api/equipment/associate_equipment_input.py +44 -0
  143. uncountable/types/api/field_options/__init__.py +1 -0
  144. uncountable/types/api/field_options/upsert_field_options.py +55 -0
  145. uncountable/types/api/files/__init__.py +1 -0
  146. uncountable/types/api/files/download_file.py +77 -0
  147. uncountable/types/api/id_source/__init__.py +1 -0
  148. uncountable/types/api/id_source/list_id_source.py +56 -0
  149. uncountable/types/api/id_source/match_id_source.py +54 -0
  150. uncountable/types/api/input_groups/get_input_group_names.py +16 -6
  151. uncountable/types/api/inputs/create_inputs.py +24 -11
  152. uncountable/types/api/inputs/get_input_data.py +32 -13
  153. uncountable/types/api/inputs/get_input_names.py +18 -8
  154. uncountable/types/api/inputs/get_inputs_data.py +29 -10
  155. uncountable/types/api/inputs/set_input_attribute_values.py +16 -9
  156. uncountable/types/api/inputs/set_input_category.py +44 -0
  157. uncountable/types/api/inputs/set_input_subcategories.py +45 -0
  158. uncountable/types/api/inputs/set_intermediate_type.py +50 -0
  159. uncountable/types/api/material_families/__init__.py +1 -0
  160. uncountable/types/api/material_families/update_entity_material_families.py +48 -0
  161. uncountable/types/api/outputs/get_output_data.py +32 -16
  162. uncountable/types/api/outputs/get_output_names.py +18 -8
  163. uncountable/types/api/outputs/resolve_output_conditions.py +23 -10
  164. uncountable/types/api/permissions/__init__.py +1 -0
  165. uncountable/types/api/permissions/set_core_permissions.py +105 -0
  166. uncountable/types/api/project/get_projects.py +17 -7
  167. uncountable/types/api/project/get_projects_data.py +21 -11
  168. uncountable/types/api/recipe_links/__init__.py +1 -0
  169. uncountable/types/api/recipe_links/create_recipe_link.py +46 -0
  170. uncountable/types/api/recipe_links/remove_recipe_link.py +45 -0
  171. uncountable/types/api/recipe_metadata/get_recipe_metadata_data.py +18 -8
  172. uncountable/types/api/recipes/add_recipe_to_project.py +42 -0
  173. uncountable/types/api/recipes/archive_recipes.py +42 -0
  174. uncountable/types/api/recipes/associate_recipe_as_input.py +44 -0
  175. uncountable/types/api/recipes/associate_recipe_as_lot.py +43 -0
  176. uncountable/types/api/recipes/clear_recipe_outputs.py +42 -0
  177. uncountable/types/api/recipes/create_recipe.py +51 -0
  178. uncountable/types/api/recipes/create_recipes.py +25 -12
  179. uncountable/types/api/recipes/disassociate_recipe_as_input.py +42 -0
  180. uncountable/types/api/recipes/edit_recipe_inputs.py +283 -0
  181. uncountable/types/api/recipes/get_column_calculation_values.py +58 -0
  182. uncountable/types/api/recipes/get_curve.py +15 -7
  183. uncountable/types/api/recipes/get_recipe_calculations.py +17 -10
  184. uncountable/types/api/recipes/get_recipe_links.py +13 -6
  185. uncountable/types/api/recipes/get_recipe_names.py +16 -6
  186. uncountable/types/api/recipes/get_recipe_output_metadata.py +14 -7
  187. uncountable/types/api/recipes/get_recipes_data.py +63 -38
  188. uncountable/types/api/recipes/lock_recipes.py +63 -0
  189. uncountable/types/api/recipes/remove_recipe_from_project.py +42 -0
  190. uncountable/types/api/recipes/set_recipe_inputs.py +19 -10
  191. uncountable/types/api/recipes/set_recipe_metadata.py +43 -0
  192. uncountable/types/api/recipes/set_recipe_output_annotations.py +115 -0
  193. uncountable/types/api/recipes/set_recipe_output_file.py +56 -0
  194. uncountable/types/api/recipes/set_recipe_outputs.py +26 -12
  195. uncountable/types/api/recipes/set_recipe_tags.py +109 -0
  196. uncountable/types/api/recipes/unarchive_recipes.py +41 -0
  197. uncountable/types/api/recipes/unlock_recipes.py +50 -0
  198. uncountable/types/api/triggers/__init__.py +1 -0
  199. uncountable/types/api/triggers/run_trigger.py +43 -0
  200. uncountable/types/api/uploader/__init__.py +1 -0
  201. uncountable/types/api/uploader/invoke_uploader.py +47 -0
  202. uncountable/types/async_batch.py +13 -0
  203. uncountable/types/async_batch_processor.py +384 -0
  204. uncountable/types/async_batch_t.py +97 -0
  205. uncountable/types/async_jobs.py +9 -0
  206. uncountable/types/async_jobs_t.py +53 -0
  207. uncountable/types/auth_retrieval.py +12 -0
  208. uncountable/types/auth_retrieval_t.py +75 -0
  209. uncountable/types/base.py +5 -78
  210. uncountable/types/base_t.py +85 -0
  211. uncountable/types/calculations.py +3 -18
  212. uncountable/types/calculations_t.py +27 -0
  213. uncountable/types/chemical_structure.py +8 -0
  214. uncountable/types/chemical_structure_t.py +28 -0
  215. uncountable/types/client_base.py +1093 -54
  216. uncountable/types/client_config.py +8 -0
  217. uncountable/types/client_config_t.py +26 -0
  218. uncountable/types/curves.py +5 -42
  219. uncountable/types/curves_t.py +51 -0
  220. uncountable/types/entity.py +8 -269
  221. uncountable/types/entity_t.py +393 -0
  222. uncountable/types/experiment_groups.py +3 -18
  223. uncountable/types/experiment_groups_t.py +27 -0
  224. uncountable/types/field_values.py +17 -60
  225. uncountable/types/field_values_t.py +204 -0
  226. uncountable/types/fields.py +3 -19
  227. uncountable/types/fields_t.py +28 -0
  228. uncountable/types/generic_upload.py +15 -0
  229. uncountable/types/generic_upload_t.py +119 -0
  230. uncountable/types/id_source.py +12 -0
  231. uncountable/types/id_source_t.py +68 -0
  232. uncountable/types/identifier.py +11 -0
  233. uncountable/types/identifier_t.py +63 -0
  234. uncountable/types/input_attributes.py +3 -24
  235. uncountable/types/input_attributes_t.py +30 -0
  236. uncountable/types/inputs.py +6 -56
  237. uncountable/types/inputs_t.py +83 -0
  238. uncountable/types/integration_server.py +9 -0
  239. uncountable/types/integration_server_t.py +42 -0
  240. uncountable/types/job_definition.py +27 -0
  241. uncountable/types/job_definition_t.py +260 -0
  242. uncountable/types/outputs.py +3 -21
  243. uncountable/types/outputs_t.py +30 -0
  244. uncountable/types/overrides.py +10 -0
  245. uncountable/types/overrides_t.py +49 -0
  246. uncountable/types/permissions.py +8 -0
  247. uncountable/types/permissions_t.py +46 -0
  248. uncountable/types/phases.py +3 -18
  249. uncountable/types/phases_t.py +27 -0
  250. uncountable/types/post_base.py +8 -0
  251. uncountable/types/post_base_t.py +30 -0
  252. uncountable/types/queued_job.py +16 -0
  253. uncountable/types/queued_job_t.py +123 -0
  254. uncountable/types/recipe_identifiers.py +12 -0
  255. uncountable/types/recipe_identifiers_t.py +76 -0
  256. uncountable/types/recipe_inputs.py +9 -0
  257. uncountable/types/recipe_inputs_t.py +30 -0
  258. uncountable/types/recipe_links.py +4 -45
  259. uncountable/types/recipe_links_t.py +54 -0
  260. uncountable/types/recipe_metadata.py +5 -45
  261. uncountable/types/recipe_metadata_t.py +58 -0
  262. uncountable/types/recipe_output_metadata.py +3 -19
  263. uncountable/types/recipe_output_metadata_t.py +28 -0
  264. uncountable/types/recipe_tags.py +3 -18
  265. uncountable/types/recipe_tags_t.py +27 -0
  266. uncountable/types/recipe_workflow_steps.py +14 -0
  267. uncountable/types/recipe_workflow_steps_t.py +95 -0
  268. uncountable/types/recipes.py +8 -0
  269. uncountable/types/recipes_t.py +25 -0
  270. uncountable/types/response.py +3 -20
  271. uncountable/types/response_t.py +26 -0
  272. uncountable/types/secret_retrieval.py +12 -0
  273. uncountable/types/secret_retrieval_t.py +75 -0
  274. uncountable/types/units.py +3 -18
  275. uncountable/types/units_t.py +27 -0
  276. uncountable/types/users.py +3 -19
  277. uncountable/types/users_t.py +28 -0
  278. uncountable/types/webhook_job.py +9 -0
  279. uncountable/types/webhook_job_t.py +37 -0
  280. uncountable/types/workflows.py +4 -27
  281. uncountable/types/workflows_t.py +39 -0
  282. UncountablePythonSDK-0.0.8.dist-info/METADATA +0 -27
  283. UncountablePythonSDK-0.0.8.dist-info/RECORD +0 -134
  284. examples/recipe-import/importer.py +0 -39
  285. type_spec/external/api/batch/execute_batch.yaml +0 -56
  286. type_spec/external/api/entity/create_entities.yaml +0 -33
  287. type_spec/external/api/entity/create_entity.yaml +0 -39
  288. type_spec/external/api/entity/get_entities_data.yaml +0 -29
  289. type_spec/external/api/entity/list_entities.yaml +0 -52
  290. type_spec/external/api/entity/resolve_entity_ids.yaml +0 -29
  291. type_spec/external/api/entity/set_values.yaml +0 -18
  292. type_spec/external/api/input_groups/get_input_group_names.yaml +0 -29
  293. type_spec/external/api/inputs/create_inputs.yaml +0 -48
  294. type_spec/external/api/inputs/get_input_data.yaml +0 -95
  295. type_spec/external/api/inputs/get_input_names.yaml +0 -38
  296. type_spec/external/api/inputs/get_inputs_data.yaml +0 -82
  297. type_spec/external/api/inputs/set_input_attribute_values.yaml +0 -33
  298. type_spec/external/api/outputs/get_output_data.yaml +0 -92
  299. type_spec/external/api/outputs/get_output_names.yaml +0 -35
  300. type_spec/external/api/outputs/resolve_output_conditions.yaml +0 -50
  301. type_spec/external/api/project/get_projects.yaml +0 -42
  302. type_spec/external/api/project/get_projects_data.yaml +0 -50
  303. type_spec/external/api/recipe_metadata/get_recipe_metadata_data.yaml +0 -41
  304. type_spec/external/api/recipes/create_recipes.yaml +0 -47
  305. type_spec/external/api/recipes/get_curve.yaml +0 -18
  306. type_spec/external/api/recipes/get_recipe_calculations.yaml +0 -39
  307. type_spec/external/api/recipes/get_recipe_links.yaml +0 -26
  308. type_spec/external/api/recipes/get_recipe_names.yaml +0 -29
  309. type_spec/external/api/recipes/get_recipe_output_metadata.yaml +0 -36
  310. type_spec/external/api/recipes/get_recipes_data.yaml +0 -238
  311. type_spec/external/api/recipes/set_recipe_inputs.yaml +0 -36
  312. type_spec/external/api/recipes/set_recipe_outputs.yaml +0 -52
@@ -1,6 +1,6 @@
1
1
  # DO NOT MODIFY -- This file is generated by type_spec
2
2
  # flake8: noqa: F821
3
- # ruff: noqa: E402
3
+ # ruff: noqa: E402 Q003
4
4
  # fmt: off
5
5
  # isort: skip_file
6
6
  # ruff: noqa: PLR0904
@@ -9,14 +9,29 @@ import typing # noqa: F401
9
9
  import datetime # noqa: F401
10
10
  from decimal import Decimal # noqa: F401
11
11
  from pkgs.serialization import OpaqueKey
12
- from . import base as base_t
12
+ import uncountable.types.api.recipes.add_recipe_to_project as add_recipe_to_project_t
13
+ import uncountable.types.api.recipes.archive_recipes as archive_recipes_t
14
+ import uncountable.types.api.equipment.associate_equipment_input as associate_equipment_input_t
15
+ import uncountable.types.api.recipes.associate_recipe_as_input as associate_recipe_as_input_t
16
+ import uncountable.types.api.recipes.associate_recipe_as_lot as associate_recipe_as_lot_t
17
+ from uncountable.types import async_batch_t
18
+ from uncountable.types import base_t
19
+ import uncountable.types.api.recipes.clear_recipe_outputs as clear_recipe_outputs_t
20
+ import uncountable.types.api.chemical.convert_chemical_formats as convert_chemical_formats_t
13
21
  import uncountable.types.api.entity.create_entities as create_entities_t
14
22
  import uncountable.types.api.entity.create_entity as create_entity_t
15
23
  import uncountable.types.api.inputs.create_inputs as create_inputs_t
24
+ import uncountable.types.api.recipes.create_recipe as create_recipe_t
25
+ import uncountable.types.api.recipe_links.create_recipe_link as create_recipe_link_t
16
26
  import uncountable.types.api.recipes.create_recipes as create_recipes_t
17
- from . import entity as entity_t
27
+ import uncountable.types.api.recipes.disassociate_recipe_as_input as disassociate_recipe_as_input_t
28
+ import uncountable.types.api.recipes.edit_recipe_inputs as edit_recipe_inputs_t
29
+ from uncountable.types import entity_t
18
30
  import uncountable.types.api.batch.execute_batch as execute_batch_t
19
- from . import field_values as field_values_t
31
+ import uncountable.types.api.batch.execute_batch_load_async as execute_batch_load_async_t
32
+ from uncountable.types import field_values_t
33
+ from uncountable.types import generic_upload_t
34
+ import uncountable.types.api.recipes.get_column_calculation_values as get_column_calculation_values_t
20
35
  import uncountable.types.api.recipes.get_curve as get_curve_t
21
36
  import uncountable.types.api.entity.get_entities_data as get_entities_data_t
22
37
  import uncountable.types.api.inputs.get_input_data as get_input_data_t
@@ -33,21 +48,52 @@ import uncountable.types.api.recipe_metadata.get_recipe_metadata_data as get_rec
33
48
  import uncountable.types.api.recipes.get_recipe_names as get_recipe_names_t
34
49
  import uncountable.types.api.recipes.get_recipe_output_metadata as get_recipe_output_metadata_t
35
50
  import uncountable.types.api.recipes.get_recipes_data as get_recipes_data_t
51
+ import uncountable.types.api.entity.grant_entity_permissions as grant_entity_permissions_t
52
+ from uncountable.types import id_source_t
53
+ from uncountable.types import identifier_t
54
+ import uncountable.types.api.uploader.invoke_uploader as invoke_uploader_t
36
55
  import uncountable.types.api.entity.list_entities as list_entities_t
37
- from . import recipe_links as recipe_links_t
56
+ import uncountable.types.api.id_source.list_id_source as list_id_source_t
57
+ import uncountable.types.api.entity.lock_entity as lock_entity_t
58
+ import uncountable.types.api.recipes.lock_recipes as lock_recipes_t
59
+ import uncountable.types.api.id_source.match_id_source as match_id_source_t
60
+ from uncountable.types import permissions_t
61
+ from uncountable.types import post_base_t
62
+ from uncountable.types import recipe_identifiers_t
63
+ from uncountable.types import recipe_links_t
64
+ from uncountable.types import recipe_metadata_t
65
+ from uncountable.types import recipe_workflow_steps_t
66
+ import uncountable.types.api.recipes.remove_recipe_from_project as remove_recipe_from_project_t
67
+ import uncountable.types.api.recipe_links.remove_recipe_link as remove_recipe_link_t
38
68
  import uncountable.types.api.entity.resolve_entity_ids as resolve_entity_ids_t
39
69
  import uncountable.types.api.outputs.resolve_output_conditions as resolve_output_conditions_t
70
+ import uncountable.types.api.triggers.run_trigger as run_trigger_t
71
+ import uncountable.types.api.permissions.set_core_permissions as set_core_permissions_t
72
+ import uncountable.types.api.entity.set_entity_field_values as set_entity_field_values_t
40
73
  import uncountable.types.api.inputs.set_input_attribute_values as set_input_attribute_values_t
74
+ import uncountable.types.api.inputs.set_input_category as set_input_category_t
75
+ import uncountable.types.api.inputs.set_input_subcategories as set_input_subcategories_t
76
+ import uncountable.types.api.inputs.set_intermediate_type as set_intermediate_type_t
41
77
  import uncountable.types.api.recipes.set_recipe_inputs as set_recipe_inputs_t
78
+ import uncountable.types.api.recipes.set_recipe_metadata as set_recipe_metadata_t
79
+ import uncountable.types.api.recipes.set_recipe_output_annotations as set_recipe_output_annotations_t
80
+ import uncountable.types.api.recipes.set_recipe_output_file as set_recipe_output_file_t
42
81
  import uncountable.types.api.recipes.set_recipe_outputs as set_recipe_outputs_t
82
+ import uncountable.types.api.recipes.set_recipe_tags as set_recipe_tags_t
43
83
  import uncountable.types.api.entity.set_values as set_values_t
84
+ import uncountable.types.api.entity.transition_entity_phase as transition_entity_phase_t
85
+ import uncountable.types.api.recipes.unarchive_recipes as unarchive_recipes_t
86
+ import uncountable.types.api.entity.unlock_entity as unlock_entity_t
87
+ import uncountable.types.api.recipes.unlock_recipes as unlock_recipes_t
88
+ import uncountable.types.api.material_families.update_entity_material_families as update_entity_material_families_t
89
+ import uncountable.types.api.field_options.upsert_field_options as upsert_field_options_t
44
90
  from abc import ABC, abstractmethod
45
- from dataclasses import dataclass
91
+ import dataclasses
46
92
 
47
93
  DT = typing.TypeVar("DT")
48
94
 
49
95
 
50
- @dataclass(kw_only=True)
96
+ @dataclasses.dataclass(kw_only=True)
51
97
  class APIRequest:
52
98
  method: str
53
99
  endpoint: str
@@ -60,16 +106,174 @@ class ClientMethods(ABC):
60
106
  def do_request(self, *, api_request: APIRequest, return_type: type[DT]) -> DT:
61
107
  ...
62
108
 
109
+ def add_recipe_to_project(
110
+ self,
111
+ *,
112
+ recipe_key: identifier_t.IdentifierKey,
113
+ project_key: identifier_t.IdentifierKey,
114
+ ) -> add_recipe_to_project_t.Data:
115
+ """Adds a recipe to a project
116
+
117
+ :param recipe_key: The identifier key of the recipe to add to the project
118
+ :param project_key: The identifier key of the project to add the recipe to
119
+ """
120
+ args = add_recipe_to_project_t.Arguments(
121
+ recipe_key=recipe_key,
122
+ project_key=project_key,
123
+ )
124
+ api_request = APIRequest(
125
+ method=add_recipe_to_project_t.ENDPOINT_METHOD,
126
+ endpoint=add_recipe_to_project_t.ENDPOINT_PATH,
127
+ args=args,
128
+ )
129
+ return self.do_request(api_request=api_request, return_type=add_recipe_to_project_t.Data)
130
+
131
+ def archive_recipes(
132
+ self,
133
+ *,
134
+ recipes: list[identifier_t.IdentifierKey],
135
+ reason: str | None = None,
136
+ ) -> archive_recipes_t.Data:
137
+ """Archive the provided recipes and their children
138
+
139
+ :param recipes: Identifier for the recipe
140
+ :param reason: This reason will be written to the audit log archive entry
141
+ """
142
+ args = archive_recipes_t.Arguments(
143
+ recipes=recipes,
144
+ reason=reason,
145
+ )
146
+ api_request = APIRequest(
147
+ method=archive_recipes_t.ENDPOINT_METHOD,
148
+ endpoint=archive_recipes_t.ENDPOINT_PATH,
149
+ args=args,
150
+ )
151
+ return self.do_request(api_request=api_request, return_type=archive_recipes_t.Data)
152
+
153
+ def associate_equipment_input(
154
+ self,
155
+ *,
156
+ equipment_key: identifier_t.IdentifierKey,
157
+ material_family_ids: list[base_t.ObjectId],
158
+ ) -> associate_equipment_input_t.Data:
159
+ """Create or return the input association for equipment
160
+
161
+ :param equipment_key: Identifier of the equipment to associate
162
+ :param material_family_ids: The list of material families to add the input to. This must be non-empty
163
+ """
164
+ args = associate_equipment_input_t.Arguments(
165
+ equipment_key=equipment_key,
166
+ material_family_ids=material_family_ids,
167
+ )
168
+ api_request = APIRequest(
169
+ method=associate_equipment_input_t.ENDPOINT_METHOD,
170
+ endpoint=associate_equipment_input_t.ENDPOINT_PATH,
171
+ args=args,
172
+ )
173
+ return self.do_request(api_request=api_request, return_type=associate_equipment_input_t.Data)
174
+
175
+ def associate_recipe_as_input(
176
+ self,
177
+ *,
178
+ recipe_key: identifier_t.IdentifierKey,
179
+ input_key: identifier_t.IdentifierKey | None = None,
180
+ show_in_listings: bool | None = None,
181
+ ) -> associate_recipe_as_input_t.Data:
182
+ """Create or return the input association for a recipe
183
+
184
+ :param recipe_key: Identifier for the recipe
185
+ :param input_key: Identifier for an input to use for the association. Optionally supplied. If not supplied, one is created
186
+ :param show_in_listings: After associating the input should it be present in listings
187
+ """
188
+ args = associate_recipe_as_input_t.Arguments(
189
+ recipe_key=recipe_key,
190
+ input_key=input_key,
191
+ show_in_listings=show_in_listings,
192
+ )
193
+ api_request = APIRequest(
194
+ method=associate_recipe_as_input_t.ENDPOINT_METHOD,
195
+ endpoint=associate_recipe_as_input_t.ENDPOINT_PATH,
196
+ args=args,
197
+ )
198
+ return self.do_request(api_request=api_request, return_type=associate_recipe_as_input_t.Data)
199
+
200
+ def associate_recipe_as_lot(
201
+ self,
202
+ *,
203
+ recipe_key: identifier_t.IdentifierKey,
204
+ ingredient_key: identifier_t.IdentifierKey,
205
+ ) -> associate_recipe_as_lot_t.Data:
206
+ """Create a new lot association for the provided recipe with the provided ingredient
207
+
208
+ :param recipe_key: Identifier for the recipe
209
+ :param ingredient_key: Identifier for the ingredient
210
+ """
211
+ args = associate_recipe_as_lot_t.Arguments(
212
+ recipe_key=recipe_key,
213
+ ingredient_key=ingredient_key,
214
+ )
215
+ api_request = APIRequest(
216
+ method=associate_recipe_as_lot_t.ENDPOINT_METHOD,
217
+ endpoint=associate_recipe_as_lot_t.ENDPOINT_PATH,
218
+ args=args,
219
+ )
220
+ return self.do_request(api_request=api_request, return_type=associate_recipe_as_lot_t.Data)
221
+
222
+ def clear_recipe_outputs(
223
+ self,
224
+ *,
225
+ recipe_key: identifier_t.IdentifierKey,
226
+ ) -> clear_recipe_outputs_t.Data:
227
+ """Clears all output values & output metadata for a given recipe
228
+
229
+ :param recipe_key: The identifier of the recipe
230
+ """
231
+ args = clear_recipe_outputs_t.Arguments(
232
+ recipe_key=recipe_key,
233
+ )
234
+ api_request = APIRequest(
235
+ method=clear_recipe_outputs_t.ENDPOINT_METHOD,
236
+ endpoint=clear_recipe_outputs_t.ENDPOINT_PATH,
237
+ args=args,
238
+ )
239
+ return self.do_request(api_request=api_request, return_type=clear_recipe_outputs_t.Data)
240
+
241
+ def convert_chemical_formats(
242
+ self,
243
+ *,
244
+ source_chemical_structures: list[convert_chemical_formats_t.ChemicalStructureFile],
245
+ ) -> convert_chemical_formats_t.Data:
246
+ """Converts chemical formats, into the format used by Uncountable and usable in other APIs for eg. set_input_attribute_values
247
+
248
+ """
249
+ args = convert_chemical_formats_t.Arguments(
250
+ source_chemical_structures=source_chemical_structures,
251
+ )
252
+ api_request = APIRequest(
253
+ method=convert_chemical_formats_t.ENDPOINT_METHOD,
254
+ endpoint=convert_chemical_formats_t.ENDPOINT_PATH,
255
+ args=args,
256
+ )
257
+ return self.do_request(api_request=api_request, return_type=convert_chemical_formats_t.Data)
63
258
 
64
259
  def create_entities(
65
260
  self,
66
261
  *,
67
- definition_id: base_t.ObjectId,
68
- entity_type: typing.Union[typing.Literal[entity_t.EntityType.LAB_REQUEST], typing.Literal[entity_t.EntityType.APPROVAL], typing.Literal[entity_t.EntityType.CUSTOM_ENTITY], typing.Literal[entity_t.EntityType.TASK], typing.Literal[entity_t.EntityType.PROJECT]],
262
+ entity_type: entity_t.LimitedEntityType,
69
263
  entities_to_create: list[create_entities_t.EntityToCreate],
264
+ definition_id: base_t.ObjectId | None = None,
265
+ definition_key: identifier_t.IdentifierKey | None = None,
70
266
  ) -> create_entities_t.Data:
267
+ """Creates new Uncountable entities
268
+
269
+ :param definition_id: Definition id for the entities to create
270
+ :param definition_key: Key for the definition of the entities to create
271
+ :param entity_type: The type of the entities to create
272
+ :param entities_to_create: A list of the entities to create
273
+ """
71
274
  args = create_entities_t.Arguments(
72
275
  definition_id=definition_id,
276
+ definition_key=definition_key,
73
277
  entity_type=entity_type,
74
278
  entities_to_create=entities_to_create,
75
279
  )
@@ -80,16 +284,23 @@ class ClientMethods(ABC):
80
284
  )
81
285
  return self.do_request(api_request=api_request, return_type=create_entities_t.Data)
82
286
 
83
-
84
287
  def create_entity(
85
288
  self,
86
289
  *,
87
- definition_id: base_t.ObjectId,
88
- entity_type: typing.Union[typing.Literal[entity_t.EntityType.LAB_REQUEST], typing.Literal[entity_t.EntityType.APPROVAL], typing.Literal[entity_t.EntityType.CUSTOM_ENTITY], typing.Literal[entity_t.EntityType.TASK], typing.Literal[entity_t.EntityType.PROJECT]],
89
- field_values: typing.Optional[typing.Optional[list[field_values_t.FieldRefNameValue]]] = None,
290
+ entity_type: entity_t.LimitedEntityType,
291
+ definition_id: base_t.ObjectId | None = None,
292
+ definition_key: identifier_t.IdentifierKey | None = None,
293
+ field_values: typing.Optional[list[field_values_t.FieldRefNameValue]] | None = None,
90
294
  ) -> create_entity_t.Data:
295
+ """Creates a new Uncountable entity
296
+
297
+ :param definition_id: Definition id of the entity to create
298
+ :param definition_key: Key for the definition of the entity to create
299
+ :param entity_type: The type of the entities requested
300
+ """
91
301
  args = create_entity_t.Arguments(
92
302
  definition_id=definition_id,
303
+ definition_key=definition_key,
93
304
  entity_type=entity_type,
94
305
  field_values=field_values,
95
306
  )
@@ -100,12 +311,15 @@ class ClientMethods(ABC):
100
311
  )
101
312
  return self.do_request(api_request=api_request, return_type=create_entity_t.Data)
102
313
 
103
-
104
314
  def external_create_inputs(
105
315
  self,
106
316
  *,
107
317
  inputs_to_create: list[create_inputs_t.InputToCreate],
108
318
  ) -> create_inputs_t.Data:
319
+ """Creates new inputs
320
+
321
+ :param inputs_to_create: A list of inputs to create
322
+ """
109
323
  args = create_inputs_t.Arguments(
110
324
  inputs_to_create=inputs_to_create,
111
325
  )
@@ -116,14 +330,86 @@ class ClientMethods(ABC):
116
330
  )
117
331
  return self.do_request(api_request=api_request, return_type=create_inputs_t.Data)
118
332
 
333
+ def create_recipe(
334
+ self,
335
+ *,
336
+ material_family_id: base_t.ObjectId,
337
+ workflow_id: base_t.ObjectId,
338
+ name: str | None = None,
339
+ project_id: base_t.ObjectId | None = None,
340
+ workflow_variant_id: typing.Optional[base_t.ObjectId] | None = None,
341
+ recipe_metadata: list[recipe_metadata_t.MetadataValue] | None = None,
342
+ identifiers: recipe_identifiers_t.RecipeIdentifiers | None = None,
343
+ definition_key: identifier_t.IdentifierKey | None = None,
344
+ ) -> create_recipe_t.Data:
345
+ """Returns the id of the recipe being created.
346
+
347
+ :param name: The name for the recipe
348
+ :param material_family_id: The material family for the recipe
349
+ :param project_id: The identifier of the project to create the recipe in
350
+ :param workflow_id: The identifier of the workflow to create the recipe with
351
+ :param workflow_variant_id: The identifier of the workflow variant to create the recipe with
352
+ :param recipe_metadata: Metadata values to populate the recipe with
353
+ :param identifiers: A recipe won't be created if it matches the identifier. An identifier must be unique in the schema
354
+ :param definition_key: The entity definition identifier, default is used if not supplied
355
+ """
356
+ args = create_recipe_t.Arguments(
357
+ name=name,
358
+ material_family_id=material_family_id,
359
+ project_id=project_id,
360
+ workflow_id=workflow_id,
361
+ workflow_variant_id=workflow_variant_id,
362
+ recipe_metadata=recipe_metadata,
363
+ identifiers=identifiers,
364
+ definition_key=definition_key,
365
+ )
366
+ api_request = APIRequest(
367
+ method=create_recipe_t.ENDPOINT_METHOD,
368
+ endpoint=create_recipe_t.ENDPOINT_PATH,
369
+ args=args,
370
+ )
371
+ return self.do_request(api_request=api_request, return_type=create_recipe_t.Data)
372
+
373
+ def create_recipe_link(
374
+ self,
375
+ *,
376
+ recipe_from_key: identifier_t.IdentifierKey,
377
+ recipe_to_key: identifier_t.IdentifierKey,
378
+ link_type: typing.Union[typing.Literal[recipe_links_t.RecipeLinkType.CHILD], typing.Literal[recipe_links_t.RecipeLinkType.CONTROL], typing.Literal[recipe_links_t.RecipeLinkType.USER_LINK]],
379
+ name: str,
380
+ ) -> create_recipe_link_t.Data:
381
+ """Create a link between two recipes. Skip if the link already exists
382
+
383
+ :param recipe_from_key: Identifier for the recipe the link comes from
384
+ :param recipe_to_key: Identifier for the recipe the link goes to
385
+ :param link_type: The type of link being created
386
+ :param name: The name used for the link
387
+ """
388
+ args = create_recipe_link_t.Arguments(
389
+ recipe_from_key=recipe_from_key,
390
+ recipe_to_key=recipe_to_key,
391
+ link_type=link_type,
392
+ name=name,
393
+ )
394
+ api_request = APIRequest(
395
+ method=create_recipe_link_t.ENDPOINT_METHOD,
396
+ endpoint=create_recipe_link_t.ENDPOINT_PATH,
397
+ args=args,
398
+ )
399
+ return self.do_request(api_request=api_request, return_type=create_recipe_link_t.Data)
119
400
 
120
401
  def create_recipes(
121
402
  self,
122
403
  *,
123
404
  material_family_id: base_t.ObjectId,
124
405
  recipe_definitions: list[create_recipes_t.CreateRecipeDefinition],
125
- project_id: typing.Optional[base_t.ObjectId] = None,
406
+ project_id: base_t.ObjectId | None = None,
126
407
  ) -> create_recipes_t.Data:
408
+ """Sets inputs values for an experiment. Values set can be numeric, text or categorical types in the Uncountable system
409
+
410
+ :param material_family_id: The identifier of the material family to create the recipes in
411
+ :param project_id: The identifier of the project to create the recipes in
412
+ """
127
413
  args = create_recipes_t.Arguments(
128
414
  material_family_id=material_family_id,
129
415
  project_id=project_id,
@@ -136,12 +422,56 @@ class ClientMethods(ABC):
136
422
  )
137
423
  return self.do_request(api_request=api_request, return_type=create_recipes_t.Data)
138
424
 
425
+ def disassociate_recipe_as_input(
426
+ self,
427
+ *,
428
+ recipe_key: identifier_t.IdentifierKey,
429
+ ) -> disassociate_recipe_as_input_t.Data:
430
+ """Remove any association between a recipe and ingredients
431
+
432
+ :param recipe_key: Identifier for the recipe
433
+ """
434
+ args = disassociate_recipe_as_input_t.Arguments(
435
+ recipe_key=recipe_key,
436
+ )
437
+ api_request = APIRequest(
438
+ method=disassociate_recipe_as_input_t.ENDPOINT_METHOD,
439
+ endpoint=disassociate_recipe_as_input_t.ENDPOINT_PATH,
440
+ args=args,
441
+ )
442
+ return self.do_request(api_request=api_request, return_type=disassociate_recipe_as_input_t.Data)
443
+
444
+ def edit_recipe_inputs(
445
+ self,
446
+ *,
447
+ recipe_key: identifier_t.IdentifierKey,
448
+ recipe_workflow_step_identifier: recipe_workflow_steps_t.RecipeWorkflowStepIdentifier,
449
+ edits: list[edit_recipe_inputs_t.RecipeInputEdit],
450
+ ) -> edit_recipe_inputs_t.Data:
451
+ """Clear, update, or add inputs on a recipe
452
+
453
+ :param recipe_key: Identifier for the recipe
454
+ """
455
+ args = edit_recipe_inputs_t.Arguments(
456
+ recipe_key=recipe_key,
457
+ recipe_workflow_step_identifier=recipe_workflow_step_identifier,
458
+ edits=edits,
459
+ )
460
+ api_request = APIRequest(
461
+ method=edit_recipe_inputs_t.ENDPOINT_METHOD,
462
+ endpoint=edit_recipe_inputs_t.ENDPOINT_PATH,
463
+ args=args,
464
+ )
465
+ return self.do_request(api_request=api_request, return_type=edit_recipe_inputs_t.Data)
139
466
 
140
467
  def execute_batch(
141
468
  self,
142
469
  *,
143
470
  requests: list[execute_batch_t.BatchRequest],
144
471
  ) -> execute_batch_t.Data:
472
+ """Run multiple API calls via one request
473
+
474
+ """
145
475
  args = execute_batch_t.Arguments(
146
476
  requests=requests,
147
477
  )
@@ -152,14 +482,60 @@ class ClientMethods(ABC):
152
482
  )
153
483
  return self.do_request(api_request=api_request, return_type=execute_batch_t.Data)
154
484
 
485
+ def execute_batch_load_async(
486
+ self,
487
+ *,
488
+ requests: list[async_batch_t.AsyncBatchRequest],
489
+ ) -> execute_batch_load_async_t.Data:
490
+ """Run multiple API calls via one request
491
+
492
+ """
493
+ args = execute_batch_load_async_t.Arguments(
494
+ requests=requests,
495
+ )
496
+ api_request = APIRequest(
497
+ method=execute_batch_load_async_t.ENDPOINT_METHOD,
498
+ endpoint=execute_batch_load_async_t.ENDPOINT_PATH,
499
+ args=args,
500
+ )
501
+ return self.do_request(api_request=api_request, return_type=execute_batch_load_async_t.Data)
502
+
503
+ def get_column_calculation_values(
504
+ self,
505
+ *,
506
+ recipe_keys: list[identifier_t.IdentifierKey],
507
+ calculation_key: identifier_t.IdentifierKey,
508
+ ) -> get_column_calculation_values_t.Data:
509
+ """Get the values for a column calculations for recipes
510
+
511
+ :param recipe_keys: Required: The recipe keys to load values for
512
+ :param calculation_key: Required: The calculation key to get the values for
513
+ """
514
+ args = get_column_calculation_values_t.Arguments(
515
+ recipe_keys=recipe_keys,
516
+ calculation_key=calculation_key,
517
+ )
518
+ api_request = APIRequest(
519
+ method=get_column_calculation_values_t.ENDPOINT_METHOD,
520
+ endpoint=get_column_calculation_values_t.ENDPOINT_PATH,
521
+ args=args,
522
+ )
523
+ return self.do_request(api_request=api_request, return_type=get_column_calculation_values_t.Data)
155
524
 
156
525
  def get_curve(
157
526
  self,
158
527
  *,
159
- recipe_output_id: base_t.ObjectId,
528
+ recipe_output_id: base_t.ObjectId | None = None,
529
+ recipe_input_id: base_t.ObjectId | None = None,
160
530
  ) -> get_curve_t.Data:
531
+ """Returns an array of values for the specified curve id.
532
+
533
+ :param recipe_output_id: The recipe output ID to fetch the curve for. This must be a curve recipe output. Recipe Outputs can be found from external_get_recipes_data
534
+ :param recipe_input_id: The recipe input ID to fetch the curve for. This must be a curve recipe input. Recipe Inputs can be found from external_get_recipes_data
535
+ """
161
536
  args = get_curve_t.Arguments(
162
537
  recipe_output_id=recipe_output_id,
538
+ recipe_input_id=recipe_input_id,
163
539
  )
164
540
  api_request = APIRequest(
165
541
  method=get_curve_t.ENDPOINT_METHOD,
@@ -168,13 +544,17 @@ class ClientMethods(ABC):
168
544
  )
169
545
  return self.do_request(api_request=api_request, return_type=get_curve_t.Data)
170
546
 
171
-
172
547
  def get_entities_data(
173
548
  self,
174
549
  *,
175
550
  entity_ids: list[base_t.ObjectId],
176
551
  entity_type: entity_t.EntityType,
177
552
  ) -> get_entities_data_t.Data:
553
+ """Gets the details for a passed entity
554
+
555
+ :param entity_ids: Ids of the entity to retrieve
556
+ :param entity_type: The type of the entities requested, e.g. lab_request or approval
557
+ """
178
558
  args = get_entities_data_t.Arguments(
179
559
  entity_ids=entity_ids,
180
560
  entity_type=entity_type,
@@ -186,16 +566,23 @@ class ClientMethods(ABC):
186
566
  )
187
567
  return self.do_request(api_request=api_request, return_type=get_entities_data_t.Data)
188
568
 
189
-
190
569
  def get_input_data(
191
570
  self,
192
571
  *,
193
572
  material_family_id: base_t.ObjectId,
194
573
  input_ids: typing.Optional[list[base_t.ObjectId]],
195
574
  is_parameter: typing.Optional[bool],
196
- offset: typing.Optional[typing.Optional[int]] = None,
197
- limit: typing.Optional[typing.Optional[int]] = None,
575
+ offset: typing.Optional[int] | None = None,
576
+ limit: typing.Optional[int] | None = None,
198
577
  ) -> get_input_data_t.Data:
578
+ """Gets the attribute, categorization and other metadata associated with a set of inputs. An input is either an ingredient or process parameter, with metadata and calculations assigned separately
579
+
580
+ :param material_family_id: The material family ID to get the input values from.
581
+ :param input_ids: The input IDs to get the data from. If this is not filled in, all inputs from a material family will be returned (in paginated form).
582
+ :param offset: Used for pagination, where the number of results returned exceeds the limit. Results are always ordered by the input ID. [Pagination More Info](#pagination)
583
+ :param is_parameter: Whether to get parameters or ingredients. By default both are returned. When set to true, only parameters are returned, and when set to false, only ingredients are returned
584
+ :param limit: 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)
585
+ """
199
586
  args = get_input_data_t.Arguments(
200
587
  material_family_id=material_family_id,
201
588
  input_ids=input_ids,
@@ -210,12 +597,15 @@ class ClientMethods(ABC):
210
597
  )
211
598
  return self.do_request(api_request=api_request, return_type=get_input_data_t.Data)
212
599
 
213
-
214
600
  def get_input_group_names(
215
601
  self,
216
602
  *,
217
603
  material_family_id: base_t.ObjectId,
218
604
  ) -> get_input_group_names_t.Data:
605
+ """Gets the name of all input groups in a material family that either the user created, or are shared to all users.
606
+
607
+ :param material_family_id: Required: The Material Family ID to get the input groups from.
608
+ """
219
609
  args = get_input_group_names_t.Arguments(
220
610
  material_family_id=material_family_id,
221
611
  )
@@ -226,15 +616,21 @@ class ClientMethods(ABC):
226
616
  )
227
617
  return self.do_request(api_request=api_request, return_type=get_input_group_names_t.Data)
228
618
 
229
-
230
619
  def get_input_names(
231
620
  self,
232
621
  *,
233
622
  material_family_id: base_t.ObjectId,
234
623
  is_parameter: typing.Optional[bool],
235
- offset: typing.Optional[typing.Optional[int]] = None,
236
- limit: typing.Optional[typing.Optional[int]] = None,
624
+ offset: typing.Optional[int] | None = None,
625
+ limit: typing.Optional[int] | None = None,
237
626
  ) -> get_input_names_t.Data:
627
+ """Gets the name of all inputs for a material family. An input is either an ingredient or process parameter, with metadata and calculations assigned separately
628
+
629
+ :param material_family_id: The material family ID to get the input values from
630
+ :param offset: Used for pagination, where the number of results returned exceeds the limit. Results are always ordered by the input ID. [Pagination More Info](#pagination)
631
+ :param is_parameter: Whether to get parameters or ingredients. By default both are returned. When set to true, only parameters are returned, and when set to false, only ingredients are returned
632
+ :param limit: 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)
633
+ """
238
634
  args = get_input_names_t.Arguments(
239
635
  material_family_id=material_family_id,
240
636
  offset=offset,
@@ -248,12 +644,15 @@ class ClientMethods(ABC):
248
644
  )
249
645
  return self.do_request(api_request=api_request, return_type=get_input_names_t.Data)
250
646
 
251
-
252
647
  def get_inputs_data(
253
648
  self,
254
649
  *,
255
650
  input_ids: list[base_t.ObjectId],
256
651
  ) -> get_inputs_data_t.Data:
652
+ """Gets the details for passed input ids
653
+
654
+ :param input_ids: Ids of the inputs to retrieve
655
+ """
257
656
  args = get_inputs_data_t.Arguments(
258
657
  input_ids=input_ids,
259
658
  )
@@ -264,15 +663,21 @@ class ClientMethods(ABC):
264
663
  )
265
664
  return self.do_request(api_request=api_request, return_type=get_inputs_data_t.Data)
266
665
 
267
-
268
666
  def get_output_data(
269
667
  self,
270
668
  *,
271
669
  material_family_id: base_t.ObjectId,
272
- output_ids: typing.Optional[list[base_t.ObjectId]] = None,
273
- offset: typing.Optional[int] = None,
274
- limit: typing.Optional[int] = None,
670
+ output_ids: list[base_t.ObjectId] | None = None,
671
+ offset: int | None = None,
672
+ limit: int | None = None,
275
673
  ) -> get_output_data_t.Data:
674
+ """Gets the attribute, categorization and other metadata associated with a set of outputs
675
+
676
+ :param material_family_id: The material family ID to get the output values from.
677
+ :param output_ids: The output IDs to get the data from. If this is not filled in, all outputs from a material family will be returned (in paginated form).
678
+ :param offset: Used for pagination, where the number of results returned exceeds the limit. Results are always ordered by the output ID. [Pagination More Info](#pagination)
679
+ :param limit: 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)
680
+ """
276
681
  args = get_output_data_t.Arguments(
277
682
  material_family_id=material_family_id,
278
683
  output_ids=output_ids,
@@ -286,14 +691,19 @@ class ClientMethods(ABC):
286
691
  )
287
692
  return self.do_request(api_request=api_request, return_type=get_output_data_t.Data)
288
693
 
289
-
290
694
  def get_output_names(
291
695
  self,
292
696
  *,
293
697
  material_family_id: base_t.ObjectId,
294
- offset: typing.Optional[int] = None,
295
- limit: typing.Optional[int] = None,
698
+ offset: int | None = None,
699
+ limit: int | None = None,
296
700
  ) -> get_output_names_t.Data:
701
+ """Gets the name of all outputs for a material family. An output represents a measurement value of any time (numeric, text, curve, etc). This includes calculations based off of other outputs, such as a calculated change over time
702
+
703
+ :param material_family_id: The material family ID to get the output values from
704
+ :param offset: Used for pagination, where the number of results returned exceeds the limit. Results are always ordered by the output ID. [Pagination More Info](#pagination)
705
+ :param limit: 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)
706
+ """
297
707
  args = get_output_names_t.Arguments(
298
708
  material_family_id=material_family_id,
299
709
  offset=offset,
@@ -306,13 +716,17 @@ class ClientMethods(ABC):
306
716
  )
307
717
  return self.do_request(api_request=api_request, return_type=get_output_names_t.Data)
308
718
 
309
-
310
719
  def get_projects(
311
720
  self,
312
721
  *,
313
722
  all_material_families: bool,
314
723
  material_family_id: typing.Optional[base_t.ObjectId],
315
724
  ) -> get_projects_t.Data:
725
+ """Gets either all projects created in the platform, or the projects associated with a material family ID. Projects are where experiments are placed in Uncountable, similar to folders in a directory structure
726
+
727
+ :param all_material_families: Whether to get projects from all material families. Material families are high level groupings of data, usually separated by functional area
728
+ :param material_family_id: The specific material family ID to get projects from. Only fill this in if all_material_families is set to false
729
+ """
316
730
  args = get_projects_t.Arguments(
317
731
  all_material_families=all_material_families,
318
732
  material_family_id=material_family_id,
@@ -324,14 +738,19 @@ class ClientMethods(ABC):
324
738
  )
325
739
  return self.do_request(api_request=api_request, return_type=get_projects_t.Data)
326
740
 
327
-
328
741
  def get_projects_data(
329
742
  self,
330
743
  *,
331
744
  project_ids: list[base_t.ObjectId],
332
- offset: typing.Optional[typing.Optional[int]] = None,
333
- limit: typing.Optional[typing.Optional[int]] = None,
745
+ offset: typing.Optional[int] | None = None,
746
+ limit: typing.Optional[int] | None = None,
334
747
  ) -> get_projects_data_t.Data:
748
+ """Gets either all data associated with a set of projects created in the platform. Because Uncountables recipe structure is complex, various data values are exploded out to increase efficiency in parsing, and this page is paginated to prevent too large of return values
749
+
750
+ :param project_ids: The projects to get the data from
751
+ :param offset: Used for pagination. All pagination is done in order of Project ID. [Pagination More Info](#pagination)
752
+ :param limit: 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)
753
+ """
335
754
  args = get_projects_data_t.Arguments(
336
755
  project_ids=project_ids,
337
756
  offset=offset,
@@ -344,13 +763,17 @@ class ClientMethods(ABC):
344
763
  )
345
764
  return self.do_request(api_request=api_request, return_type=get_projects_data_t.Data)
346
765
 
347
-
348
766
  def get_recipe_calculations(
349
767
  self,
350
768
  *,
351
769
  recipe_ids: list[base_t.ObjectId],
352
- calculation_ids: typing.Optional[list[base_t.ObjectId]] = None,
770
+ calculation_ids: list[base_t.ObjectId] | None = None,
353
771
  ) -> get_recipe_calculations_t.Data:
772
+ """Gets the calculations for the passed recipes
773
+
774
+ :param recipe_ids: Ids of the Recipes to retrieve calculations for
775
+ :param calculation_ids: Optionally a list of ids of calculations to retrieve
776
+ """
354
777
  args = get_recipe_calculations_t.Arguments(
355
778
  recipe_ids=recipe_ids,
356
779
  calculation_ids=calculation_ids,
@@ -362,7 +785,6 @@ class ClientMethods(ABC):
362
785
  )
363
786
  return self.do_request(api_request=api_request, return_type=get_recipe_calculations_t.Data)
364
787
 
365
-
366
788
  def get_recipe_links(
367
789
  self,
368
790
  *,
@@ -370,6 +792,12 @@ class ClientMethods(ABC):
370
792
  depth: int = 1,
371
793
  link_types: typing.Optional[list[recipe_links_t.RecipeLinkType]],
372
794
  ) -> get_recipe_links_t.Data:
795
+ """Gets the links for the passed recipes
796
+
797
+ :param recipe_ids: Ids of the Recipes to retrieve links for
798
+ :param depth: How many layers deep to look for links
799
+ :param link_types: Optional filter to only desired link types
800
+ """
373
801
  args = get_recipe_links_t.Arguments(
374
802
  recipe_ids=recipe_ids,
375
803
  depth=depth,
@@ -382,15 +810,21 @@ class ClientMethods(ABC):
382
810
  )
383
811
  return self.do_request(api_request=api_request, return_type=get_recipe_links_t.Data)
384
812
 
385
-
386
813
  def get_recipe_metadata_data(
387
814
  self,
388
815
  *,
389
816
  material_family_id: base_t.ObjectId,
390
817
  recipe_metadata_ids: typing.Optional[list[base_t.ObjectId]],
391
- offset: typing.Optional[typing.Optional[int]] = None,
392
- limit: typing.Optional[typing.Optional[int]] = None,
818
+ offset: typing.Optional[int] | None = None,
819
+ limit: typing.Optional[int] | None = None,
393
820
  ) -> get_recipe_metadata_data_t.Data:
821
+ """Gets the recipe metadata. Recipe metadata is data associated with experiments that is not an input, output or calculation, such as a sample ID.
822
+
823
+ :param material_family_id: The material family ID to get the recipe metadata values from.
824
+ :param recipe_metadata_ids: 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).
825
+ :param offset: Used for pagination, where the number of results returned exceeds the limit. Results are always ordered by the metadata ID. [Pagination More Info](#pagination)
826
+ :param limit: 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)
827
+ """
394
828
  args = get_recipe_metadata_data_t.Arguments(
395
829
  material_family_id=material_family_id,
396
830
  recipe_metadata_ids=recipe_metadata_ids,
@@ -404,12 +838,15 @@ class ClientMethods(ABC):
404
838
  )
405
839
  return self.do_request(api_request=api_request, return_type=get_recipe_metadata_data_t.Data)
406
840
 
407
-
408
841
  def get_recipe_names(
409
842
  self,
410
843
  *,
411
844
  project_id: base_t.ObjectId,
412
845
  ) -> get_recipe_names_t.Data:
846
+ """Gets the name of all recipes (or experiments, used as synonyms by Uncountable) for a project. The call external_get_projects can be used to find projects
847
+
848
+ :param project_id: Required: The project ID to get the recipes/experiments from.
849
+ """
413
850
  args = get_recipe_names_t.Arguments(
414
851
  project_id=project_id,
415
852
  )
@@ -420,12 +857,15 @@ class ClientMethods(ABC):
420
857
  )
421
858
  return self.do_request(api_request=api_request, return_type=get_recipe_names_t.Data)
422
859
 
423
-
424
860
  def get_recipe_output_metadata(
425
861
  self,
426
862
  *,
427
863
  recipe_output_ids: list[base_t.ObjectId],
428
864
  ) -> get_recipe_output_metadata_t.Data:
865
+ """Gets the metadata values for the passed recipe outputs
866
+
867
+ :param recipe_output_ids: Ids of the Recipe Outputs to retrieve metadata for
868
+ """
429
869
  args = get_recipe_output_metadata_t.Arguments(
430
870
  recipe_output_ids=recipe_output_ids,
431
871
  )
@@ -436,15 +876,21 @@ class ClientMethods(ABC):
436
876
  )
437
877
  return self.do_request(api_request=api_request, return_type=get_recipe_output_metadata_t.Data)
438
878
 
439
-
440
879
  def get_recipes_data(
441
880
  self,
442
881
  *,
443
- recipe_ids: typing.Optional[typing.Optional[list[base_t.ObjectId]]] = None,
444
- project_id: typing.Optional[typing.Optional[base_t.ObjectId]] = None,
445
- offset: typing.Optional[typing.Optional[int]] = None,
446
- limit: typing.Optional[typing.Optional[int]] = None,
882
+ recipe_ids: typing.Optional[list[base_t.ObjectId]] | None = None,
883
+ project_id: typing.Optional[base_t.ObjectId] | None = None,
884
+ offset: typing.Optional[int] | None = None,
885
+ limit: typing.Optional[int] | None = None,
447
886
  ) -> get_recipes_data_t.Data:
887
+ """Gets all data associated with a set of recipes. Because Uncountables recipe structure is complex, various data values are exploded out to increase efficiency in parsing, and this page is paginated to prevent too large of return values
888
+
889
+ :param recipe_ids: The recipes to get the data from. Either these or project_id must be filled in
890
+ :param project_id: The projects to get the data from. Either these or recipe_ids must be filled in
891
+ :param offset: Used for pagination. All pagination is done in order of Recipe ID. [Pagination More Info](#pagination)
892
+ :param limit: 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)
893
+ """
448
894
  args = get_recipes_data_t.Arguments(
449
895
  recipe_ids=recipe_ids,
450
896
  project_id=project_id,
@@ -458,16 +904,76 @@ class ClientMethods(ABC):
458
904
  )
459
905
  return self.do_request(api_request=api_request, return_type=get_recipes_data_t.Data)
460
906
 
907
+ def grant_entity_permissions(
908
+ self,
909
+ *,
910
+ entity_type: entity_t.LimitedEntityType,
911
+ entity_key: identifier_t.IdentifierKey,
912
+ permission_types: list[entity_t.GrantableEntityPermissionType],
913
+ user_keys: list[identifier_t.IdentifierKey] | None = None,
914
+ user_group_keys: list[identifier_t.IdentifierKey] | None = None,
915
+ all_users: bool | None = None,
916
+ ) -> grant_entity_permissions_t.Data:
917
+ """Grant entity permissions to a list of users or user groups or to all users.
918
+
919
+ """
920
+ args = grant_entity_permissions_t.Arguments(
921
+ entity_type=entity_type,
922
+ entity_key=entity_key,
923
+ permission_types=permission_types,
924
+ user_keys=user_keys,
925
+ user_group_keys=user_group_keys,
926
+ all_users=all_users,
927
+ )
928
+ api_request = APIRequest(
929
+ method=grant_entity_permissions_t.ENDPOINT_METHOD,
930
+ endpoint=grant_entity_permissions_t.ENDPOINT_PATH,
931
+ args=args,
932
+ )
933
+ return self.do_request(api_request=api_request, return_type=grant_entity_permissions_t.Data)
934
+
935
+ def invoke_uploader(
936
+ self,
937
+ *,
938
+ uploader_key: identifier_t.IdentifierKey,
939
+ destination: generic_upload_t.UploadDestination,
940
+ file_id: base_t.ObjectId | None = None,
941
+ file_ids: list[base_t.ObjectId] | None = None,
942
+ ) -> invoke_uploader_t.Data:
943
+ """Runs a file through an uploader.
944
+
945
+ :param file_id: DEPRECATED: use file_ids
946
+ """
947
+ args = invoke_uploader_t.Arguments(
948
+ file_id=file_id,
949
+ file_ids=file_ids,
950
+ uploader_key=uploader_key,
951
+ destination=destination,
952
+ )
953
+ api_request = APIRequest(
954
+ method=invoke_uploader_t.ENDPOINT_METHOD,
955
+ endpoint=invoke_uploader_t.ENDPOINT_PATH,
956
+ args=args,
957
+ )
958
+ return self.do_request(api_request=api_request, return_type=invoke_uploader_t.Data)
461
959
 
462
960
  def list_entities(
463
961
  self,
464
962
  *,
465
- entity_type: entity_t.EntityType,
466
963
  config_reference: str,
467
- attributes: typing.Optional[dict[OpaqueKey, base_t.JsonValue]] = None,
468
- offset: typing.Optional[typing.Optional[int]] = None,
469
- limit: typing.Optional[typing.Optional[int]] = None,
964
+ entity_type: entity_t.EntityType | None = None,
965
+ attributes: dict[OpaqueKey, base_t.JsonValue] | None = None,
966
+ offset: typing.Optional[int] | None = None,
967
+ limit: typing.Optional[int] | None = None,
470
968
  ) -> list_entities_t.Data:
969
+ """Uses a structured loading configuration to list entities in the system
970
+
971
+ :param entity_type: DEPRECATED: The type of the entities requested, e.g. lab_request, recipe
972
+ :param config_reference: The configuration reference name for the listing config
973
+ :param attributes: Attributes to pass to the configuration for parameterizing filters
974
+ :param offset: Used for pagination. Pagination is done based on the sorting of the config. [Pagination More Info](#pagination)
975
+ :param limit: 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)
976
+ """
471
977
  args = list_entities_t.Arguments(
472
978
  entity_type=entity_type,
473
979
  config_reference=config_reference,
@@ -482,6 +988,160 @@ class ClientMethods(ABC):
482
988
  )
483
989
  return self.do_request(api_request=api_request, return_type=list_entities_t.Data)
484
990
 
991
+ def list_id_source(
992
+ self,
993
+ *,
994
+ spec: id_source_t.IdSourceSpec,
995
+ search_label: str,
996
+ offset: typing.Optional[int] | None = None,
997
+ limit: typing.Optional[int] | None = None,
998
+ ) -> list_id_source_t.Data:
999
+ """Lists id and label pairs
1000
+
1001
+ :param spec: The id source spec to use
1002
+ :param search_label: Text to search within the labels to search matches
1003
+ :param offset: Used for pagination. Pagination is done based on the sorting of the config. [Pagination More Info](#pagination)
1004
+ :param limit: 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)
1005
+ """
1006
+ args = list_id_source_t.Arguments(
1007
+ spec=spec,
1008
+ search_label=search_label,
1009
+ offset=offset,
1010
+ limit=limit,
1011
+ )
1012
+ api_request = APIRequest(
1013
+ method=list_id_source_t.ENDPOINT_METHOD,
1014
+ endpoint=list_id_source_t.ENDPOINT_PATH,
1015
+ args=args,
1016
+ )
1017
+ return self.do_request(api_request=api_request, return_type=list_id_source_t.Data)
1018
+
1019
+ def external_lock_entity(
1020
+ self,
1021
+ *,
1022
+ entity_key: identifier_t.IdentifierKey,
1023
+ entity_type: entity_t.EntityType,
1024
+ globally_removable: bool | None = None,
1025
+ ) -> lock_entity_t.Data:
1026
+ """Lock an entity
1027
+
1028
+ :param entity_key: Identifier for the entity
1029
+ :param globally_removable: Should the lock be removable by any user or just admins
1030
+ """
1031
+ args = lock_entity_t.Arguments(
1032
+ entity_key=entity_key,
1033
+ entity_type=entity_type,
1034
+ globally_removable=globally_removable,
1035
+ )
1036
+ api_request = APIRequest(
1037
+ method=lock_entity_t.ENDPOINT_METHOD,
1038
+ endpoint=lock_entity_t.ENDPOINT_PATH,
1039
+ args=args,
1040
+ )
1041
+ return self.do_request(api_request=api_request, return_type=lock_entity_t.Data)
1042
+
1043
+ def lock_recipes(
1044
+ self,
1045
+ *,
1046
+ type: lock_recipes_t.RecipeLockType = lock_recipes_t.RecipeLockType.ALL,
1047
+ recipes: list[identifier_t.IdentifierKey],
1048
+ globally_removable: bool,
1049
+ lock_samples: bool | None = None,
1050
+ comments: str | None = None,
1051
+ ) -> lock_recipes_t.Data:
1052
+ """Lock experiments. Experiments will require unlocking to be editable. Edits to the experiments are blocked while they are locked.
1053
+
1054
+ :param type: The type of lock to set.
1055
+ All = both inputs and measurements are locked.
1056
+ Inputs Only = only inputs are locked from editing.
1057
+
1058
+ :param recipes: The recipes to lock, a maximum of 100 can be sent
1059
+ :param globally_removable: If true any user can unlock the experiment. If false the locking user is the only user that can unlock.
1060
+ :param lock_samples: Should associated experiment test samples also be locked.
1061
+ :param comments: Optional comment describing the purpose of locking
1062
+ """
1063
+ args = lock_recipes_t.Arguments(
1064
+ type=type,
1065
+ recipes=recipes,
1066
+ globally_removable=globally_removable,
1067
+ lock_samples=lock_samples,
1068
+ comments=comments,
1069
+ )
1070
+ api_request = APIRequest(
1071
+ method=lock_recipes_t.ENDPOINT_METHOD,
1072
+ endpoint=lock_recipes_t.ENDPOINT_PATH,
1073
+ args=args,
1074
+ )
1075
+ return self.do_request(api_request=api_request, return_type=lock_recipes_t.Data)
1076
+
1077
+ def match_id_source(
1078
+ self,
1079
+ *,
1080
+ spec: id_source_t.IdSourceSpec,
1081
+ names: list[str],
1082
+ ) -> match_id_source_t.Data:
1083
+ """Lists id and label pairs
1084
+
1085
+ :param spec: The id source spec to use
1086
+ :param names: The names to match with the id source. At most 10 are allowed at a time
1087
+ """
1088
+ args = match_id_source_t.Arguments(
1089
+ spec=spec,
1090
+ names=names,
1091
+ )
1092
+ api_request = APIRequest(
1093
+ method=match_id_source_t.ENDPOINT_METHOD,
1094
+ endpoint=match_id_source_t.ENDPOINT_PATH,
1095
+ args=args,
1096
+ )
1097
+ return self.do_request(api_request=api_request, return_type=match_id_source_t.Data)
1098
+
1099
+ def remove_recipe_from_project(
1100
+ self,
1101
+ *,
1102
+ recipe_key: identifier_t.IdentifierKey,
1103
+ project_key: identifier_t.IdentifierKey,
1104
+ ) -> remove_recipe_from_project_t.Data:
1105
+ """Removes a recipe from a project
1106
+
1107
+ :param recipe_key: The identifier key of the recipe to remove from the project
1108
+ :param project_key: The identifier key of the project to remove the recipe from
1109
+ """
1110
+ args = remove_recipe_from_project_t.Arguments(
1111
+ recipe_key=recipe_key,
1112
+ project_key=project_key,
1113
+ )
1114
+ api_request = APIRequest(
1115
+ method=remove_recipe_from_project_t.ENDPOINT_METHOD,
1116
+ endpoint=remove_recipe_from_project_t.ENDPOINT_PATH,
1117
+ args=args,
1118
+ )
1119
+ return self.do_request(api_request=api_request, return_type=remove_recipe_from_project_t.Data)
1120
+
1121
+ def remove_recipe_link(
1122
+ self,
1123
+ *,
1124
+ recipe_from_key: identifier_t.IdentifierKey,
1125
+ recipe_to_key: identifier_t.IdentifierKey,
1126
+ link_type: typing.Union[typing.Literal[recipe_links_t.RecipeLinkType.CHILD], typing.Literal[recipe_links_t.RecipeLinkType.CONTROL], typing.Literal[recipe_links_t.RecipeLinkType.USER_LINK]],
1127
+ ) -> remove_recipe_link_t.Data:
1128
+ """Remove a link between two recipes. Skip if the link doesn't already exist
1129
+
1130
+ :param recipe_from_key: Identifier for the recipe the link comes from
1131
+ :param recipe_to_key: Identifier for the recipe the link goes to
1132
+ :param link_type: The type of link being removed
1133
+ """
1134
+ args = remove_recipe_link_t.Arguments(
1135
+ recipe_from_key=recipe_from_key,
1136
+ recipe_to_key=recipe_to_key,
1137
+ link_type=link_type,
1138
+ )
1139
+ api_request = APIRequest(
1140
+ method=remove_recipe_link_t.ENDPOINT_METHOD,
1141
+ endpoint=remove_recipe_link_t.ENDPOINT_PATH,
1142
+ args=args,
1143
+ )
1144
+ return self.do_request(api_request=api_request, return_type=remove_recipe_link_t.Data)
485
1145
 
486
1146
  def resolve_entity_ids(
487
1147
  self,
@@ -489,6 +1149,11 @@ class ClientMethods(ABC):
489
1149
  entity_ids: list[typing.Union[str, base_t.ObjectId]],
490
1150
  entity_type: entity_t.EntityType,
491
1151
  ) -> resolve_entity_ids_t.Data:
1152
+ """Gets the names for passed in ids
1153
+
1154
+ :param entity_ids: Ids of the entity to retrieve
1155
+ :param entity_type: The type of the entities requested
1156
+ """
492
1157
  args = resolve_entity_ids_t.Arguments(
493
1158
  entity_ids=entity_ids,
494
1159
  entity_type=entity_type,
@@ -500,12 +1165,14 @@ class ClientMethods(ABC):
500
1165
  )
501
1166
  return self.do_request(api_request=api_request, return_type=resolve_entity_ids_t.Data)
502
1167
 
503
-
504
1168
  def resolve_output_conditions(
505
1169
  self,
506
1170
  *,
507
1171
  requested_conditions: list[resolve_output_conditions_t.ConditionRequest],
508
1172
  ) -> resolve_output_conditions_t.Data:
1173
+ """For the provided set of condition parameter id and values, returns the existing or newly created output condition id for that value and id pair.
1174
+
1175
+ """
509
1176
  args = resolve_output_conditions_t.Arguments(
510
1177
  requested_conditions=requested_conditions,
511
1178
  )
@@ -516,12 +1183,87 @@ class ClientMethods(ABC):
516
1183
  )
517
1184
  return self.do_request(api_request=api_request, return_type=resolve_output_conditions_t.Data)
518
1185
 
1186
+ def run_trigger(
1187
+ self,
1188
+ *,
1189
+ trigger_ref_name: str,
1190
+ entity: entity_t.Entity | None = None,
1191
+ ) -> run_trigger_t.Data:
1192
+ """Runs a trigger. Requires admin access
1193
+
1194
+ """
1195
+ args = run_trigger_t.Arguments(
1196
+ entity=entity,
1197
+ trigger_ref_name=trigger_ref_name,
1198
+ )
1199
+ api_request = APIRequest(
1200
+ method=run_trigger_t.ENDPOINT_METHOD,
1201
+ endpoint=run_trigger_t.ENDPOINT_PATH,
1202
+ args=args,
1203
+ )
1204
+ return self.do_request(api_request=api_request, return_type=run_trigger_t.Data)
1205
+
1206
+ def set_core_permissions(
1207
+ self,
1208
+ *,
1209
+ scope: set_core_permissions_t.PermissionsScope,
1210
+ permissions_types: list[permissions_t.CorePermissionType],
1211
+ update_type: post_base_t.UpdateType,
1212
+ user_group_ids: list[int] | None = None,
1213
+ user_ids: list[int] | None = None,
1214
+ ) -> set_core_permissions_t.Data:
1215
+ """Sets recipe related permissions
1216
+
1217
+ :param scope: Scope of permissions to change
1218
+ :param user_group_ids: User group ids to grant permission to
1219
+ :param user_ids: User ids to grant permission to
1220
+ :param update_type: The type of update to perform
1221
+ """
1222
+ args = set_core_permissions_t.Arguments(
1223
+ scope=scope,
1224
+ user_group_ids=user_group_ids,
1225
+ user_ids=user_ids,
1226
+ permissions_types=permissions_types,
1227
+ update_type=update_type,
1228
+ )
1229
+ api_request = APIRequest(
1230
+ method=set_core_permissions_t.ENDPOINT_METHOD,
1231
+ endpoint=set_core_permissions_t.ENDPOINT_PATH,
1232
+ args=args,
1233
+ )
1234
+ return self.do_request(api_request=api_request, return_type=set_core_permissions_t.Data)
1235
+
1236
+ def set_entity_field_values(
1237
+ self,
1238
+ *,
1239
+ entity_identifier: entity_t.EntityIdentifier,
1240
+ field_values: list[field_values_t.FieldArgumentValue],
1241
+ ) -> set_entity_field_values_t.Data:
1242
+ """Sets field values for an entity
1243
+
1244
+ :param entity_identifier: Entity to update
1245
+ :param field_values: Field values to set
1246
+ """
1247
+ args = set_entity_field_values_t.Arguments(
1248
+ entity_identifier=entity_identifier,
1249
+ field_values=field_values,
1250
+ )
1251
+ api_request = APIRequest(
1252
+ method=set_entity_field_values_t.ENDPOINT_METHOD,
1253
+ endpoint=set_entity_field_values_t.ENDPOINT_PATH,
1254
+ args=args,
1255
+ )
1256
+ return self.do_request(api_request=api_request, return_type=set_entity_field_values_t.Data)
519
1257
 
520
1258
  def set_input_attribute_values(
521
1259
  self,
522
1260
  *,
523
1261
  attribute_values: list[set_input_attribute_values_t.InputAttributeValue],
524
1262
  ) -> set_input_attribute_values_t.Data:
1263
+ """Sets attribute values for an input
1264
+
1265
+ :param attribute_values: The attributes of the input to set
1266
+ """
525
1267
  args = set_input_attribute_values_t.Arguments(
526
1268
  attribute_values=attribute_values,
527
1269
  )
@@ -532,12 +1274,87 @@ class ClientMethods(ABC):
532
1274
  )
533
1275
  return self.do_request(api_request=api_request, return_type=set_input_attribute_values_t.Data)
534
1276
 
1277
+ def external_set_input_category(
1278
+ self,
1279
+ *,
1280
+ input_key: identifier_t.IdentifierKey,
1281
+ category_id: typing.Optional[int],
1282
+ material_family_ids: list[int] | None = None,
1283
+ ) -> set_input_category_t.Data:
1284
+ """Sets subcategories for an input
1285
+
1286
+ :param input_key: Identifier for the input
1287
+ :param category_id: The category identifier to set. Null unsets the current category.
1288
+ :param material_family_ids: The material families to perform the update in
1289
+ """
1290
+ args = set_input_category_t.Arguments(
1291
+ input_key=input_key,
1292
+ category_id=category_id,
1293
+ material_family_ids=material_family_ids,
1294
+ )
1295
+ api_request = APIRequest(
1296
+ method=set_input_category_t.ENDPOINT_METHOD,
1297
+ endpoint=set_input_category_t.ENDPOINT_PATH,
1298
+ args=args,
1299
+ )
1300
+ return self.do_request(api_request=api_request, return_type=set_input_category_t.Data)
1301
+
1302
+ def external_set_input_subcategories(
1303
+ self,
1304
+ *,
1305
+ input_key: identifier_t.IdentifierKey,
1306
+ subcategory_ids: list[int],
1307
+ update_type: post_base_t.UpdateType,
1308
+ ) -> set_input_subcategories_t.Data:
1309
+ """Sets subcategories for an input
1310
+
1311
+ :param input_key: Identifier for the input
1312
+ :param subcategory_ids: The subcategory identifiers to set
1313
+ :param update_type: The type of update to perform
1314
+ """
1315
+ args = set_input_subcategories_t.Arguments(
1316
+ input_key=input_key,
1317
+ subcategory_ids=subcategory_ids,
1318
+ update_type=update_type,
1319
+ )
1320
+ api_request = APIRequest(
1321
+ method=set_input_subcategories_t.ENDPOINT_METHOD,
1322
+ endpoint=set_input_subcategories_t.ENDPOINT_PATH,
1323
+ args=args,
1324
+ )
1325
+ return self.do_request(api_request=api_request, return_type=set_input_subcategories_t.Data)
1326
+
1327
+ def set_intermediate_type(
1328
+ self,
1329
+ *,
1330
+ input_key: identifier_t.IdentifierKey,
1331
+ intermediate_type: set_intermediate_type_t.IntermediateType,
1332
+ ) -> set_intermediate_type_t.Data:
1333
+ """Sets the type of an intermediate ingredient.
1334
+
1335
+ :param input_key: The identifier key of the intermediate ingredient
1336
+ :param intermediate_type: The new type of the intermediate ingredient
1337
+ """
1338
+ args = set_intermediate_type_t.Arguments(
1339
+ input_key=input_key,
1340
+ intermediate_type=intermediate_type,
1341
+ )
1342
+ api_request = APIRequest(
1343
+ method=set_intermediate_type_t.ENDPOINT_METHOD,
1344
+ endpoint=set_intermediate_type_t.ENDPOINT_PATH,
1345
+ args=args,
1346
+ )
1347
+ return self.do_request(api_request=api_request, return_type=set_intermediate_type_t.Data)
535
1348
 
536
1349
  def set_recipe_inputs(
537
1350
  self,
538
1351
  *,
539
1352
  input_data: list[set_recipe_inputs_t.RecipeInputValue],
540
1353
  ) -> set_recipe_inputs_t.Data:
1354
+ """Sets inputs values for an experiment. Values set can be numeric, text or categorical types in the Uncountable system
1355
+
1356
+ :param input_data: The inputs to set. Must be at most 100 entries long
1357
+ """
541
1358
  args = set_recipe_inputs_t.Arguments(
542
1359
  input_data=input_data,
543
1360
  )
@@ -548,12 +1365,75 @@ class ClientMethods(ABC):
548
1365
  )
549
1366
  return self.do_request(api_request=api_request, return_type=set_recipe_inputs_t.Data)
550
1367
 
1368
+ def set_recipe_metadata(
1369
+ self,
1370
+ *,
1371
+ recipe_key: identifier_t.IdentifierKey,
1372
+ recipe_metadata: list[recipe_metadata_t.MetadataValue],
1373
+ ) -> set_recipe_metadata_t.Data:
1374
+ """Set metadata values on a recipe
1375
+
1376
+ :param recipe_key: Identifier for the recipe
1377
+ :param recipe_metadata: Metadata values to populate the recipe with
1378
+ """
1379
+ args = set_recipe_metadata_t.Arguments(
1380
+ recipe_key=recipe_key,
1381
+ recipe_metadata=recipe_metadata,
1382
+ )
1383
+ api_request = APIRequest(
1384
+ method=set_recipe_metadata_t.ENDPOINT_METHOD,
1385
+ endpoint=set_recipe_metadata_t.ENDPOINT_PATH,
1386
+ args=args,
1387
+ )
1388
+ return self.do_request(api_request=api_request, return_type=set_recipe_metadata_t.Data)
1389
+
1390
+ def set_recipe_output_annotations(
1391
+ self,
1392
+ *,
1393
+ updates: list[set_recipe_output_annotations_t.RecipeOutputUpdateAnnotations],
1394
+ ) -> set_recipe_output_annotations_t.Data:
1395
+ """Update annotations for an experiments outputs
1396
+
1397
+ :param updates: The output edits to perform. Must be at most 100 entries long
1398
+ """
1399
+ args = set_recipe_output_annotations_t.Arguments(
1400
+ updates=updates,
1401
+ )
1402
+ api_request = APIRequest(
1403
+ method=set_recipe_output_annotations_t.ENDPOINT_METHOD,
1404
+ endpoint=set_recipe_output_annotations_t.ENDPOINT_PATH,
1405
+ args=args,
1406
+ )
1407
+ return self.do_request(api_request=api_request, return_type=set_recipe_output_annotations_t.Data)
1408
+
1409
+ def set_recipe_output_file(
1410
+ self,
1411
+ *,
1412
+ output_file_data: set_recipe_output_file_t.RecipeOutputFileValue,
1413
+ ) -> set_recipe_output_file_t.Data:
1414
+ """Sets output file value for an experiment. Include a single file as part of the FormData of the request with the filename as the key
1415
+
1416
+ :param output_file_data: The output file to set
1417
+ """
1418
+ args = set_recipe_output_file_t.Arguments(
1419
+ output_file_data=output_file_data,
1420
+ )
1421
+ api_request = APIRequest(
1422
+ method=set_recipe_output_file_t.ENDPOINT_METHOD,
1423
+ endpoint=set_recipe_output_file_t.ENDPOINT_PATH,
1424
+ args=args,
1425
+ )
1426
+ return self.do_request(api_request=api_request, return_type=set_recipe_output_file_t.Data)
551
1427
 
552
1428
  def set_recipe_outputs(
553
1429
  self,
554
1430
  *,
555
1431
  output_data: list[set_recipe_outputs_t.RecipeOutputValue],
556
1432
  ) -> set_recipe_outputs_t.Data:
1433
+ """Sets output values for an experiment. Values set can be numeric, text or categorical types in the Uncountable system
1434
+
1435
+ :param output_data: The outputs to set. Must be at most 100 entries long
1436
+ """
557
1437
  args = set_recipe_outputs_t.Arguments(
558
1438
  output_data=output_data,
559
1439
  )
@@ -564,6 +1444,27 @@ class ClientMethods(ABC):
564
1444
  )
565
1445
  return self.do_request(api_request=api_request, return_type=set_recipe_outputs_t.Data)
566
1446
 
1447
+ def set_recipe_tags(
1448
+ self,
1449
+ *,
1450
+ recipe_key: identifier_t.IdentifierKey,
1451
+ recipe_tag_update: set_recipe_tags_t.RecipeTagUpdate,
1452
+ ) -> set_recipe_tags_t.Data:
1453
+ """Modifies recipes tags for a recipe
1454
+
1455
+ :param recipe_key: Identifier for the recipe
1456
+ :param recipe_tag_update: The update to perform on the recipe tags
1457
+ """
1458
+ args = set_recipe_tags_t.Arguments(
1459
+ recipe_key=recipe_key,
1460
+ recipe_tag_update=recipe_tag_update,
1461
+ )
1462
+ api_request = APIRequest(
1463
+ method=set_recipe_tags_t.ENDPOINT_METHOD,
1464
+ endpoint=set_recipe_tags_t.ENDPOINT_PATH,
1465
+ args=args,
1466
+ )
1467
+ return self.do_request(api_request=api_request, return_type=set_recipe_tags_t.Data)
567
1468
 
568
1469
  def set_values(
569
1470
  self,
@@ -571,6 +1472,9 @@ class ClientMethods(ABC):
571
1472
  entity: entity_t.Entity,
572
1473
  values: list[field_values_t.ArgumentValueRefName],
573
1474
  ) -> set_values_t.Data:
1475
+ """Sets field values for an entity
1476
+
1477
+ """
574
1478
  args = set_values_t.Arguments(
575
1479
  entity=entity,
576
1480
  values=values,
@@ -581,3 +1485,138 @@ class ClientMethods(ABC):
581
1485
  args=args,
582
1486
  )
583
1487
  return self.do_request(api_request=api_request, return_type=set_values_t.Data)
1488
+
1489
+ def transition_entity_phase(
1490
+ self,
1491
+ *,
1492
+ entity: entity_t.Entity,
1493
+ transition: transition_entity_phase_t.TransitionIdentifier,
1494
+ ) -> transition_entity_phase_t.Data:
1495
+ """Transitions an entity from one phase to another
1496
+
1497
+ """
1498
+ args = transition_entity_phase_t.Arguments(
1499
+ entity=entity,
1500
+ transition=transition,
1501
+ )
1502
+ api_request = APIRequest(
1503
+ method=transition_entity_phase_t.ENDPOINT_METHOD,
1504
+ endpoint=transition_entity_phase_t.ENDPOINT_PATH,
1505
+ args=args,
1506
+ )
1507
+ return self.do_request(api_request=api_request, return_type=transition_entity_phase_t.Data)
1508
+
1509
+ def unarchive_recipes(
1510
+ self,
1511
+ *,
1512
+ recipes: list[identifier_t.IdentifierKey],
1513
+ ) -> unarchive_recipes_t.Data:
1514
+ """Unarchive/restore the provided recipes
1515
+
1516
+ :param recipes: Identifier for the recipe
1517
+ """
1518
+ args = unarchive_recipes_t.Arguments(
1519
+ recipes=recipes,
1520
+ )
1521
+ api_request = APIRequest(
1522
+ method=unarchive_recipes_t.ENDPOINT_METHOD,
1523
+ endpoint=unarchive_recipes_t.ENDPOINT_PATH,
1524
+ args=args,
1525
+ )
1526
+ return self.do_request(api_request=api_request, return_type=unarchive_recipes_t.Data)
1527
+
1528
+ def external_unlock_entity(
1529
+ self,
1530
+ *,
1531
+ entity_key: identifier_t.IdentifierKey,
1532
+ entity_type: entity_t.EntityType,
1533
+ ) -> unlock_entity_t.Data:
1534
+ """Unlock an entity
1535
+
1536
+ :param entity_key: Identifier for the entity
1537
+ """
1538
+ args = unlock_entity_t.Arguments(
1539
+ entity_key=entity_key,
1540
+ entity_type=entity_type,
1541
+ )
1542
+ api_request = APIRequest(
1543
+ method=unlock_entity_t.ENDPOINT_METHOD,
1544
+ endpoint=unlock_entity_t.ENDPOINT_PATH,
1545
+ args=args,
1546
+ )
1547
+ return self.do_request(api_request=api_request, return_type=unlock_entity_t.Data)
1548
+
1549
+ def unlock_recipes(
1550
+ self,
1551
+ *,
1552
+ type: unlock_recipes_t.RecipeUnlockType = unlock_recipes_t.RecipeUnlockType.STANDARD,
1553
+ recipes: list[identifier_t.IdentifierKey],
1554
+ unlock_samples: bool | None = None,
1555
+ ) -> unlock_recipes_t.Data:
1556
+ """Unlock experiments. Experiments will edtiable after unlocking if they are currently locked.
1557
+
1558
+ :param type: The method to unlock recipes. Default is standard.
1559
+ :param recipes: The recipes to unlock, a maximum of 100 can be sent
1560
+ :param unlock_samples: Should associated experiment test samples also be unlocked.
1561
+ """
1562
+ args = unlock_recipes_t.Arguments(
1563
+ type=type,
1564
+ recipes=recipes,
1565
+ unlock_samples=unlock_samples,
1566
+ )
1567
+ api_request = APIRequest(
1568
+ method=unlock_recipes_t.ENDPOINT_METHOD,
1569
+ endpoint=unlock_recipes_t.ENDPOINT_PATH,
1570
+ args=args,
1571
+ )
1572
+ return self.do_request(api_request=api_request, return_type=unlock_recipes_t.Data)
1573
+
1574
+ def update_entity_material_families(
1575
+ self,
1576
+ *,
1577
+ entity_key: identifier_t.IdentifierKey,
1578
+ 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]],
1579
+ material_family_ids: list[base_t.ObjectId],
1580
+ update_type: post_base_t.UpdateType,
1581
+ ) -> update_entity_material_families_t.Data:
1582
+ """Updates the material families that the entity is available in
1583
+
1584
+ :param entity_key: The identifier for the entity to update across material families
1585
+ :param entity_type: The type of the entities requested
1586
+ :param material_family_ids: The material families to update
1587
+ :param update_type: The type of update to make
1588
+ """
1589
+ args = update_entity_material_families_t.Arguments(
1590
+ entity_key=entity_key,
1591
+ entity_type=entity_type,
1592
+ material_family_ids=material_family_ids,
1593
+ update_type=update_type,
1594
+ )
1595
+ api_request = APIRequest(
1596
+ method=update_entity_material_families_t.ENDPOINT_METHOD,
1597
+ endpoint=update_entity_material_families_t.ENDPOINT_PATH,
1598
+ args=args,
1599
+ )
1600
+ return self.do_request(api_request=api_request, return_type=update_entity_material_families_t.Data)
1601
+
1602
+ def upsert_field_options(
1603
+ self,
1604
+ *,
1605
+ option_set_key: identifier_t.IdentifierKey,
1606
+ field_options: list[upsert_field_options_t.FieldOption],
1607
+ ) -> upsert_field_options_t.Data:
1608
+ """Creates or updates field options for an option set
1609
+
1610
+ :param option_set_key: Identifier for the field option set
1611
+ :param field_options: Field options to upsert
1612
+ """
1613
+ args = upsert_field_options_t.Arguments(
1614
+ option_set_key=option_set_key,
1615
+ field_options=field_options,
1616
+ )
1617
+ api_request = APIRequest(
1618
+ method=upsert_field_options_t.ENDPOINT_METHOD,
1619
+ endpoint=upsert_field_options_t.ENDPOINT_PATH,
1620
+ args=args,
1621
+ )
1622
+ return self.do_request(api_request=api_request, return_type=upsert_field_options_t.Data)