UncountablePythonSDK 0.0.20__py3-none-any.whl → 0.0.22__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 (55) hide show
  1. {UncountablePythonSDK-0.0.20.dist-info → UncountablePythonSDK-0.0.22.dist-info}/METADATA +3 -1
  2. {UncountablePythonSDK-0.0.20.dist-info → UncountablePythonSDK-0.0.22.dist-info}/RECORD +55 -34
  3. examples/async_batch.py +36 -0
  4. examples/upload_files.py +19 -0
  5. pkgs/type_spec/actions_registry/__main__.py +35 -23
  6. pkgs/type_spec/actions_registry/emit_typescript.py +71 -9
  7. pkgs/type_spec/builder.py +125 -8
  8. pkgs/type_spec/config.py +1 -0
  9. pkgs/type_spec/emit_open_api.py +197 -16
  10. pkgs/type_spec/emit_open_api_util.py +18 -0
  11. pkgs/type_spec/emit_python.py +241 -55
  12. pkgs/type_spec/load_types.py +48 -5
  13. pkgs/type_spec/open_api_util.py +13 -33
  14. pkgs/type_spec/type_info/emit_type_info.py +129 -8
  15. type_spec/external/api/entity/create_entities.yaml +13 -1
  16. type_spec/external/api/entity/create_entity.yaml +13 -1
  17. type_spec/external/api/entity/transition_entity_phase.yaml +44 -0
  18. type_spec/external/api/permissions/set_core_permissions.yaml +69 -0
  19. type_spec/external/api/recipes/associate_recipe_as_input.yaml +4 -4
  20. type_spec/external/api/recipes/create_recipe.yaml +2 -1
  21. type_spec/external/api/recipes/disassociate_recipe_as_input.yaml +16 -0
  22. type_spec/external/api/recipes/edit_recipe_inputs.yaml +86 -0
  23. type_spec/external/api/recipes/get_curve.yaml +4 -1
  24. type_spec/external/api/recipes/get_recipes_data.yaml +6 -0
  25. type_spec/external/api/recipes/set_recipe_metadata.yaml +1 -0
  26. type_spec/external/api/recipes/set_recipe_tags.yaml +62 -0
  27. uncountable/core/__init__.py +3 -1
  28. uncountable/core/async_batch.py +22 -0
  29. uncountable/core/client.py +84 -10
  30. uncountable/core/file_upload.py +95 -0
  31. uncountable/core/types.py +22 -0
  32. uncountable/types/__init__.py +18 -0
  33. uncountable/types/api/entity/create_entities.py +1 -1
  34. uncountable/types/api/entity/create_entity.py +1 -1
  35. uncountable/types/api/entity/transition_entity_phase.py +66 -0
  36. uncountable/types/api/permissions/__init__.py +1 -0
  37. uncountable/types/api/permissions/set_core_permissions.py +89 -0
  38. uncountable/types/api/recipes/associate_recipe_as_input.py +4 -3
  39. uncountable/types/api/recipes/create_recipe.py +1 -1
  40. uncountable/types/api/recipes/disassociate_recipe_as_input.py +35 -0
  41. uncountable/types/api/recipes/edit_recipe_inputs.py +106 -0
  42. uncountable/types/api/recipes/get_curve.py +2 -1
  43. uncountable/types/api/recipes/get_recipes_data.py +2 -0
  44. uncountable/types/api/recipes/set_recipe_tags.py +91 -0
  45. uncountable/types/async_batch.py +10 -0
  46. uncountable/types/async_batch_processor.py +154 -0
  47. uncountable/types/client_base.py +113 -48
  48. uncountable/types/identifier.py +3 -3
  49. uncountable/types/permissions.py +46 -0
  50. uncountable/types/post_base.py +30 -0
  51. uncountable/types/recipe_inputs.py +30 -0
  52. uncountable/types/recipe_metadata.py +2 -0
  53. uncountable/types/recipe_workflow_steps.py +77 -0
  54. {UncountablePythonSDK-0.0.20.dist-info → UncountablePythonSDK-0.0.22.dist-info}/WHEEL +0 -0
  55. {UncountablePythonSDK-0.0.20.dist-info → UncountablePythonSDK-0.0.22.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,106 @@
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 pkgs.strenum_compat import StrEnum
11
+ from dataclasses import dataclass
12
+ from pkgs.serialization import serial_class
13
+ from ... import identifier as identifier_t
14
+ from ... import recipe_inputs as recipe_inputs_t
15
+ from ... import recipe_workflow_steps as recipe_workflow_steps_t
16
+
17
+ __all__: list[str] = [
18
+ "Arguments",
19
+ "Data",
20
+ "ENDPOINT_METHOD",
21
+ "ENDPOINT_PATH",
22
+ "RecipeInputEdit",
23
+ "RecipeInputEditAddInput",
24
+ "RecipeInputEditBase",
25
+ "RecipeInputEditClearInputs",
26
+ "RecipeInputEditInputBase",
27
+ "RecipeInputEditType",
28
+ "RecipeInputEditUpsertInput",
29
+ ]
30
+
31
+ ENDPOINT_METHOD = "POST"
32
+ ENDPOINT_PATH = "api/external/recipes/edit_recipe_inputs"
33
+
34
+
35
+ # DO NOT MODIFY -- This file is generated by type_spec
36
+ class RecipeInputEditType(StrEnum):
37
+ CLEAR_INPUTS = "clear_inputs"
38
+ UPSERT_INPUT = "upsert_input"
39
+ ADD_INPUT = "add_input"
40
+
41
+
42
+ # DO NOT MODIFY -- This file is generated by type_spec
43
+ @dataclass(kw_only=True)
44
+ class RecipeInputEditBase:
45
+ type: RecipeInputEditType
46
+
47
+
48
+ # DO NOT MODIFY -- This file is generated by type_spec
49
+ @serial_class(
50
+ parse_require={"type"},
51
+ )
52
+ @dataclass(kw_only=True)
53
+ class RecipeInputEditClearInputs(RecipeInputEditBase):
54
+ type: typing.Literal[RecipeInputEditType.CLEAR_INPUTS] = RecipeInputEditType.CLEAR_INPUTS
55
+
56
+
57
+ # DO NOT MODIFY -- This file is generated by type_spec
58
+ @serial_class(
59
+ to_string_values={"value_numeric"},
60
+ )
61
+ @dataclass(kw_only=True)
62
+ class RecipeInputEditInputBase(RecipeInputEditBase):
63
+ ingredient_key: identifier_t.IdentifierKey
64
+ quantity_basis: recipe_inputs_t.QuantityBasis = recipe_inputs_t.QuantityBasis.MASS
65
+ input_value_type: recipe_inputs_t.InputValueType = recipe_inputs_t.InputValueType.VALUE
66
+ value_numeric: typing.Optional[Decimal] = None
67
+ value_str: typing.Optional[str] = None
68
+ calculation_key: typing.Optional[identifier_t.IdentifierKey] = None
69
+
70
+
71
+ # DO NOT MODIFY -- This file is generated by type_spec
72
+ @serial_class(
73
+ parse_require={"type"},
74
+ )
75
+ @dataclass(kw_only=True)
76
+ class RecipeInputEditUpsertInput(RecipeInputEditInputBase):
77
+ type: typing.Literal[RecipeInputEditType.UPSERT_INPUT] = RecipeInputEditType.UPSERT_INPUT
78
+ clear_first: bool
79
+
80
+
81
+ # DO NOT MODIFY -- This file is generated by type_spec
82
+ @serial_class(
83
+ parse_require={"type"},
84
+ )
85
+ @dataclass(kw_only=True)
86
+ class RecipeInputEditAddInput(RecipeInputEditInputBase):
87
+ type: typing.Literal[RecipeInputEditType.ADD_INPUT] = RecipeInputEditType.ADD_INPUT
88
+
89
+
90
+ # DO NOT MODIFY -- This file is generated by type_spec
91
+ RecipeInputEdit = typing.Union[RecipeInputEditClearInputs, RecipeInputEditUpsertInput, RecipeInputEditAddInput]
92
+
93
+
94
+ # DO NOT MODIFY -- This file is generated by type_spec
95
+ @dataclass(kw_only=True)
96
+ class Arguments:
97
+ recipe_key: identifier_t.IdentifierKey
98
+ recipe_workflow_step_identifier: recipe_workflow_steps_t.RecipeWorkflowStepIdentifier
99
+ edits: list[RecipeInputEdit]
100
+
101
+
102
+ # DO NOT MODIFY -- This file is generated by type_spec
103
+ @dataclass(kw_only=True)
104
+ class Data:
105
+ pass
106
+ # DO NOT MODIFY -- This file is generated by type_spec
@@ -25,7 +25,8 @@ ENDPOINT_PATH = "api/external/recipes/external_get_curve"
25
25
  # DO NOT MODIFY -- This file is generated by type_spec
26
26
  @dataclass(kw_only=True)
27
27
  class Arguments:
28
- recipe_output_id: base_t.ObjectId
28
+ recipe_output_id: typing.Optional[base_t.ObjectId] = None
29
+ recipe_input_id: typing.Optional[base_t.ObjectId] = None
29
30
 
30
31
 
31
32
  # DO NOT MODIFY -- This file is generated by type_spec
@@ -90,11 +90,13 @@ class SimpleOutputCondition:
90
90
  )
