UncountablePythonSDK 0.0.16__py3-none-any.whl → 0.0.18__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 (81) hide show
  1. {UncountablePythonSDK-0.0.16.dist-info → UncountablePythonSDK-0.0.18.dist-info}/METADATA +14 -1
  2. {UncountablePythonSDK-0.0.16.dist-info → UncountablePythonSDK-0.0.18.dist-info}/RECORD +81 -33
  3. {UncountablePythonSDK-0.0.16.dist-info → UncountablePythonSDK-0.0.18.dist-info}/top_level.txt +1 -0
  4. docs/.gitignore +1 -0
  5. docs/conf.py +52 -0
  6. docs/index.md +13 -0
  7. docs/justfile +12 -0
  8. docs/quickstart.md +19 -0
  9. docs/requirements.txt +7 -0
  10. docs/static/favicons/android-chrome-192x192.png +0 -0
  11. docs/static/favicons/android-chrome-512x512.png +0 -0
  12. docs/static/favicons/apple-touch-icon.png +0 -0
  13. docs/static/favicons/browserconfig.xml +9 -0
  14. docs/static/favicons/favicon-16x16.png +0 -0
  15. docs/static/favicons/favicon-32x32.png +0 -0
  16. docs/static/favicons/manifest.json +18 -0
  17. docs/static/favicons/mstile-150x150.png +0 -0
  18. docs/static/favicons/safari-pinned-tab.svg +32 -0
  19. docs/static/logo_blue.png +0 -0
  20. examples/create_entity.py +23 -16
  21. pkgs/argument_parser/_is_enum.py +1 -1
  22. pkgs/argument_parser/argument_parser.py +26 -19
  23. pkgs/serialization/serial_class.py +3 -3
  24. pkgs/serialization_util/_get_type_for_serialization.py +1 -3
  25. pkgs/serialization_util/serialization_helpers.py +1 -3
  26. pkgs/strenum_compat/strenum_compat.py +1 -9
  27. pkgs/type_spec/actions_registry/__init__.py +0 -0
  28. pkgs/type_spec/actions_registry/__main__.py +114 -0
  29. pkgs/type_spec/actions_registry/emit_typescript.py +120 -0
  30. pkgs/type_spec/builder.py +14 -10
  31. pkgs/type_spec/config.py +3 -2
  32. pkgs/type_spec/emit_python.py +54 -17
  33. pkgs/type_spec/emit_typescript.py +8 -9
  34. pkgs/type_spec/emit_typescript_util.py +1 -2
  35. pkgs/type_spec/load_types.py +2 -1
  36. pkgs/type_spec/open_api_util.py +2 -2
  37. pkgs/type_spec/parts/base.py.prepart +2 -1
  38. pkgs/type_spec/util.py +9 -9
  39. pkgs/type_spec/value_spec/__main__.py +2 -2
  40. pkgs/type_spec/value_spec/emit_python.py +1 -0
  41. type_spec/external/api/batch/execute_batch_load_async.yaml +18 -0
  42. type_spec/external/api/chemical/convert_chemical_formats.yaml +33 -0
  43. type_spec/external/api/entity/create_entities.yaml +1 -1
  44. type_spec/external/api/entity/create_entity.yaml +1 -1
  45. type_spec/external/api/id_source/list_id_source.yaml +35 -0
  46. type_spec/external/api/id_source/match_id_source.yaml +32 -0
  47. type_spec/external/api/recipe_links/create_recipe_link.yaml +25 -0
  48. type_spec/external/api/recipes/associate_recipe_as_input.yaml +19 -0
  49. type_spec/external/api/recipes/associate_recipe_as_lot.yaml +19 -0
  50. type_spec/external/api/recipes/create_recipe.yaml +38 -0
  51. type_spec/external/api/recipes/get_recipes_data.yaml +21 -21
  52. type_spec/external/api/recipes/set_recipe_inputs.yaml +6 -0
  53. type_spec/external/api/recipes/set_recipe_metadata.yaml +19 -0
  54. type_spec/external/api/triggers/run_trigger.yaml +18 -0
  55. uncountable/core/client.py +13 -14
  56. uncountable/types/__init__.py +30 -0
  57. uncountable/types/api/batch/execute_batch_load_async.py +35 -0
  58. uncountable/types/api/chemical/__init__.py +1 -0
  59. uncountable/types/api/chemical/convert_chemical_formats.py +50 -0
  60. uncountable/types/api/entity/create_entities.py +1 -1
  61. uncountable/types/api/entity/create_entity.py +1 -1
  62. uncountable/types/api/id_source/__init__.py +1 -0
  63. uncountable/types/api/id_source/list_id_source.py +46 -0
  64. uncountable/types/api/id_source/match_id_source.py +48 -0
  65. uncountable/types/api/recipe_links/__init__.py +1 -0
  66. uncountable/types/api/recipe_links/create_recipe_link.py +39 -0
  67. uncountable/types/api/recipes/associate_recipe_as_input.py +35 -0
  68. uncountable/types/api/recipes/associate_recipe_as_lot.py +36 -0
  69. uncountable/types/api/recipes/create_recipe.py +43 -0
  70. uncountable/types/api/recipes/set_recipe_inputs.py +2 -0
  71. uncountable/types/api/recipes/set_recipe_metadata.py +36 -0
  72. uncountable/types/api/triggers/__init__.py +1 -0
  73. uncountable/types/api/triggers/run_trigger.py +36 -0
  74. uncountable/types/async_batch.py +45 -0
  75. uncountable/types/base.py +2 -1
  76. uncountable/types/chemical_structure.py +27 -0
  77. uncountable/types/client_base.py +404 -2
  78. uncountable/types/id_source.py +49 -0
  79. uncountable/types/identifier.py +54 -0
  80. uncountable/types/recipe_identifiers.py +62 -0
  81. {UncountablePythonSDK-0.0.16.dist-info → UncountablePythonSDK-0.0.18.dist-info}/WHEEL +0 -0