91
91
  @dataclass(kw_only=True)
92
92
  class RecipeInput:
93
+ id: base_t.ObjectId
93
94
  input_id: base_t.ObjectId
94
95
  input_lot_recipe_id: typing.Optional[base_t.ObjectId]
95
96
  recipe_step_id: base_t.ObjectId
96
97
  quantity_dec: Decimal
97
98
  quantity_json: base_t.JsonValue
99
+ curve_id: typing.Optional[base_t.ObjectId]
98
100
  actual_quantity_dec: Decimal
99
101
  actual_quantity_json: base_t.JsonValue
100
102
  input_type: str
@@ -0,0 +1,91 @@
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 pkgs.strenum_compat import StrEnum
11
+ from dataclasses import dataclass
12
+ from pkgs.serialization import serial_class
13
+ from ... import base as base_t
14
+ from ... import identifier as identifier_t
15
+
16
+ __all__: list[str] = [
17
+ "Arguments",
18
+ "Data",
19
+ "ENDPOINT_METHOD",
20
+ "ENDPOINT_PATH",
21
+ "RecipeTagAppend",
22
+ "RecipeTagOverride",
23
+ "RecipeTagRemove",
24
+ "RecipeTagUpdate",
25
+ "RecipeTagUpdateBase",
26
+ "RecipeTagUpdateType",
27
+ ]
28
+
29
+ ENDPOINT_METHOD = "POST"
30
+ ENDPOINT_PATH = "api/external/recipes/set_recipe_tags"
31
+
32
+
33
+ # DO NOT MODIFY -- This file is generated by type_spec
34
+ class RecipeTagUpdateType(StrEnum):
35
+ APPEND = "append"
36
+ OVERRIDE = "override"
37
+ REMOVE = "remove"
38
+
39
+
40
+ # DO NOT MODIFY -- This file is generated by type_spec
41
+ @dataclass(kw_only=True)
42
+ class RecipeTagUpdateBase:
43
+ type: RecipeTagUpdateType
44
+
45
+
46
+ # DO NOT MODIFY -- This file is generated by type_spec
47
+ @serial_class(
48
+ parse_require={"type"},
49
+ )
50
+ @dataclass(kw_only=True)
51
+ class RecipeTagAppend(RecipeTagUpdateBase):
52
+ type: typing.Literal[RecipeTagUpdateType.APPEND] = RecipeTagUpdateType.APPEND
53
+ recipe_tag_ids: list[base_t.ObjectId]
54
+
55
+
56
+ # DO NOT MODIFY -- This file is generated by type_spec
57
+ @serial_class(
58
+ parse_require={"type"},
59
+ )
60
+ @dataclass(kw_only=True)
61
+ class RecipeTagRemove(RecipeTagUpdateBase):
62
+ type: typing.Literal[RecipeTagUpdateType.REMOVE] = RecipeTagUpdateType.REMOVE
63
+ recipe_tag_ids: list[base_t.ObjectId]
64
+
65
+
66
+ # DO NOT MODIFY -- This file is generated by type_spec
67
+ @serial_class(
68
+ parse_require={"type"},
69
+ )
70
+ @dataclass(kw_only=True)
71
+ class RecipeTagOverride(RecipeTagUpdateBase):
72
+ type: typing.Literal[RecipeTagUpdateType.OVERRIDE] = RecipeTagUpdateType.OVERRIDE
73
+ recipe_tag_ids: list[base_t.ObjectId]
74
+
75
+
76
+ # DO NOT MODIFY -- This file is generated by type_spec
77
+ RecipeTagUpdate = typing.Union[RecipeTagAppend, RecipeTagRemove, RecipeTagOverride]
78
+
79
+
80
+ # DO NOT MODIFY -- This file is generated by type_spec
81
+ @dataclass(kw_only=True)
82
+ class Arguments:
83
+ recipe_key: identifier_t.IdentifierKey
84
+ recipe_tag_update: RecipeTagUpdate
85
+
86
+
87
+ # DO NOT MODIFY -- This file is generated by type_spec
88
+ @dataclass(kw_only=True)
89
+ class Data:
90
+ pass
91
+ # DO NOT MODIFY -- This file is generated by type_spec
@@ -16,6 +16,7 @@ __all__: list[str] = [
16
16
  "AsyncBatchActionReturn",
17
17
  "AsyncBatchRequest",
18
18
  "AsyncBatchRequestPath",
19
+ "QueuedAsyncBatchRequest",
19
20
  ]
20
21
 
21
22
 
@@ -23,6 +24,8 @@ __all__: list[str] = [
23
24
  class AsyncBatchRequestPath(StrEnum):
24
25
  CREATE_RECIPE = "recipes/create_recipe"
25
26
  SET_RECIPE_METADATA = "recipes/set_recipe_metadata"
27
+ SET_RECIPE_TAGS = "recipes/set_recipe_tags"
28
+ EDIT_RECIPE_INPUTS = "recipes/edit_recipe_inputs"
26
29
 
27
30
 
28
31
  # DO NOT MODIFY -- This file is generated by type_spec
@@ -42,4 +45,11 @@ class AsyncBatchRequest:
42
45
  class AsyncBatchActionReturn:
43
46
  modification_made: bool
44
47
  result_id: typing.Optional[base_t.ObjectId] = None
48
+
49
+
50
+ # DO NOT MODIFY -- This file is generated by type_spec
51
+ @dataclass(kw_only=True, frozen=True, eq=True)
52
+ class QueuedAsyncBatchRequest:
53
+ path: AsyncBatchRequestPath
54
+ batch_reference: str
45
55
  # DO NOT MODIFY -- This file is generated by type_spec
@@ -0,0 +1,154 @@
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
+ # ruff: noqa: PLR0904
7
+ from __future__ import annotations
8
+ import typing # noqa: F401
9
+ import datetime # noqa: F401
10
+ from decimal import Decimal # noqa: F401
11
+ from uncountable.types import async_batch as async_batch_t
12
+ from uncountable.types import base as base_t
13
+ import uncountable.types.api.recipes.create_recipe as create_recipe_t
14
+ import uncountable.types.api.recipes.edit_recipe_inputs as edit_recipe_inputs_t
15
+ from uncountable.types import identifier as identifier_t
16
+ from uncountable.types import recipe_identifiers as recipe_identifiers_t
17
+ from uncountable.types import recipe_metadata as recipe_metadata_t
18
+ from uncountable.types import recipe_workflow_steps as recipe_workflow_steps_t
19
+ import uncountable.types.api.recipes.set_recipe_metadata as set_recipe_metadata_t
20
+ import uuid
21
+ from abc import ABC, abstractmethod
22
+ from dataclasses import dataclass
23
+ from pkgs.serialization_util.serialization_helpers import serialize_for_api
24
+
25
+
26
+ class AsyncBatchProcessorBase(ABC):
27
+ @abstractmethod
28
+ def _enqueue(self, req: async_batch_t.AsyncBatchRequest) -> None:
29
+ ...
30
+
31
+ @abstractmethod
32
+ def send(self) -> base_t.ObjectId:
33
+ ...
34
+
35
+ def create_recipe(
36
+ self,
37
+ *,
38
+ material_family_id: base_t.ObjectId,
39
+ workflow_id: base_t.ObjectId,
40
+ name: typing.Optional[str] = None,
41
+ workflow_variant_id: typing.Optional[typing.Optional[base_t.ObjectId]] = None,
42
+ recipe_metadata: typing.Optional[list[recipe_metadata_t.MetadataValue]] = None,
43
+ identifiers: typing.Optional[recipe_identifiers_t.RecipeIdentifiers] = None,
44
+ definition_key: typing.Optional[identifier_t.IdentifierKey] = None,
45
+ depends_on: typing.Optional[list[str]] = None,
46
+ ) -> async_batch_t.QueuedAsyncBatchRequest:
47
+ """Returns the id of the recipe being created.
48
+
49
+ :param name: The name for the recipe
50
+ :param material_family_id: The material family for the recipe
51
+ :param workflow_id: The identifier of the workflow to create the recipe with
52
+ :param workflow_variant_id: The identifier of the workflow variant to create the recipe with
53
+ :param recipe_metadata: Metadata values to populate the recipe with
54
+ :param identifiers: A recipe won't be created if it matches the identifier. An identifier must be unique in the schema
55
+ :param definition_key: The entity definition identifier, default is used if not supplied
56
+ :param depends_on: A list of batch reference keys to process before processing this request
57
+ """
58
+ args = create_recipe_t.Arguments(
59
+ name=name,
60
+ material_family_id=material_family_id,
61
+ workflow_id=workflow_id,
62
+ workflow_variant_id=workflow_variant_id,
63
+ recipe_metadata=recipe_metadata,
64
+ identifiers=identifiers,
65
+ definition_key=definition_key,
66
+ )
67
+ json_data = serialize_for_api(args)
68
+
69
+ batch_reference = str(uuid.uuid4())
70
+
71
+ req = async_batch_t.AsyncBatchRequest(
72
+ path=async_batch_t.AsyncBatchRequestPath.CREATE_RECIPE,
73
+ data=json_data,
74
+ depends_on=depends_on,
75
+ batch_reference=batch_reference,
76
+ )
77
+
78
+ self._enqueue(req)
79
+
80
+ return async_batch_t.QueuedAsyncBatchRequest(
81
+ path=req.path,
82
+ batch_reference=req.batch_reference,
83
+ )
84
+
85
+ def edit_recipe_inputs(
86
+ self,
87
+ *,
88
+ recipe_key: identifier_t.IdentifierKey,
89
+ recipe_workflow_step_identifier: recipe_workflow_steps_t.RecipeWorkflowStepIdentifier,
90
+ edits: list[edit_recipe_inputs_t.RecipeInputEdit],
91
+ depends_on: typing.Optional[list[str]] = None,
92
+ ) -> async_batch_t.QueuedAsyncBatchRequest:
93
+ """Clear, update, or add inputs on a recipe
94
+
95
+ :param recipe_key: Identifier for the recipe
96
+ :param depends_on: A list of batch reference keys to process before processing this request
97
+ """
98
+ args = edit_recipe_inputs_t.Arguments(
99
+ recipe_key=recipe_key,
100
+ recipe_workflow_step_identifier=recipe_workflow_step_identifier,
101
+ edits=edits,
102
+ )
103
+ json_data = serialize_for_api(args)
104
+
105
+ batch_reference = str(uuid.uuid4())
106
+
107
+ req = async_batch_t.AsyncBatchRequest(
108
+ path=async_batch_t.AsyncBatchRequestPath.EDIT_RECIPE_INPUTS,
109
+ data=json_data,
110
+ depends_on=depends_on,
111
+ batch_reference=batch_reference,
112
+ )
113
+
114
+ self._enqueue(req)
115
+
116
+ return async_batch_t.QueuedAsyncBatchRequest(
117
+ path=req.path,
118
+ batch_reference=req.batch_reference,
119
+ )
120
+
121
+ def set_recipe_metadata(
122
+ self,
123
+ *,
124
+ recipe_key: identifier_t.IdentifierKey,
125
+ recipe_metadata: list[recipe_metadata_t.MetadataValue],
126
+ depends_on: typing.Optional[list[str]] = None,
127
+ ) -> async_batch_t.QueuedAsyncBatchRequest:
128
+ """Set metadata values on a recipe
129
+
130
+ :param recipe_key: Identifier for the recipe
131
+ :param recipe_metadata: Metadata values to populate the recipe with
132
+ :param depends_on: A list of batch reference keys to process before processing this request
133
+ """
134
+ args = set_recipe_metadata_t.Arguments(
135
+ recipe_key=recipe_key,
136
+ recipe_metadata=recipe_metadata,
137
+ )
138
+ json_data = serialize_for_api(args)
139
+
140
+ batch_reference = str(uuid.uuid4())
141
+
142
+ req = async_batch_t.AsyncBatchRequest(
143
+ path=async_batch_t.AsyncBatchRequestPath.SET_RECIPE_METADATA,
144
+ data=json_data,
145
+ depends_on=depends_on,
146
+ batch_reference=batch_reference,
147
+ )
148
+
149
+ self._enqueue(req)
150
+
151
+ return async_batch_t.QueuedAsyncBatchRequest(
152
+ path=req.path,
153
+ batch_reference=req.batch_reference,
154
+ )