pkgs/type_spec/util.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import json
2
2
  import os
3
3
  from dataclasses import dataclass
4
- from typing import Dict, List, Optional, TypeVar, Union
4
+ from typing import Optional, TypeVar, Union
5
5
 
6
6
  import regex as re
7
7
 
@@ -29,11 +29,11 @@ LiteralTypeValue = Union[str, bool]
29
29
  class ParsedTypePart:
30
30
  name: str
31
31
  # An empty list is distinct from None
32
- parameters: Optional[List["ParsedTypePath"]] = None
32
+ parameters: Optional[list["ParsedTypePath"]] = None
33
33
  literal_value: Optional[LiteralTypeValue] = None
34
34
 
35
35
 
36
- ParsedTypePath = List[ParsedTypePart]
36
+ ParsedTypePath = list[ParsedTypePart]
37
37
 
38
38
 
39
39
  @dataclass
@@ -48,7 +48,7 @@ def consume_parameter(
48
48
  ) -> ConsumedParameter:
49
49
  if bits[at] != "'":
50
50
  return ConsumedParameter(at=at, part=ParsedTypePart(name=bits[at]))
51
- quote_stack: List[str] = []
51
+ quote_stack: list[str] = []
52
52
  at += 1
53
53
  while at < len(bits):
54
54
  if bits[at] == "'":
@@ -68,7 +68,7 @@ def parse_type_str(type_str: str) -> ParsedTypePath:
68
68
  """
69
69
  IMPROVE: will not detect all errors yet, focuses on correct cases
70
70
  """
71
- raw_bits: List[str] = re.split(r"([.<>,'])", type_str)
71
+ raw_bits: list[str] = re.split(r"([.<>,'])", type_str)
72
72
  bits = [
73
73
  stripped_bit
74
74
  for stripped_bit in (padded_bit.strip() for padded_bit in raw_bits)
@@ -81,7 +81,7 @@ def parse_type_str(type_str: str) -> ParsedTypePath:
81
81
  cur_path = result
82
82
  cur_path.append(cur_part)
83
83
 
84
- path_stack: List[ParsedTypePath] = []
84
+ path_stack: list[ParsedTypePath] = []
85
85
 
86
86
  at = 1
87
87
  while at < len(bits):
@@ -156,19 +156,19 @@ def is_valid_property_name(name: str) -> bool:
156
156
  return re_pattern_property_name.match(name) is not None
157
157
 
158
158
 
159
- def check_fields(data: Dict[str, T], allowed: List[str]) -> None:
159
+ def check_fields(data: dict[str, T], allowed: list[str]) -> None:
160
160
  for key in data:
161
161
  if key not in allowed:
162
162
  raise Exception(f"unexpected-field: {key}")
163
163
 
164
164
 
165
- def split_any_name(name: str) -> List[str]:
165
+ def split_any_name(name: str) -> list[str]:
166
166
  """
167
167
  Splits a name on case and underscores.
168
168
  myName => [my, name]
169
169
  my_name => [my, name]
170
170
  """
171
- bits: List[str] = re_pattern_split_name.split(name)
171
+ bits: list[str] = re_pattern_split_name.split(name)
172
172
  return [s.lower() for s in filter(lambda x: x is not None and x != "_", bits)]
173
173
 
174
174
 
@@ -17,7 +17,7 @@ If null is allowed as a legitimate value, such as in conditionals like `if`, the
17
17
  """
18
18
 
19
19
  import sys
20
- from typing import Type, TypeVar, cast
20
+ from typing import TypeVar, cast
21
21
 
22
22
  import regex as re
23
23
  import yaml
@@ -177,7 +177,7 @@ def main() -> None:
177
177
  raise Exception(f"missing-{key}:{get_where()}")
178
178
  return cast(base_t.PureJsonValue, x)
179
179
 
180
- def get_as(node: base_t.PureJsonValue, key: str, type_: Type[TypeT]) -> TypeT:
180
+ def get_as(node: base_t.PureJsonValue, key: str, type_: type[TypeT]) -> TypeT:
181
181
  raw = get(node, key)
182
182
  assert isinstance(raw, type_)
183
183
 
@@ -22,6 +22,7 @@ def emit_functions(functions: list[value_spec_t.Function]) -> str:
22
22
  out.write(
23
23
  f"""{MODIFY_NOTICE}
24
24
  {LINT_HEADER}
25
+ import datetime
25
26
  from typing import cast, Union
26
27
 
27
28
  from decimal import Decimal
@@ -0,0 +1,18 @@
1
+ $endpoint:
2
+ is_sdk: true
3
+ method: post
4
+ path: ${external}/batch/execute_batch_load_async
5
+ function: main.site.app.external.batch.execute_batch_load_async.execute_batch_load_async
6
+ desc: Run multiple API calls via one request
7
+
8
+ Arguments:
9
+ type: Object
10
+ properties:
11
+ requests:
12
+ type: List<async_batch.AsyncBatchRequest>
13
+
14
+ Data:
15
+ type: Object
16
+ properties:
17
+ job_id:
18
+ type: ObjectId
@@ -0,0 +1,33 @@
1
+ $endpoint:
2
+ is_sdk: true
3
+ method: post
4
+ path: ${external}/chemical/convert_chemical_formats
5
+ function: main.site.app.external.chemical.convert_chemical_formats.convert_chemical_formats
6
+ desc: Converts chemical formats, into the format used by Uncountable and usable in other APIs for eg. set_input_attribute_values
7
+
8
+
9
+ ChemicalStructureFile:
10
+ type: Object
11
+ properties:
12
+ struct_file:
13
+ type: String
14
+ desc: Stringified chemical structure. MOL v2000/3000, SMILES, Part of SDF.
15
+
16
+ Arguments:
17
+ type: Object
18
+ properties:
19
+ source_chemical_structures:
20
+ type: List<ChemicalStructureFile>
21
+
22
+ UncountableChemicalStructure:
23
+ type: Alias
24
+ alias: Dict<String, JsonValue>
25
+ desc: Uncountable format for chemical structures compatible with set ingredient attributes api etc.
26
+
27
+ Data:
28
+ type: Object
29
+ properties:
30
+ chemical_structures:
31
+ type: List<UncountableChemicalStructure>
32
+ desc: The parsed chemical structures in the Uncountable format
33
+ convert_value: no_convert
@@ -19,7 +19,7 @@ Arguments:
19
19
  type: ObjectId
20
20
  desc: "Definition id for the entities to create"
21
21
  entity_type:
22
- type: Union<Literal<entity.EntityType.lab_request>, Literal<entity.EntityType.approval>, Literal<entity.EntityType.custom_entity>, Literal<entity.EntityType.task>, Literal<entity.EntityType.project>>
22
+ type: Union<Literal<entity.EntityType.lab_request>, Literal<entity.EntityType.approval>, Literal<entity.EntityType.custom_entity>, Literal<entity.EntityType.task>, Literal<entity.EntityType.project>, Literal<entity.EntityType.equipment>, Literal<entity.EntityType.inv_local_locations>>
23
23
  desc: "The type of the entities to create"
24
24
  entities_to_create:
25
25
  type: List<EntityToCreate>
@@ -26,7 +26,7 @@ Arguments:
26
26
  type: ObjectId
27
27
  desc: "Definition id of the entity to create"
28
28
  entity_type:
29
- type: Union<Literal<entity.EntityType.lab_request>, Literal<entity.EntityType.approval>, Literal<entity.EntityType.custom_entity>, Literal<entity.EntityType.task>, Literal<entity.EntityType.project>>
29
+ type: Union<Literal<entity.EntityType.lab_request>, Literal<entity.EntityType.approval>, Literal<entity.EntityType.custom_entity>, Literal<entity.EntityType.task>, Literal<entity.EntityType.project>, Literal<entity.EntityType.equipment>, Literal<entity.EntityType.inv_local_locations>>
30
30
  desc: "The type of the entities requested"
31
31
  field_values?:
32
32
  type: Optional<List<field_values.FieldRefNameValue>>
@@ -0,0 +1,35 @@
1
+ $endpoint:
2
+ is_sdk: true
3
+ method: get
4
+ path: ${external}/id_source/list_id_source
5
+ function: main.site.app.external.id_source.list_id_source.list_id_source
6
+ desc: "Lists id and label pairs"
7
+ Arguments:
8
+ type: Object
9
+ properties:
10
+ spec:
11
+ type: id_source.IdSourceSpec
12
+ desc: "The id source spec to use"
13
+ search_label:
14
+ type: String
15
+ desc: Text to search within the labels to search matches
16
+ offset?:
17
+ type: Optional<Integer>
18
+ desc: "Used for pagination. Pagination is done based on the sorting of the config"
19
+ limit?:
20
+ type: Optional<Integer>
21
+ desc: "The number of data points to return. If not filled in, it will be set to 100, and cannot be set higher than 100"
22
+
23
+ IdName:
24
+ type: Object
25
+ properties:
26
+ id:
27
+ type: Union<ObjectId,String>
28
+ name:
29
+ type: String
30
+
31
+ Data:
32
+ type: Object
33
+ properties:
34
+ results:
35
+ type: List<IdName>
@@ -0,0 +1,32 @@
1
+ $endpoint:
2
+ is_sdk: true
3
+ method: get
4
+ path: ${external}/id_source/match_id_source
5
+ function: main.site.app.external.id_source.match_id_source.match_id_source
6
+ desc: "Lists id and label pairs"
7
+ Arguments:
8
+ type: Object
9
+ properties:
10
+ spec:
11
+ type: id_source.IdSourceSpec
12
+ desc: "The id source spec to use"
13
+ names:
14
+ type: List<String>
15
+ desc: "The names to match with the id source. At most 10 are allowed at a time"
16
+
17
+ Match:
18
+ type: Object
19
+ properties:
20
+ name:
21
+ type: String
22
+ desc: The name used to match
23
+ ids:
24
+ type: List<Union<ObjectId, String>>
25
+ desc: The list of matches
26
+
27
+ Data:
28
+ type: Object
29
+ properties:
30
+ results:
31
+ type: List<Match>
32
+ convert_value: no_convert
@@ -0,0 +1,25 @@
1
+ $endpoint:
2
+ is_sdk: true
3
+ method: post
4
+ path: ${external}/recipe_links/create_recipe_link
5
+ function: main.site.app.external.recipe_links.create_recipe_link.create_recipe_link
6
+ desc: Create a link between two recipes. Skip if the link already exists
7
+
8
+ Arguments:
9
+ type: Object
10
+ properties:
11
+ recipe_from_key:
12
+ type: identifier.IdentifierKey
13
+ desc: "Identifier for the recipe the link comes from"
14
+ recipe_to_key:
15
+ type: identifier.IdentifierKey
16
+ desc: "Identifier for the recipe the link goes to"
17
+ link_type:
18
+ type: Union<Literal<recipe_links.RecipeLinkType.child>, Literal<recipe_links.RecipeLinkType.control>, Literal<recipe_links.RecipeLinkType.user_link>>
19
+ desc: "The type of link being created"
20
+ name:
21
+ type: String
22
+ desc: "The name used for the link"
23
+
24
+ Data:
25
+ type: async_batch.AsyncBatchActionReturn
@@ -0,0 +1,19 @@
1
+ $endpoint:
2
+ is_sdk: true
3
+ method: post
4
+ path: ${external}/recipes/associate_recipe_as_input
5
+ function: main.site.app.external.recipes.associate_recipe_as_input.associate_recipe_as_input
6
+ desc: Create or return the input association for a recipe
7
+
8
+ Arguments:
9
+ type: Object
10
+ properties:
11
+ recipe_key:
12
+ type: identifier.IdentifierKey
13
+ desc: "Identifier for the recipe"
14
+
15
+ Data:
16
+ type: Object
17
+ properties:
18
+ result_id:
19
+ type: ObjectId
@@ -0,0 +1,19 @@
1
+ $endpoint:
2
+ is_sdk: true
3
+ method: post
4
+ path: ${external}/recipes/associate_recipe_as_lot
5
+ function: main.site.app.external.recipes.associate_recipe_as_lot.associate_recipe_as_lot
6
+ desc: Create a new lot association for the provided recipe with the provided ingredient
7
+
8
+ Arguments:
9
+ type: Object
10
+ properties:
11
+ recipe_key:
12
+ type: identifier.IdentifierKey
13
+ desc: "Identifier for the recipe"
14
+ ingredient_key:
15
+ type: identifier.IdentifierKey
16
+ desc: "Identifier for the ingredient"
17
+
18
+ Data:
19
+ type: async_batch.AsyncBatchActionReturn
@@ -0,0 +1,38 @@
1
+ $endpoint:
2
+ is_sdk: true
3
+ method: post
4
+ path: ${external}/recipes/create_recipe
5
+ function: main.site.app.external.recipes.create_recipe.create_recipe
6
+ desc: Returns the id of the recipe being created.
7
+
8
+
9
+ Arguments:
10
+ type: Object
11
+ properties:
12
+ name?:
13
+ type: String
14
+ desc: The name for the recipe
15
+ material_family_id:
16
+ type: ObjectId
17
+ desc: The material family for the recipe
18
+ workflow_id:
19
+ type: ObjectId
20
+ desc: The identifier of the workflow to create the recipe with
21
+ workflow_variant_id?:
22
+ type: Optional<ObjectId>
23
+ desc: The identifier of the workflow variant to create the recipe with
24
+ recipe_metadata?:
25
+ type: List<recipe_metadata.MetadataValue>
26
+ desc: Metadata values to populate the recipe with
27
+ identifiers:
28
+ type: recipe_identifiers.RecipeIdentifiers
29
+ desc: A recipe won't be created if it matches the identifier. An identifier must be unique in the schema
30
+ definition_key?:
31
+ type: identifier.IdentifierKey
32
+ desc: The entity definition identifier, default is used if not supplied
33
+
34
+ Data:
35
+ type: Object
36
+ properties:
37
+ result_id:
38
+ type: ObjectId
@@ -3,7 +3,7 @@ $endpoint:
3
3
  method: get
4
4
  path: ${external}/recipes/external_get_recipes_data
5
5
  function: main.site.app.external.recipes.get_recipes_data.get_recipes_data
6
- desc: "Gets all data associated with a set of recipes / experiments. 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"
6
+ desc: "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"
7
7
  Arguments:
8
8
  type: Object
9
9
  properties:
@@ -22,7 +22,7 @@ Arguments:
22
22
 
23
23
  RecipeOutput:
24
24
  type: Object
25
- desc: "A representation of a single measurement associated with a recipe / experiment within Uncountable system"
25
+ desc: "A representation of a single measurement associated with a recipe within Uncountable system"
26
26
  properties:
27
27
  id:
28
28
  type: ObjectId
@@ -113,7 +113,7 @@ RecipeStep:
113
113
  desc: "An optional name for the recipe step"
114
114
  recipe_step_id:
115
115
  type: ObjectId
116
- desc: "An ID value for the recipe step, used elsewhere to reference the part of the recipe / experiment that the input was placed in"
116
+ desc: "An ID value for the recipe step, used elsewhere to reference the part of the recipe that the input was placed in"
117
117
  recipe_step_number:
118
118
  type: Integer
119
119
  desc: "An ordering for the recipe step, allowing the user to determine the ordering of the steps"
@@ -126,24 +126,24 @@ RecipeStepGroup:
126
126
  properties:
127
127
  name:
128
128
  type: Optional<String>
129
- desc: "An optional name for the recipe step group. These names are on a per recipe basis, allowing users to individually name sub-components of recipes / experiments"
129
+ desc: "An optional name for the recipe step group. These names are on a per recipe basis, allowing users to individually name sub-components of recipes"
130
130
  recipe_steps:
131
131
  type: List<RecipeStep>
132
- desc: "A listing of recipe steps. Recipe Steps are the base component in Uncountables recipe structure, where inputs are directly placed"
132
+ desc: "A listing of recipe steps. Recipe Steps are the base component in Uncountable's recipe structure, where inputs are directly placed"
133
133
 
134
134
  RecipeWorkflowStep:
135
135
  type: Object
136
- desc: "A workflow step associated with a recipe / experiment. Workflow steps are comprised of recipe step groups, in turn comprised of recipe steps, where inputs are located. These groupings exists to give customers the ability to flexibly place inputs into the correct process ordering"
136
+ desc: "A workflow step associated with a recipe. Workflow steps are comprised of recipe step groups, in turn comprised of recipe steps, where inputs are located. These groupings exists to give customers the ability to flexibly place inputs into the correct process ordering"
137
137
  properties:
138
138
  recipe_workflow_step_id:
139
139
  type: ObjectId
140
140
  desc: "A unique reference for the workflow step within the recipe."
141
141
  workflow_step_id:
142
142
  type: ObjectId
143
- desc: "A reference to the workflow_step_id for the workflow. This will be shared across recipes / experiments, and can be used to do analysis about what part of a generic process inputs are located in."
143
+ desc: "A reference to the workflow_step_id for the workflow. This will be shared across recipes, and can be used to do analysis about what part of a generic process inputs are located in."
144
144
  recipe_step_groups:
145
145
  type: List<RecipeStepGroup>
146
- desc: "A listing of recipe step groups within the recipe / experiment"
146
+ desc: "A listing of recipe step groups within the recipe"
147
147
 
148
148
  RecipeStepRelationship:
149
149
  type: Object
@@ -172,46 +172,46 @@ Recipe:
172
172
  properties:
173
173
  recipe_id:
174
174
  type: ObjectId
175
- desc: "A unique identifier for the recipe / experiment. Used for joining elsewhere"
175
+ desc: "A unique identifier for the recipe. Used for joining elsewhere"
176
176
  creating_user_id?:
177
177
  type: ObjectId
178
- desc: "The user ID who originally created the recipe / experiment. Null when created from automated scripts, such as data transfers, or from the Uncountable implementation team."
178
+ desc: "The user ID who originally created the recipe. Null when created from automated scripts, such as data transfers, or from the Uncountable implementation team."
179
179
  create_datetime:
180
180
  type: String
181
- desc: "When the recipe / experiment was created"
181
+ desc: "When the recipe was created"
182
182
  last_modified_datetime:
183
183
  type: String
184
- desc: "when the recipe / experiment was last modified"
184
+ desc: "when the recipe was last modified"
185
185
  name:
186
186
  type: String
187
- desc: "The full name in the system of the recipe / experiment"
187
+ desc: "The full name in the system of the recipe"
188
188
  notes:
189
189
  type: Optional<String>
190
- desc: "Any notes associated with the recipe / experiment. This may be null if there are no notes present"
190
+ desc: "Any notes associated with the recipe. This may be null if there are no notes present"
191
191
  barcode_value?:
192
192
  type: String
193
193
  desc: "The value used in the barcoding system to lookup this experiment."
194
194
  workflow_id:
195
195
  type: ObjectId
196
- desc: "The workflow ID associated with the recipe / experiment. Workflows correspond to a set of experimental steps performed, and are referenced in the workflows return object"
196
+ desc: "The workflow ID associated with the recipe. Workflows correspond to a set of experimental steps performed, and are referenced in the workflows return object"
197
197
  metadata:
198
198
  type: List<recipe_metadata.RecipeMetadata>
199
- desc: "Metadata associated with a recipe / experimen. Metadata includes values that are neither ingredients nor process parameters, such as a location of an experiment"
199
+ desc: "Metadata associated with a recipe. Metadata includes values that are neither ingredients nor process parameters, such as a location of an experiment"
200
200
  inputs:
201
201
  type: List<RecipeInput>
202
- desc: "Inputs and quantities of those inputs associated with a recipe / experimen. Uncountable refers to inputs as either ingredients or process parameters."
202
+ desc: "Inputs and quantities of those inputs associated with a recipe. Uncountable refers to inputs as either ingredients or process parameters."
203
203
  outputs:
204
204
  type: List<RecipeOutput>
205
- desc: "Outputs and quantities of those outputs associated with a recipe / experimen. These can be of any form referred to in the Uncountable system."
205
+ desc: "Outputs and quantities of those outputs associated with a recipe. These can be of any form referred to in the Uncountable system."
206
206
  workflow_steps:
207
207
  type: List<RecipeWorkflowStep>
208
- desc: "A reference of workflow steps in the recipe / experimen. This is used to reference input values to where they occurred in the experimental process."
208
+ desc: "A reference of workflow steps in the recipe. This is used to reference input values to where they occurred in the experimental process."
209
209
  tag_ids:
210
210
  type: List<ObjectId>
211
- desc: A list of Tag IDs associated with the recipe / experiment
211
+ desc: A list of Tag IDs associated with the recipe
212
212
  experiment_group_ids:
213
213
  type: List<ObjectId>
214
- desc: A list of experiment group IDs associated with the recipe / experiment
214
+ desc: A list of experiment group IDs associated with the recipe
215
215
  step_relationships:
216
216
  type: List<RecipeStepRelationship>
217
217
 
@@ -25,6 +25,12 @@ RecipeInputValue:
25
25
  set_actual_value?:
26
26
  type: Boolean
27
27
  desc: "If True, modify the actual value for the input. If not provided or False, modify the set value for the input."
28
+ lot_recipe_id?:
29
+ type: ObjectId
30
+ desc: The recipe id for a lot to be associated to this recipe input. If the recipe is not a lot, it will be created as a lot.
31
+ remove?:
32
+ type: Boolean
33
+ desc: When true will remove the input from the recipe
28
34
 
29
35
  Arguments:
30
36
  type: Object
@@ -0,0 +1,19 @@
1
+ $endpoint:
2
+ is_sdk: true
3
+ method: post
4
+ path: ${external}/recipes/set_recipe_metadata
5
+ function: main.site.app.external.recipes.set_recipe_metadata.set_recipe_metadata
6
+ desc: "Set metadata values on a recipe"
7
+
8
+ Arguments:
9
+ type: Object
10
+ properties:
11
+ recipe_key:
12
+ type: identifier.IdentifierKey
13
+ desc: "Identifier for the recipe"
14
+ recipe_metadata:
15
+ type: List<recipe_metadata.MetadataValue>
16
+ desc: "Metadata values to populate the recipe with"
17
+
18
+ Data:
19
+ type: Object
@@ -0,0 +1,18 @@
1
+ $endpoint:
2
+ is_sdk: true
3
+ method: post
4
+ path: ${external}/triggers/run_trigger
5
+ function: main.site.app.external.triggers.run_trigger.run_trigger
6
+ desc: "Runs a trigger. Requires admin access"
7
+
8
+ Arguments:
9
+ type: Object
10
+ properties:
11
+ entity?:
12
+ type: entity.Entity
13
+ trigger_ref_name:
14
+ type: String
15
+
16
+ Data:
17
+ type: response.Response
18
+ properties:
@@ -1,15 +1,15 @@
1
+ import base64
2
+ import json
3
+ import typing
1
4
  from dataclasses import dataclass
2
5
  from enum import StrEnum
3
- import json
4
6
  from urllib.parse import urljoin
5
- import base64
6
- import typing
7
+
7
8
  import requests
8
- from uncountable.types.base import JsonValue
9
- from uncountable.types.client_base import APIRequest, ClientMethods
9
+
10
10
  from pkgs.argument_parser import CachedParser
11
11
  from pkgs.serialization_util import serialize_for_api
12
-
12
+ from uncountable.types.client_base import APIRequest, ClientMethods
13
13
 
14
14
  DT = typing.TypeVar("DT")
15
15
 
@@ -24,8 +24,8 @@ class HTTPRequestBase:
24
24
  method: EndpointMethod
25
25
  url: str
26
26
  headers: dict[str, str]
27
- body: typing.Optional[str] = None
28
- query_params: typing.Optional[dict[str, str]]
27
+ body: typing.Optional[typing.Union[str, dict[str, str]]] = None
28
+ query_params: typing.Optional[dict[str, str]] = None
29
29
 
30
30
 
31
31
  @dataclass(kw_only=True)
@@ -37,6 +37,7 @@ class HTTPGetRequest(HTTPRequestBase):
37
37
  @dataclass(kw_only=True)
38
38
  class HTTPPostRequest(HTTPRequestBase):
39
39
  method: typing.Literal[EndpointMethod.POST]
40
+ body: typing.Union[str, dict[str, str]]
40
41
 
41
42
 
42
43
  HTTPRequest = HTTPPostRequest | HTTPGetRequest
@@ -98,9 +99,7 @@ class Client(ClientMethods):
98
99
  match self._auth_details:
99
100
  case AuthDetailsApiKey():
100
101
  encoded = base64.standard_b64encode(
101
- f"{self._auth_details.api_id}:{self._auth_details.api_secret_key}".encode(
102
- "utf-8"
103
- )
102
+ f"{self._auth_details.api_id}:{self._auth_details.api_secret_key}".encode()
104
103
  ).decode("utf-8")
105
104
  return {"Authorization": f"Basic {encoded}"}
106
105
  typing.assert_never(self._auth_details)
@@ -108,21 +107,21 @@ class Client(ClientMethods):
108
107
  def _build_http_request(self, *, api_request: APIRequest) -> HTTPRequest:
109
108
  headers = self._build_auth_headers()
110
109
  method = api_request.method.lower()
111
- query_params = {"data": json.dumps(serialize_for_api(api_request.args))}
110
+ data = {"data": json.dumps(serialize_for_api(api_request.args))}
112
111
  match method:
113
112
  case "get":
114
113
  return HTTPGetRequest(
115
114
  method=EndpointMethod.GET,
116
115
  url=urljoin(self._base_url, api_request.endpoint),
117
- query_params=query_params,
116
+ query_params=data,
118
117
  headers=headers,
119
118
  )
120
119
  case "post":
121
120
  return HTTPPostRequest(
122
121
  method=EndpointMethod.POST,
123
122
  url=urljoin(self._base_url, api_request.endpoint),
123
+ body=data,
124
124
  headers=headers,
125
- query_params=query_params
126
125
  )
127
126
  case _:
128
127
  raise ValueError(f"unsupported request method: {method}")