UncountablePythonSDK 0.0.105__py3-none-any.whl → 0.0.110__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 (42) hide show
  1. docs/requirements.txt +2 -2
  2. pkgs/argument_parser/argument_parser.py +8 -8
  3. pkgs/filesystem_utils/_gdrive_session.py +1 -1
  4. pkgs/serialization/annotation.py +3 -3
  5. pkgs/serialization/missing_sentry.py +1 -1
  6. pkgs/serialization/serial_alias.py +2 -2
  7. pkgs/serialization/serial_class.py +1 -12
  8. pkgs/serialization/serial_generic.py +1 -1
  9. pkgs/serialization/serial_union.py +3 -3
  10. pkgs/serialization_util/serialization_helpers.py +4 -1
  11. pkgs/type_spec/config.py +5 -2
  12. pkgs/type_spec/cross_output_links.py +1 -1
  13. pkgs/type_spec/emit_open_api.py +27 -0
  14. pkgs/type_spec/emit_open_api_util.py +3 -3
  15. pkgs/type_spec/emit_python.py +1 -9
  16. pkgs/type_spec/open_api_util.py +12 -1
  17. pkgs/type_spec/type_info/emit_type_info.py +19 -2
  18. pkgs/type_spec/util.py +5 -3
  19. uncountable/integration/queue_runner/datastore/datastore_sqlite.py +1 -1
  20. uncountable/types/__init__.py +2 -0
  21. uncountable/types/api/entity/lookup_entity.py +0 -1
  22. uncountable/types/api/recipes/add_time_series_data.py +0 -1
  23. uncountable/types/api/recipes/edit_recipe_inputs.py +11 -2
  24. uncountable/types/api/recipes/get_recipe_links.py +0 -1
  25. uncountable/types/api/recipes/lock_recipes.py +0 -1
  26. uncountable/types/api/recipes/set_recipe_outputs.py +2 -1
  27. uncountable/types/api/recipes/unlock_recipes.py +0 -1
  28. uncountable/types/async_batch_t.py +1 -0
  29. uncountable/types/client_config_t.py +0 -1
  30. uncountable/types/data.py +12 -0
  31. uncountable/types/data_t.py +93 -0
  32. uncountable/types/entity_t.py +2 -2
  33. uncountable/types/field_values.py +3 -0
  34. uncountable/types/field_values_t.py +40 -3
  35. uncountable/types/generic_upload_t.py +0 -1
  36. uncountable/types/job_definition_t.py +0 -2
  37. uncountable/types/recipe_workflow_steps_t.py +0 -1
  38. uncountable/types/response_t.py +0 -1
  39. {uncountablepythonsdk-0.0.105.dist-info → uncountablepythonsdk-0.0.110.dist-info}/METADATA +2 -2
  40. {uncountablepythonsdk-0.0.105.dist-info → uncountablepythonsdk-0.0.110.dist-info}/RECORD +42 -40
  41. {uncountablepythonsdk-0.0.105.dist-info → uncountablepythonsdk-0.0.110.dist-info}/WHEEL +1 -1
  42. {uncountablepythonsdk-0.0.105.dist-info → uncountablepythonsdk-0.0.110.dist-info}/top_level.txt +0 -0
docs/requirements.txt CHANGED
@@ -1,8 +1,8 @@
1
1
  furo==2024.8.6
2
2
  myst-parser==4.0.0
3
- sphinx-autoapi==3.5.0
3
+ sphinx-autoapi==3.6.0
4
4
  sphinx-copybutton==0.5.2
5
- Sphinx==8.1.3
5
+ Sphinx==8.2.0
6
6
  sphinx_design==0.6.1
7
7
  sphinx-favicon==1.0.1
8
8
  astroid==3.3.8
@@ -115,7 +115,7 @@ def _get_field_default(
115
115
  return field.default_factory()
116
116
 
117
117
 
118
- def _invoke_tuple_parsers[T](
118
+ def _invoke_tuple_parsers(
119
119
  tuple_type: type[T],
120
120
  arg_parsers: typing.Sequence[typing.Callable[[typing.Any], object]],
121
121
  has_ellipsis: bool,
@@ -152,7 +152,7 @@ def _invoke_fallback_parsers(
152
152
  ) from ExceptionGroup("Fallback Parser Exception", exceptions)
153
153
 
154
154
 
155
- def _invoke_membership_parser[T](
155
+ def _invoke_membership_parser(
156
156
  expected_values: set[T],
157
157
  value: typing.Any,
158
158
  ) -> T:
@@ -167,7 +167,7 @@ def _invoke_membership_parser[T](
167
167
  raise ValueError(f"Expected value from {expected_values} but got value {value}")
168
168
 
169
169
 
170
- def _build_parser_discriminated_union[T](
170
+ def _build_parser_discriminated_union(
171
171
  context: ParserContext,
172
172
  discriminator: str,
173
173
  discriminator_map: dict[str, ParserFunction[T]],
@@ -189,7 +189,7 @@ def _build_parser_discriminated_union[T](
189
189
  return parse
190
190
 
191
191
 
192
- def _build_parser_inner[T](
192
+ def _build_parser_inner(
193
193
  parsed_type: type[T],
194
194
  context: ParserContext,
195
195
  ) -> ParserFunction[T]:
@@ -399,7 +399,7 @@ def _build_parser_inner[T](
399
399
  raise ValueError(f"Unhandled type {parsed_type}/{origin}")
400
400
 
401
401
 
402
- def _build_parser_dataclass[T](
402
+ def _build_parser_dataclass(
403
403
  parsed_type: type[T],
404
404
  context: ParserContext,
405
405
  ) -> ParserFunction[T]:
@@ -515,7 +515,7 @@ def _build_parser_dataclass[T](
515
515
  _CACHE_MAP: dict[ParserOptions, ParserCache] = defaultdict(ParserCache)
516
516
 
517
517
 
518
- def build_parser[T](
518
+ def build_parser(
519
519
  parsed_type: type[T],
520
520
  options: ParserOptions,
521
521
  ) -> ParserFunction[T]:
@@ -537,7 +537,7 @@ def build_parser[T](
537
537
  return built_parser
538
538
 
539
539
 
540
- class ParserBase[T](ABC):
540
+ class ParserBase(ABC, typing.Generic[T]):
541
541
  def parse_from_encoding(
542
542
  self,
543
543
  args: typing.Any,
@@ -568,7 +568,7 @@ class ParserBase[T](ABC):
568
568
  return self.parse_storage(yaml.safe_load(fp))
569
569
 
570
570
 
571
- class CachedParser[T](ParserBase[T]):
571
+ class CachedParser(ParserBase[T], typing.Generic[T]):
572
572
  def __init__(
573
573
  self,
574
574
  args: type[T],
@@ -63,7 +63,7 @@ def download_gdrive_file(
63
63
  downloader = MediaIoBaseDownload(file_handler, file_request)
64
64
  download_complete = False
65
65
  while not download_complete:
66
- status, download_complete = downloader.next_chunk()
66
+ _status, download_complete = downloader.next_chunk()
67
67
 
68
68
  file_handler.seek(0)
69
69
  file_data = file_handler.read()
@@ -16,7 +16,7 @@ class SerialBase:
16
16
  from_decorator: bool = False
17
17
 
18
18
 
19
- def get_serial_annotation[T](parsed_type: type[T]) -> SerialBase | None:
19
+ def get_serial_annotation(parsed_type: type[T]) -> SerialBase | None:
20
20
  if not hasattr(parsed_type, "__metadata__"):
21
21
  return None
22
22
  metadata = parsed_type.__metadata__ # type:ignore[attr-defined]
@@ -28,7 +28,7 @@ def get_serial_annotation[T](parsed_type: type[T]) -> SerialBase | None:
28
28
  return serial
29
29
 
30
30
 
31
- class SerialInspector[T]:
31
+ class SerialInspector(typing.Generic[T]):
32
32
  def __init__(self, parsed_type: type[T], serial_base: SerialBase) -> None:
33
33
  self._parsed_type = parsed_type
34
34
  self._serial_base = serial_base
@@ -53,7 +53,7 @@ class SerialInspector[T]:
53
53
  return self._serial_base.is_dynamic_allowed
54
54
 
55
55
 
56
- def unwrap_annotated[T](parsed_type: type[T]) -> type[T]:
56
+ def unwrap_annotated(parsed_type: type[T]) -> type[T]:
57
57
  """
58
58
  If the type is an annotated type then return the origin of it.
59
59
  Otherwise return the original type.
@@ -26,5 +26,5 @@ MISSING_SENTRY = MissingSentryType()
26
26
  MissingType = Union[MissingSentryType, ClassT]
27
27
 
28
28
 
29
- def coalesce_missing_sentry[ClassT](value: MissingType[ClassT]) -> ClassT | None:
29
+ def coalesce_missing_sentry(value: MissingType[ClassT]) -> ClassT | None:
30
30
  return None if isinstance(value, MissingSentryType) else value
@@ -26,7 +26,7 @@ def serial_alias_annotation(
26
26
  )
27
27
 
28
28
 
29
- def _get_serial_alias[T](parsed_type: type[T]) -> _SerialAlias | None:
29
+ def _get_serial_alias(parsed_type: type[T]) -> _SerialAlias | None:
30
30
  serial = get_serial_annotation(parsed_type)
31
31
  if not isinstance(serial, _SerialAlias):
32
32
  return None
@@ -39,7 +39,7 @@ class SerialAliasInspector(SerialInspector[T]):
39
39
  self._serial_alias = serial_alias
40
40
 
41
41
 
42
- def get_serial_alias_data[T](parsed_type: type[T]) -> SerialAliasInspector[T] | None:
42
+ def get_serial_alias_data(parsed_type: type[T]) -> SerialAliasInspector[T] | None:
43
43
  serial = _get_serial_alias(parsed_type)
44
44
  if serial is None:
45
45
  return None
@@ -17,7 +17,6 @@ class _SerialClassData(SerialBase):
17
17
  to_string_values: set[str] = dataclasses.field(default_factory=set)
18
18
  parse_require: set[str] = dataclasses.field(default_factory=set)
19
19
  named_type_path: str | None = None
20
- explicit_defaults: set[str] = dataclasses.field(default_factory=set)
21
20
 
22
21
 
23
22
  EMPTY_SERIAL_CLASS_DATA = _SerialClassData()
@@ -31,7 +30,6 @@ def serial_class(
31
30
  parse_require: set[str] | None = None,
32
31
  named_type_path: str | None = None,
33
32
  is_dynamic_allowed: bool = False,
34
- explicit_defaults: set[str] | None = None,
35
33
  ) -> Callable[[ClassT], ClassT]:
36
34
  """
37
35
  An additional decorator to a dataclass that specifies serialization options.
@@ -54,9 +52,6 @@ def serial_class(
54
52
  requiring them for the API input.
55
53
  @param named_type_path
56
54
  The type_spec type-path to this type. This applies only to named types.
57
- @param explicit_defaults
58
- Fields that have explicit defaults in the definition. This is useful for
59
- falling back onto these defaults when the field is mandatory but receives a null value.
60
55
  """
61
56
 
62
57
  def decorate(orig_class: ClassT) -> ClassT:
@@ -68,7 +63,6 @@ def serial_class(
68
63
  named_type_path=named_type_path,
69
64
  from_decorator=True,
70
65
  is_dynamic_allowed=is_dynamic_allowed,
71
- explicit_defaults=explicit_defaults or set(),
72
66
  )
73
67
  return orig_class
74
68
 
@@ -96,9 +90,6 @@ class SerialClassDataInspector(SerialInspector[ClassT]):
96
90
  def has_parse_require(self, key: str) -> bool:
97
91
  return key in self.current.parse_require
98
92
 
99
- def has_explicit_default(self, key: str) -> bool:
100
- return key in self.current.explicit_defaults
101
-
102
93
 
103
94
  def get_merged_serial_class_data(type_class: type[Any]) -> _SerialClassData | None:
104
95
  base_class_data = (
@@ -124,13 +115,11 @@ def get_merged_serial_class_data(type_class: type[Any]) -> _SerialClassData | No
124
115
  | curr_base_class_data.to_string_values,
125
116
  parse_require=base_class_data.parse_require
126
117
  | curr_base_class_data.parse_require,
127
- explicit_defaults=base_class_data.explicit_defaults
128
- | curr_base_class_data.explicit_defaults,
129
118
  )
130
119
  return base_class_data
131
120
 
132
121
 
133
- def get_serial_class_data[ClassT](
122
+ def get_serial_class_data(
134
123
  type_class: type[ClassT],
135
124
  ) -> SerialClassDataInspector[ClassT]:
136
125
  return SerialClassDataInspector(
@@ -6,7 +6,7 @@ from .serial_class import get_merged_serial_class_data
6
6
  T = typing.TypeVar("T")
7
7
 
8
8
 
9
- def get_serial_data[T](parsed_type: type[T]) -> SerialInspector[T] | None:
9
+ def get_serial_data(parsed_type: type[T]) -> SerialInspector[T] | None:
10
10
  serial = get_serial_annotation(parsed_type)
11
11
  if serial is None:
12
12
  serial = get_merged_serial_class_data(parsed_type)
@@ -6,7 +6,7 @@ from .annotation import SerialBase, SerialInspector, get_serial_annotation
6
6
  T = typing.TypeVar("T")
7
7
 
8
8
 
9
- class IdentityHashWrapper[T]:
9
+ class IdentityHashWrapper(typing.Generic[T]):
10
10
  """This allows unhashable types to be used in the SerialUnion, like dict.
11
11
  Since we have only one copy of the types themselves, we rely on
12
12
  object identity for the hashing."""
@@ -49,7 +49,7 @@ def serial_union_annotation(
49
49
  )
50
50
 
51
51
 
52
- def _get_serial_union[T](parsed_type: type[T]) -> _SerialUnion | None:
52
+ def _get_serial_union(parsed_type: type[T]) -> _SerialUnion | None:
53
53
  serial = get_serial_annotation(parsed_type)
54
54
  if not isinstance(serial, _SerialUnion):
55
55
  return None
@@ -76,7 +76,7 @@ class SerialClassInspector(SerialInspector[T]):
76
76
  return self._serial_union.discriminator_map.inner
77
77
 
78
78
 
79
- def get_serial_union_data[T](parsed_type: type[T]) -> SerialClassInspector[T] | None:
79
+ def get_serial_union_data(parsed_type: type[T]) -> SerialClassInspector[T] | None:
80
80
  serial = _get_serial_union(parsed_type)
81
81
  if serial is None:
82
82
  return None
@@ -12,6 +12,7 @@ from typing import (
12
12
  Any,
13
13
  ClassVar,
14
14
  Protocol,
15
+ TypeVar,
15
16
  Union,
16
17
  overload,
17
18
  )
@@ -33,12 +34,14 @@ if TYPE_CHECKING:
33
34
  else:
34
35
  JsonValue = Union[JsonScalar, dict[str, Any], list[Any]]
35
36
 
37
+ T = TypeVar("T")
38
+
36
39
 
37
40
  class Dataclass(Protocol):
38
41
  __dataclass_fields__: ClassVar[dict] # type: ignore[type-arg,unused-ignore]
39
42
 
40
43
 
41
- def identity[T](x: T) -> T:
44
+ def identity(x: T) -> T:
42
45
  return x
43
46
 
44
47
 
pkgs/type_spec/config.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import os
2
2
  from collections.abc import Callable, Mapping
3
3
  from dataclasses import dataclass
4
- from typing import Self
4
+ from typing import Self, TypeVar
5
5
 
6
6
  from pkgs.serialization import yaml
7
7
 
@@ -107,7 +107,10 @@ class Config:
107
107
  open_api: OpenAPIConfig | None
108
108
 
109
109
 
110
- def _parse_language[T](config_class: type[T], raw_value: ConfigValueType) -> T:
110
+ T = TypeVar("T")
111
+
112
+
113
+ def _parse_language(config_class: type[T], raw_value: ConfigValueType) -> T:
111
114
  assert isinstance(raw_value, dict), "expecting language config to have key/values."
112
115
  return config_class(**raw_value)
113
116
 
@@ -11,7 +11,7 @@ def get_python_stub_file_path(
11
11
  ) -> str | None:
12
12
  if function_name is None:
13
13
  return None
14
- module_dir, file_name, func_name = function_name.rsplit(".", 2)
14
+ module_dir, file_name, _func_name = function_name.rsplit(".", 2)
15
15
  module_path = os.path.relpath(module_dir.replace(".", "/"))
16
16
  api_stub_file = f"{module_path}/{file_name}.py"
17
17
  return api_stub_file
@@ -7,6 +7,7 @@ WORK-IN-PROGRESS, DON'T USE!
7
7
  import dataclasses
8
8
  import json
9
9
  import re
10
+ from enum import StrEnum
10
11
  from typing import Collection, assert_never, cast
11
12
 
12
13
  from pkgs.serialization import yaml
@@ -62,6 +63,10 @@ base_name_map = {
62
63
  }
63
64
 
64
65
 
66
+ class OpenAPIDefaultBehavior(StrEnum):
67
+ OPTIONAL_WITH_DEFAULT = "optional_with_default"
68
+
69
+
65
70
  def _rewrite_with_notice(
66
71
  file_path: str, file_content: str, *, notice: str = MODIFY_NOTICE
67
72
  ) -> bool:
@@ -432,6 +437,18 @@ def _emit_namespace(
432
437
  _rewrite_with_notice(path, yaml.dumps(oa_namespace, sort_keys=False))
433
438
 
434
439
 
440
+ def _get_openapi_default_behavior(
441
+ prop: builder.SpecProperty,
442
+ ) -> OpenAPIDefaultBehavior | None:
443
+ if prop.ext_info is None or prop.ext_info.get("open_api") is None:
444
+ return None
445
+ value_passed = prop.ext_info["open_api"].get("default_required_behavior")
446
+ if value_passed is None:
447
+ return None
448
+ assert isinstance(value_passed, str)
449
+ return OpenAPIDefaultBehavior(value_passed)
450
+
451
+
435
452
  def _emit_type(
436
453
  ctx: EmitOpenAPIContext,
437
454
  stype: builder.SpecType,
@@ -495,6 +512,16 @@ def _emit_type(
495
512
  # arguments, thus treat like extant==missing
496
513
  # IMPROVE: if we can decide they are meant as output instead, then
497
514
  # they should be marked as required
515
+ openapi_default_beahvior = _get_openapi_default_behavior(prop)
516
+ match openapi_default_beahvior:
517
+ case None:
518
+ pass
519
+ case OpenAPIDefaultBehavior.OPTIONAL_WITH_DEFAULT:
520
+ ref_type.nullable = True
521
+ assert prop.default is not None, (
522
+ "optional_with_default requires default"
523
+ )
524
+ ref_type.default = prop.default
498
525
  properties[prop_name] = ref_type
499
526
  elif prop.extant == builder.PropertyExtant.missing:
500
527
  # Unlike optional below, missing does not imply null is possible. They
@@ -14,9 +14,9 @@ from .open_api_util import OpenAPIType
14
14
 
15
15
  MODIFY_NOTICE = "# DO NOT MODIFY -- This file is generated by type_spec"
16
16
 
17
- type GlobalContextInfo = dict[str, str | dict[str, str]]
18
- type TagGroupToNamedTags = dict[str, str | list[str]]
19
- type TagPathsToRef = dict[str, dict[str, str]]
17
+ GlobalContextInfo = dict[str, str | dict[str, str]]
18
+ TagGroupToNamedTags = dict[str, str | list[str]]
19
+ TagPathsToRef = dict[str, dict[str, str]]
20
20
 
21
21
 
22
22
  @dataclass
@@ -697,7 +697,6 @@ class EmittedPropertiesMetadata:
697
697
  unconverted_values: set[str]
698
698
  to_string_values: set[str]
699
699
  parse_require: set[str]
700
- explicit_defaults: set[str]
701
700
 
702
701
 
703
702
  def _emit_type_properties(
@@ -729,7 +728,6 @@ def _emit_properties(
729
728
  unconverted_values: set[str] = set()
730
729
  to_string_values: set[str] = set()
731
730
  parse_require: set[str] = set()
732
- explicit_defaults: set[str] = set()
733
731
 
734
732
  if len(properties) > 0:
735
733
 
@@ -750,9 +748,6 @@ def _emit_properties(
750
748
  if prop.parse_require:
751
749
  parse_require.add(py_name)
752
750
 
753
- if prop.explicit_default:
754
- explicit_defaults.add(py_name)
755
-
756
751
  ref_type = refer_to(ctx, stype)
757
752
  default = None
758
753
  if prop.extant == builder.PropertyExtant.missing:
@@ -796,7 +791,6 @@ def _emit_properties(
796
791
  unconverted_values=unconverted_values,
797
792
  to_string_values=to_string_values,
798
793
  parse_require=parse_require,
799
- explicit_defaults=explicit_defaults,
800
794
  )
801
795
 
802
796
 
@@ -887,7 +881,6 @@ def _emit_type(ctx: Context, stype: builder.SpecType) -> None:
887
881
  unconverted_values = emitted_properties_metadata.unconverted_values
888
882
  to_string_values = emitted_properties_metadata.to_string_values
889
883
  parse_require = emitted_properties_metadata.parse_require
890
- explicit_defaults = emitted_properties_metadata.explicit_defaults
891
884
 
892
885
  _emit_generics(ctx, generics)
893
886
 
@@ -909,7 +902,6 @@ def _emit_type(ctx: Context, stype: builder.SpecType) -> None:
909
902
  write_values("unconverted_values", unconverted_values)
910
903
  write_values("to_string_values", to_string_values)
911
904
  write_values("parse_require", parse_require)
912
- write_values("explicit_defaults", explicit_defaults)
913
905
 
914
906
  ctx.out.write(")\n")
915
907
 
@@ -1192,7 +1184,7 @@ def _emit_api_stubs(*, builder: builder.SpecBuilder, config: PythonConfig) -> No
1192
1184
  if endpoint_function is None:
1193
1185
  continue
1194
1186
 
1195
- module_dir, file_name, func_name = endpoint_function.rsplit(".", 2)
1187
+ module_dir, file_name, _func_name = endpoint_function.rsplit(".", 2)
1196
1188
  module_path = os.path.abspath(module_dir.replace(".", "/"))
1197
1189
  api_stub_file = f"{module_path}/{file_name}.py"
1198
1190
  if os.path.isfile(api_stub_file):
@@ -1,14 +1,23 @@
1
1
  from abc import ABC, abstractmethod
2
2
  from enum import StrEnum
3
3
 
4
+ from pkgs.serialization_util import JsonValue
5
+
4
6
 
5
7
  class OpenAPIType(ABC):
6
8
  description: str | None = None
7
9
  nullable: bool = False
10
+ default: JsonValue
8
11
 
9
- def __init__(self, description: str | None = None, nullable: bool = False) -> None:
12
+ def __init__(
13
+ self,
14
+ description: str | None = None,
15
+ nullable: bool = False,
16
+ default: JsonValue = None,
17
+ ) -> None:
10
18
  self.description = description
11
19
  self.nullable = nullable
20
+ self.default = default
12
21
 
13
22
  @abstractmethod
14
23
  def asdict(self) -> dict[str, object]:
@@ -19,6 +28,8 @@ class OpenAPIType(ABC):
19
28
  emitted["description"] = self.description
20
29
  if self.nullable:
21
30
  emitted["nullable"] = self.nullable
31
+ if self.default is not None:
32
+ emitted["default"] = self.default
22
33
  return emitted
23
34
 
24
35
 
@@ -163,7 +163,7 @@ class MapStringEnum(MapTypeBase):
163
163
  values: dict[str, str]
164
164
 
165
165
 
166
- type MapType = MapTypeObject | MapTypeAlias | MapStringEnum
166
+ MapType = MapTypeObject | MapTypeAlias | MapStringEnum
167
167
 
168
168
 
169
169
  @dataclasses.dataclass
@@ -296,6 +296,21 @@ def _extract_and_validate_layout(
296
296
  return layout
297
297
 
298
298
 
299
+ def _pull_property_from_type_recursively(
300
+ stype: builder.SpecTypeDefnObject,
301
+ property_name: str,
302
+ ) -> builder.SpecProperty | None:
303
+ assert stype.properties is not None
304
+ prop = stype.properties.get(property_name)
305
+ if prop is not None:
306
+ return prop
307
+
308
+ if stype.base is None:
309
+ return None
310
+
311
+ return _pull_property_from_type_recursively(stype.base, property_name)
312
+
313
+
299
314
  def _validate_type_ext_info(
300
315
  stype: builder.SpecTypeDefnObject,
301
316
  ) -> tuple[ExtInfoLayout | None, type_info_t.ExtInfo | None]:
@@ -306,7 +321,7 @@ def _validate_type_ext_info(
306
321
  if ext_info.label_fields is not None:
307
322
  assert stype.properties is not None
308
323
  for name in ext_info.label_fields:
309
- prop = stype.properties.get(name)
324
+ prop = _pull_property_from_type_recursively(stype, name)
310
325
  assert prop is not None, f"missing-label-field:{name}"
311
326
 
312
327
  if not stype.is_base and isinstance(stype.base, builder.SpecTypeDefnObject):
@@ -416,6 +431,8 @@ def _parse_ext_info(in_ext: Any) -> type_info_t.ExtInfo | None:
416
431
  df["result_type"] = serialize_for_storage(converted)
417
432
  mod_ext["data_format"] = df
418
433
 
434
+ if "open_api" in mod_ext:
435
+ del mod_ext["open_api"]
419
436
  return ext_info_parser.parse_storage(mod_ext)
420
437
 
421
438
 
pkgs/type_spec/util.py CHANGED
@@ -1,10 +1,12 @@
1
1
  import json
2
2
  import os
3
3
  from dataclasses import dataclass
4
- from typing import Union
4
+ from typing import TypeVar, Union
5
5
 
6
6
  import regex as re
7
7
 
8
+ T = TypeVar("T")
9
+
8
10
 
9
11
  def rewrite_file(filename: str, content: str) -> bool:
10
12
  os.makedirs(os.path.dirname(filename), exist_ok=True)
@@ -154,7 +156,7 @@ def is_valid_property_name(name: str) -> bool:
154
156
  return re_pattern_property_name.match(name) is not None
155
157
 
156
158
 
157
- def check_fields[T](data: dict[str, T], allowed: list[str]) -> None:
159
+ def check_fields(data: dict[str, T], allowed: list[str]) -> None:
158
160
  for key in data:
159
161
  if key not in allowed:
160
162
  raise Exception(f"unexpected-field: {key}. Allowed: {allowed}")
@@ -178,7 +180,7 @@ def encode_common_string(value: str) -> str:
178
180
  return rep
179
181
 
180
182
 
181
- def unused[T](_arg: T) -> None:
183
+ def unused(_arg: T) -> None:
182
184
  """
183
185
  Identifies that an argument is intended not be used, as opposed to
184
186
  simply forgotten, or a remnant. This can happen in patterned calls
@@ -56,7 +56,7 @@ class DatastoreSqlite(Datastore):
56
56
  )
57
57
  session.execute(update_stmt)
58
58
  session.flush()
59
- # IMPROVE: python3.12's sqlite does not support the RETURNING clause
59
+ # IMPROVE: python3's sqlite does not support the RETURNING clause
60
60
  select_stmt = select(QueuedJob.num_attempts).filter(
61
61
  QueuedJob.id == queued_job_uuid
62
62
  )
@@ -25,6 +25,7 @@ from .api.recipes import create_recipe as create_recipe_t
25
25
  from .api.recipe_links import create_recipe_link as create_recipe_link_t
26
26
  from .api.recipes import create_recipes as create_recipes_t
27
27
  from . import curves_t as curves_t
28
+ from . import data_t as data_t
28
29
  from .api.recipes import disassociate_recipe_as_input as disassociate_recipe_as_input_t
29
30
  from .api.files import download_file as download_file_t
30
31
  from .api.recipes import edit_recipe_inputs as edit_recipe_inputs_t
@@ -136,6 +137,7 @@ __all__: list[str] = [
136
137
  "create_recipe_link_t",
137
138
  "create_recipes_t",
138
139
  "curves_t",
140
+ "data_t",
139
141
  "disassociate_recipe_as_input_t",
140
142
  "download_file_t",
141
143
  "edit_recipe_inputs_t",
@@ -50,7 +50,6 @@ class LookupEntityQueryBase:
50
50
  @serial_class(
51
51
  named_type_path="sdk.api.entity.lookup_entity.LookupFieldArgumentValue",
52
52
  unconverted_values={"field_value"},
53
- explicit_defaults={"value_resolution"},
54
53
  )
55
54
  @dataclasses.dataclass(kw_only=True)
56
55
  class LookupFieldArgumentValue:
@@ -45,7 +45,6 @@ class TimeSeriesDatum:
45
45
  # DO NOT MODIFY -- This file is generated by type_spec
46
46
  @serial_class(
47
47
  named_type_path="sdk.api.recipes.add_time_series_data.Arguments",
48
- explicit_defaults={"on_conflict"},
49
48
  )
50
49
  @dataclasses.dataclass(kw_only=True)
51
50
  class Arguments:
@@ -21,6 +21,7 @@ __all__: list[str] = [
21
21
  "Data",
22
22
  "ENDPOINT_METHOD",
23
23
  "ENDPOINT_PATH",
24
+ "MixStepMatchStrategy",
24
25
  "PlaceholderBase",
25
26
  "PlaceholderDisplayMode",
26
27
  "PlaceholderType",
@@ -58,6 +59,12 @@ class RecipeInputEditType(StrEnum):
58
59
  SET_PLACEHOLDER = "set_placeholder"
59
60
 
60
61
 
62
+ # DO NOT MODIFY -- This file is generated by type_spec
63
+ class MixStepMatchStrategy(StrEnum):
64
+ FIRST = "first"
65
+ LAST = "last"
66
+
67
+
61
68
  # DO NOT MODIFY -- This file is generated by type_spec
62
69
  @serial_class(
63
70
  named_type_path="sdk.api.recipes.edit_recipe_inputs.RecipeInputEditBase",
@@ -81,7 +88,6 @@ class RecipeInputEditClearInputs(RecipeInputEditBase):
81
88
  @serial_class(
82
89
  named_type_path="sdk.api.recipes.edit_recipe_inputs.RecipeInputEditInputBase",
83
90
  to_string_values={"value_numeric"},
84
- explicit_defaults={"input_value_type", "quantity_basis"},
85
91
  )
86
92
  @dataclasses.dataclass(kw_only=True)
87
93
  class RecipeInputEditInputBase(RecipeInputEditBase):
@@ -102,6 +108,7 @@ class RecipeInputEditInputBase(RecipeInputEditBase):
102
108
  @dataclasses.dataclass(kw_only=True)
103
109
  class RecipeInputEditChangeBasisViewed(RecipeInputEditInputBase):
104
110
  type: typing.Literal[RecipeInputEditType.CHANGE_BASIS] = RecipeInputEditType.CHANGE_BASIS
111
+ mix_step_match_strategy: MixStepMatchStrategy = MixStepMatchStrategy.FIRST
105
112
 
106
113
 
107
114
  # DO NOT MODIFY -- This file is generated by type_spec
@@ -113,6 +120,7 @@ class RecipeInputEditChangeBasisViewed(RecipeInputEditInputBase):
113
120
  class RecipeInputEditUpsertInput(RecipeInputEditInputBase):
114
121
  type: typing.Literal[RecipeInputEditType.UPSERT_INPUT] = RecipeInputEditType.UPSERT_INPUT
115
122
  clear_first: bool
123
+ mix_step_match_strategy: MixStepMatchStrategy = MixStepMatchStrategy.FIRST
116
124
 
117
125
 
118
126
  # DO NOT MODIFY -- This file is generated by type_spec
@@ -170,6 +178,7 @@ class RecipeInputEditUpdateAnnotations(RecipeInputEditInputBase):
170
178
  type: typing.Literal[RecipeInputEditType.UPDATE_ANNOTATIONS] = RecipeInputEditType.UPDATE_ANNOTATIONS
171
179
  clear_first: bool
172
180
  annotations: list[AnnotationEdit]
181
+ mix_step_match_strategy: MixStepMatchStrategy = MixStepMatchStrategy.FIRST
173
182
 
174
183
 
175
184
  # DO NOT MODIFY -- This file is generated by type_spec
@@ -197,7 +206,6 @@ class PlaceholderDisplayMode(StrEnum):
197
206
  # DO NOT MODIFY -- This file is generated by type_spec
198
207
  @serial_class(
199
208
  named_type_path="sdk.api.recipes.edit_recipe_inputs.PlaceholderBase",
200
- explicit_defaults={"display_mode", "require_for_creation"},
201
209
  )
202
210
  @dataclasses.dataclass(kw_only=True)
203
211
  class PlaceholderBase:
@@ -240,6 +248,7 @@ class RecipeInputEditPlaceholder(RecipeInputEditBase):
240
248
  type: typing.Literal[RecipeInputEditType.SET_PLACEHOLDER] = RecipeInputEditType.SET_PLACEHOLDER
241
249
  ingredient_key: identifier_t.IdentifierKey
242
250
  placeholder: RecipeInputPlaceholder
251
+ mix_step_match_strategy: MixStepMatchStrategy = MixStepMatchStrategy.FIRST
243
252
 
244
253
 
245
254
  # DO NOT MODIFY -- This file is generated by type_spec
@@ -25,7 +25,6 @@ ENDPOINT_PATH = "api/external/recipes/external_get_recipe_links"
25
25
  # DO NOT MODIFY -- This file is generated by type_spec
26
26
  @serial_class(
27
27
  named_type_path="sdk.api.recipes.get_recipe_links.Arguments",
28
- explicit_defaults={"depth"},
29
28
  )
30
29
  @dataclasses.dataclass(kw_only=True)
31
30
  class Arguments:
@@ -42,7 +42,6 @@ class RecipeLockBase:
42
42
  # DO NOT MODIFY -- This file is generated by type_spec
43
43
  @serial_class(
44
44
  named_type_path="sdk.api.recipes.lock_recipes.Arguments",
45
- explicit_defaults={"type"},
46
45
  )
47
46
  @dataclasses.dataclass(kw_only=True)
48
47
  class Arguments:
@@ -10,6 +10,7 @@ from enum import StrEnum
10
10
  import dataclasses
11
11
  from pkgs.serialization import serial_class
12
12
  from ... import base_t
13
+ from ... import data_t
13
14
  from ... import field_values_t
14
15
  from ... import recipes_t
15
16
  from ... import response_t
@@ -48,7 +49,6 @@ class NullBehavior(StrEnum):
48
49
  @serial_class(
49
50
  named_type_path="sdk.api.recipes.set_recipe_outputs.RecipeOutputValue",
50
51
  to_string_values={"value_numeric"},
51
- explicit_defaults={"null_behavior"},
52
52
  )
53
53
  @dataclasses.dataclass(kw_only=True)
54
54
  class RecipeOutputValue:
@@ -60,6 +60,7 @@ class RecipeOutputValue:
60
60
  value_numeric: Decimal | None = None
61
61
  value_str: str | None = None
62
62
  value_curve: CurveValues | None = None
63
+ value_color: data_t.RecipeOutputColor | None = None
63
64
  formatting: recipes_t.RecipeAttributeFormatting | None = None
64
65
  field_values: list[field_values_t.ArgumentValueRefName | field_values_t.ArgumentValueId] | None = None
65
66
 
@@ -31,7 +31,6 @@ class RecipeUnlockType(StrEnum):
31
31
  # DO NOT MODIFY -- This file is generated by type_spec
32
32
  @serial_class(
33
33
  named_type_path="sdk.api.recipes.unlock_recipes.Arguments",
34
- explicit_defaults={"type"},
35
34
  )
36
35
  @dataclasses.dataclass(kw_only=True)
37
36
  class Arguments:
@@ -41,6 +41,7 @@ class AsyncBatchRequestPath(StrEnum):
41
41
  CREATE_OR_UPDATE_ENTITY = "entity/create_or_update_entity"
42
42
  ADD_TIME_SERIES_DATA = "recipes/add_time_series_data"
43
43
  LOOKUP_ENTITY = "entity/lookup_entity"
44
+ CREATE_RECIPE_LINK = "recipe_links/create_recipe_link"
44
45
 
45
46
 
46
47
  # DO NOT MODIFY -- This file is generated by type_spec
@@ -17,7 +17,6 @@ __all__: list[str] = [
17
17
  # DO NOT MODIFY -- This file is generated by type_spec
18
18
  @serial_class(
19
19
  named_type_path="sdk.client_config.ClientConfigOptions",
20
- explicit_defaults={"allow_insecure_tls"},
21
20
  )
22
21
  @dataclasses.dataclass(kw_only=True)
23
22
  class ClientConfigOptions:
@@ -0,0 +1,12 @@
1
+ # ruff: noqa: E402 Q003
2
+ # fmt: off
3
+ # isort: skip_file
4
+ # DO NOT MODIFY -- This file is generated by type_spec
5
+ # Kept only for SDK backwards compatibility
6
+ from .data_t import RgbColor as RgbColor
7
+ from .data_t import CielabColor as CielabColor
8
+ from .data_t import XyzColor as XyzColor
9
+ from .data_t import LChColor as LChColor
10
+ from .data_t import HslColor as HslColor
11
+ from .data_t import RecipeOutputColor as RecipeOutputColor
12
+ # DO NOT MODIFY -- This file is generated by type_spec
@@ -0,0 +1,93 @@
1
+ # DO NOT MODIFY -- This file is generated by type_spec
2
+ # ruff: noqa: E402 Q003
3
+ # fmt: off
4
+ # isort: skip_file
5
+ from __future__ import annotations
6
+ import typing # noqa: F401
7
+ import datetime # noqa: F401
8
+ from decimal import Decimal # noqa: F401
9
+ import dataclasses
10
+ from pkgs.serialization import serial_class
11
+
12
+ __all__: list[str] = [
13
+ "CielabColor",
14
+ "HslColor",
15
+ "LChColor",
16
+ "RecipeOutputColor",
17
+ "RgbColor",
18
+ "XyzColor",
19
+ ]
20
+
21
+
22
+ # DO NOT MODIFY -- This file is generated by type_spec
23
+ @serial_class(
24
+ named_type_path="sdk.data.RgbColor",
25
+ unconverted_keys={"B", "G", "R"},
26
+ )
27
+ @dataclasses.dataclass(kw_only=True)
28
+ class RgbColor:
29
+ R: int
30
+ G: int
31
+ B: int
32
+
33
+
34
+ # DO NOT MODIFY -- This file is generated by type_spec
35
+ @serial_class(
36
+ named_type_path="sdk.data.CielabColor",
37
+ unconverted_keys={"L", "a", "b"},
38
+ )
39
+ @dataclasses.dataclass(kw_only=True)
40
+ class CielabColor:
41
+ L: int
42
+ a: int
43
+ b: int
44
+
45
+
46
+ # DO NOT MODIFY -- This file is generated by type_spec
47
+ @serial_class(
48
+ named_type_path="sdk.data.XyzColor",
49
+ unconverted_keys={"X", "Y", "Z"},
50
+ )
51
+ @dataclasses.dataclass(kw_only=True)
52
+ class XyzColor:
53
+ X: int
54
+ Y: int
55
+ Z: int
56
+
57
+
58
+ # DO NOT MODIFY -- This file is generated by type_spec
59
+ @serial_class(
60
+ named_type_path="sdk.data.LChColor",
61
+ unconverted_keys={"C", "L", "h"},
62
+ )
63
+ @dataclasses.dataclass(kw_only=True)
64
+ class LChColor:
65
+ L: int
66
+ C: int
67
+ h: int
68
+
69
+
70
+ # DO NOT MODIFY -- This file is generated by type_spec
71
+ @serial_class(
72
+ named_type_path="sdk.data.HslColor",
73
+ unconverted_keys={"L", "h", "s"},
74
+ )
75
+ @dataclasses.dataclass(kw_only=True)
76
+ class HslColor:
77
+ h: int
78
+ s: int
79
+ L: int
80
+
81
+
82
+ # DO NOT MODIFY -- This file is generated by type_spec
83
+ @serial_class(
84
+ named_type_path="sdk.data.RecipeOutputColor",
85
+ unconverted_keys={"CIELAB", "LCH", "RGB", "XYZ"},
86
+ )
87
+ @dataclasses.dataclass(kw_only=True)
88
+ class RecipeOutputColor:
89
+ RGB: RgbColor
90
+ CIELAB: CielabColor
91
+ XYZ: XyzColor | None = None
92
+ LCH: LChColor | None = None
93
+ # DO NOT MODIFY -- This file is generated by type_spec
@@ -94,7 +94,7 @@ __all__: list[str] = [
94
94
  "lab_location": "Lab Location",
95
95
  "lab_request": "Lab Request",
96
96
  "license": "License",
97
- "maintenance_schedule": "Maintenance Schedule",
97
+ "maintenance_schedule": "Equipment Action Type",
98
98
  "material_family": "Material Family",
99
99
  "measurement_group": "Measurement Group",
100
100
  "measurement_group_input": "Measurement Group Input",
@@ -384,7 +384,7 @@ class EntityType(StrEnum):
384
384
 
385
385
  # DO NOT MODIFY -- This file is generated by type_spec
386
386
  LimitedEntityType = typing.Annotated[
387
- typing.Literal[EntityType.LAB_REQUEST] | typing.Literal[EntityType.APPROVAL] | typing.Literal[EntityType.CUSTOM_ENTITY] | typing.Literal[EntityType.INGREDIENT_ATTRIBUTE] | typing.Literal[EntityType.INVENTORY_AMOUNT] | typing.Literal[EntityType.TASK] | typing.Literal[EntityType.PROJECT] | typing.Literal[EntityType.EQUIPMENT] | typing.Literal[EntityType.INV_LOCAL_LOCATIONS] | typing.Literal[EntityType.FIELD_OPTION_SET] | typing.Literal[EntityType.WEBHOOK] | typing.Literal[EntityType.SPECS] | typing.Literal[EntityType.GOAL] | typing.Literal[EntityType.INGREDIENT_TAG_MAP] | typing.Literal[EntityType.INGREDIENT_TAG] | typing.Literal[EntityType.CONDITION_PARAMETER] | typing.Literal[EntityType.OUTPUT] | typing.Literal[EntityType.OUTPUT_CONDITION_PARAMETER] | typing.Literal[EntityType.ASYNC_JOB] | typing.Literal[EntityType.CONSTRAINT] | typing.Literal[EntityType.INGREDIENT_CATEGORY_ALL] | typing.Literal[EntityType.TIME_SERIES_SEGMENT],
387
+ typing.Literal[EntityType.LAB_REQUEST] | typing.Literal[EntityType.APPROVAL] | typing.Literal[EntityType.CUSTOM_ENTITY] | typing.Literal[EntityType.INGREDIENT_ATTRIBUTE] | typing.Literal[EntityType.INVENTORY_AMOUNT] | typing.Literal[EntityType.TASK] | typing.Literal[EntityType.PROJECT] | typing.Literal[EntityType.EQUIPMENT] | typing.Literal[EntityType.INV_LOCAL_LOCATIONS] | typing.Literal[EntityType.FIELD_OPTION_SET] | typing.Literal[EntityType.WEBHOOK] | typing.Literal[EntityType.SPECS] | typing.Literal[EntityType.GOAL] | typing.Literal[EntityType.INGREDIENT_TAG_MAP] | typing.Literal[EntityType.INGREDIENT_TAG] | typing.Literal[EntityType.CONDITION_PARAMETER] | typing.Literal[EntityType.OUTPUT] | typing.Literal[EntityType.OUTPUT_CONDITION_PARAMETER] | typing.Literal[EntityType.ASYNC_JOB] | typing.Literal[EntityType.CONSTRAINT] | typing.Literal[EntityType.INGREDIENT_CATEGORY_ALL] | typing.Literal[EntityType.TIME_SERIES_SEGMENT] | typing.Literal[EntityType.EQUIPMENT_MAINTENANCE] | typing.Literal[EntityType.MAINTENANCE_SCHEDULE],
388
388
  serial_alias_annotation(
389
389
  named_type_path="sdk.entity.LimitedEntityType",
390
390
  ),
@@ -21,6 +21,9 @@ from .field_values_t import FieldValueBoolean as FieldValueBoolean
21
21
  from .field_values_t import FieldValueNumeric as FieldValueNumeric
22
22
  from .field_values_t import FieldValueBatchReference as FieldValueBatchReference
23
23
  from .field_values_t import FieldValueNull as FieldValueNull
24
+ from .field_values_t import FieldValueNotes as FieldValueNotes
25
+ from .field_values_t import FieldValueDate as FieldValueDate
26
+ from .field_values_t import FieldValueDatetime as FieldValueDatetime
24
27
  from .field_values_t import FieldValue as FieldValue
25
28
  from .field_values_t import FieldArgumentValue as FieldArgumentValue
26
29
  # DO NOT MODIFY -- This file is generated by type_spec
@@ -24,11 +24,14 @@ __all__: list[str] = [
24
24
  "FieldValueBase",
25
25
  "FieldValueBatchReference",
26
26
  "FieldValueBoolean",
27
+ "FieldValueDate",
28
+ "FieldValueDatetime",
27
29
  "FieldValueFieldOption",
28
30
  "FieldValueFieldOptions",
29
31
  "FieldValueFiles",
30
32
  "FieldValueId",
31
33
  "FieldValueIds",
34
+ "FieldValueNotes",
32
35
  "FieldValueNull",
33
36
  "FieldValueNumeric",
34
37
  "FieldValueText",
@@ -100,6 +103,9 @@ class FieldValueType(StrEnum):
100
103
  FIELD_OPTION = "field_option"
101
104
  FIELD_OPTIONS = "field_options"
102
105
  NULL_VALUE = "null_value"
106
+ NOTES = "notes"
107
+ DATE = "date"
108
+ DATETIME = "datetime"
103
109
 
104
110
 
105
111
  # DO NOT MODIFY -- This file is generated by type_spec
@@ -132,7 +138,6 @@ class ValueResolution(StrEnum):
132
138
  @serial_class(
133
139
  named_type_path="sdk.field_values.FieldValueFieldOption",
134
140
  parse_require={"type"},
135
- explicit_defaults={"value_resolution"},
136
141
  )
137
142
  @dataclasses.dataclass(kw_only=True)
138
143
  class FieldValueFieldOption(FieldValueBase):
@@ -145,7 +150,6 @@ class FieldValueFieldOption(FieldValueBase):
145
150
  @serial_class(
146
151
  named_type_path="sdk.field_values.FieldValueFieldOptions",
147
152
  parse_require={"type"},
148
- explicit_defaults={"value_resolution"},
149
153
  )
150
154
  @dataclasses.dataclass(kw_only=True)
151
155
  class FieldValueFieldOptions(FieldValueBase):
@@ -245,9 +249,42 @@ class FieldValueNull(FieldValueBase):
245
249
  type: typing.Literal[FieldValueType.NULL_VALUE] = FieldValueType.NULL_VALUE
246
250
 
247
251
 
252
+ # DO NOT MODIFY -- This file is generated by type_spec
253
+ @serial_class(
254
+ named_type_path="sdk.field_values.FieldValueNotes",
255
+ parse_require={"type"},
256
+ )
257
+ @dataclasses.dataclass(kw_only=True)
258
+ class FieldValueNotes(FieldValueBase):
259
+ type: typing.Literal[FieldValueType.NOTES] = FieldValueType.NOTES
260
+ value: str
261
+
262
+
263
+ # DO NOT MODIFY -- This file is generated by type_spec
264
+ @serial_class(
265
+ named_type_path="sdk.field_values.FieldValueDate",
266
+ parse_require={"type"},
267
+ )
268
+ @dataclasses.dataclass(kw_only=True)
269
+ class FieldValueDate(FieldValueBase):
270
+ type: typing.Literal[FieldValueType.DATE] = FieldValueType.DATE
271
+ value: datetime.date
272
+
273
+
274
+ # DO NOT MODIFY -- This file is generated by type_spec
275
+ @serial_class(
276
+ named_type_path="sdk.field_values.FieldValueDatetime",
277
+ parse_require={"type"},
278
+ )
279
+ @dataclasses.dataclass(kw_only=True)
280
+ class FieldValueDatetime(FieldValueBase):
281
+ type: typing.Literal[FieldValueType.DATETIME] = FieldValueType.DATETIME
282
+ value: datetime.datetime
283
+
284
+
248
285
  # DO NOT MODIFY -- This file is generated by type_spec
249
286
  FieldValue = typing.Annotated[
250
- FieldValueFiles | FieldValueId | FieldValueIds | FieldValueText | FieldValueTexts | FieldValueBoolean | FieldValueNumeric | FieldValueBatchReference | FieldValueFieldOption | FieldValueFieldOptions | FieldValueNull,
287
+ FieldValueFiles | FieldValueId | FieldValueIds | FieldValueText | FieldValueTexts | FieldValueBoolean | FieldValueNumeric | FieldValueBatchReference | FieldValueFieldOption | FieldValueFieldOptions | FieldValueNull | FieldValueNotes | FieldValueDate | FieldValueDatetime,
251
288
  serial_union_annotation(
252
289
  named_type_path="sdk.field_values.FieldValue",
253
290
  ),
@@ -109,7 +109,6 @@ UploadDestination = typing.Annotated[
109
109
  # DO NOT MODIFY -- This file is generated by type_spec
110
110
  @serial_class(
111
111
  named_type_path="sdk.generic_upload.GenericUploadStrategy",
112
- explicit_defaults={"skip_moving_files"},
113
112
  )
114
113
  @dataclasses.dataclass(kw_only=True)
115
114
  class GenericUploadStrategy:
@@ -168,7 +168,6 @@ JobExecutor = typing.Annotated[
168
168
  # DO NOT MODIFY -- This file is generated by type_spec
169
169
  @serial_class(
170
170
  named_type_path="sdk.job_definition.JobLoggingSettings",
171
- explicit_defaults={"enabled"},
172
171
  )
173
172
  @dataclasses.dataclass(kw_only=True)
174
173
  class JobLoggingSettings:
@@ -179,7 +178,6 @@ class JobLoggingSettings:
179
178
  # DO NOT MODIFY -- This file is generated by type_spec
180
179
  @serial_class(
181
180
  named_type_path="sdk.job_definition.JobDefinitionBase",
182
- explicit_defaults={"enabled"},
183
181
  )
184
182
  @dataclasses.dataclass(kw_only=True)
185
183
  class JobDefinitionBase:
@@ -59,7 +59,6 @@ class RecipeWorkflowStepPosition(StrEnum):
59
59
  @serial_class(
60
60
  named_type_path="sdk.recipe_workflow_steps.RecipeWorkflowStepIdentifierWorkflowStep",
61
61
  parse_require={"type"},
62
- explicit_defaults={"position"},
63
62
  )
64
63
  @dataclasses.dataclass(kw_only=True)
65
64
  class RecipeWorkflowStepIdentifierWorkflowStep(RecipeWorkflowStepIdentifierBase):
@@ -18,7 +18,6 @@ __all__: list[str] = [
18
18
  @serial_class(
19
19
  named_type_path="sdk.response.Response",
20
20
  parse_require={"status"},
21
- explicit_defaults={"status"},
22
21
  )
23
22
  @dataclasses.dataclass(kw_only=True)
24
23
  class Response:
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: UncountablePythonSDK
3
- Version: 0.0.105
3
+ Version: 0.0.110
4
4
  Summary: Uncountable SDK
5
5
  Project-URL: Homepage, https://github.com/uncountableinc/uncountable-python-sdk
6
6
  Project-URL: Repository, https://github.com/uncountableinc/uncountable-python-sdk.git
@@ -3,7 +3,7 @@ docs/conf.py,sha256=YF5J-9g_Wg8wXmyHsGaE8xYlDEzqocNl3UWUmP0CwBg,1702
3
3
  docs/index.md,sha256=eEdirX_Ds6ICTRtIS5iT4irCquHcQyKN7E4M5QP9T8A,257
4
4
  docs/justfile,sha256=Ej6_tqyrBIQaEXOwjIrwIfhTOOC-9xZr0i7wPWhDJkQ,273
5
5
  docs/quickstart.md,sha256=3GuJ0MB1O5kjlsrgAmdSkDq0rYqATrYy-tzEHDy8H-c,422
6
- docs/requirements.txt,sha256=boDCqjFBcBYm1T6FHTF2j5XqVX8s5YIsoB4r3HK0HPg,153
6
+ docs/requirements.txt,sha256=IBoo8nKwyuZXoaSX7XOYRJvfT6VjwJPXz49eZvcZGuY,153
7
7
  docs/static/logo_blue.png,sha256=SyYpMTVhhBbhF5Wl8lWaVwz-_p1MIR6dW6bVhufQRME,46708
8
8
  docs/static/favicons/android-chrome-192x192.png,sha256=XoF-AhD55JlSBDGsEPJKfT_VeXT-awhwKyZnxLhrwvk,1369
9
9
  docs/static/favicons/android-chrome-512x512.png,sha256=1S4xwY9YtJQ5ifFsZ-DOzssoyBYs0t9uwdOUmYx0Xso,3888
@@ -31,54 +31,54 @@ pkgs/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
31
  pkgs/argument_parser/__init__.py,sha256=VWUOOtJ-ueRF2lkIJzgQe4xhBKR9IPkgf9vY28nF35s,870
32
32
  pkgs/argument_parser/_is_enum.py,sha256=Gw6jJa8nBwYGqXwwCZbSnWL8Rvr5alkg5lSVAqXtOZM,257
33
33
  pkgs/argument_parser/_is_namedtuple.py,sha256=Rjc1bKanIPPogl3qG5JPBxglG1TqWYOo1nxxhBASQWY,265
34
- pkgs/argument_parser/argument_parser.py,sha256=3SR0EX5ZNz5kGDcWWrzQKNkGgWsaSMgTLVVgs-GJeRU,20879
34
+ pkgs/argument_parser/argument_parser.py,sha256=imyOd7JkEVI-fwEzozFns9M38UBF3DIBVIy2FEBfxpE,20893
35
35
  pkgs/argument_parser/case_convert.py,sha256=NuJLJUJRbyVb6_Slen4uqaStEHbcOS1d-hBBfDrrw-c,605
36
36
  pkgs/filesystem_utils/__init__.py,sha256=2a0d2rEPlEEYwhm3Wckny4VCp4ZS7JtYSXmwdwNCRjo,1332
37
37
  pkgs/filesystem_utils/_blob_session.py,sha256=CtoB7PIocuZo8vvFIS_Rc-YR6KwzFB0rHUVPKFEbRAI,4862
38
- pkgs/filesystem_utils/_gdrive_session.py,sha256=XTAKppTfIiJtPkzq90yftoMHa-kcGe9MDZQlmx1bviQ,11058
38
+ pkgs/filesystem_utils/_gdrive_session.py,sha256=xelwsGfxhxKX0LFwOv9UJ3_jSHyhYyHiLH6EUXNZgHo,11059
39
39
  pkgs/filesystem_utils/_local_session.py,sha256=xFEYhAvNqrOYqwt4jrEYOuYkjJn0zclZhTelW_Q1-rw,2325
40
40
  pkgs/filesystem_utils/_s3_session.py,sha256=DdD6M90z1VyTiuRdTmjvBNJOEFHBPyEU8wGKRKwHvOU,4027
41
41
  pkgs/filesystem_utils/_sftp_session.py,sha256=l1hS8KjnINqCX2CZU1t66H-is0mTwTLeMcQMyXW8DjM,4847
42
42
  pkgs/filesystem_utils/file_type_utils.py,sha256=oklu7Wtcxg9pBz84cAlXpNlhYEM0AbsO5DoEqvFjoXY,1896
43
43
  pkgs/filesystem_utils/filesystem_session.py,sha256=BQ2Go8Mu9-GcnaWh2Pm4x7ugLVsres6XrOQ8RoiEpcE,1045
44
44
  pkgs/serialization/__init__.py,sha256=b2sNfYICz0D6Y8shzEUfyUoHZukfuAvfuaZvg8dZHic,1163
45
- pkgs/serialization/annotation.py,sha256=wn9yb4a4DrsyPAYqY9mVswJarP4lsOkgfnvchrg5toE,2104
46
- pkgs/serialization/missing_sentry.py,sha256=89SomyM0sBWLr_N0SPOyxU3hWcm1ljL-veTazZ1-GU8,811
45
+ pkgs/serialization/annotation.py,sha256=UJNMb9wMUWLWW-om17HSNmfFtAEcZJcCmvirdmmGmhg,2114
46
+ pkgs/serialization/missing_sentry.py,sha256=0r1JF2yt6bF42nVWWnhk5Ohdi1O7K-ghEAIl1SyjmWU,803
47
47
  pkgs/serialization/opaque_key.py,sha256=8ak7aMCGWkKDjnG374yqy8gtnCCUzG2DSJEBfoPgi0c,194
48
- pkgs/serialization/serial_alias.py,sha256=zP0wAy7NGvpyOe-TGUwHy3wPF0XZTIwFLh_caDX67BU,1343
49
- pkgs/serialization/serial_class.py,sha256=uBfleDXvSZcPfPSzLIqKTocXix5i-lMjidnS9-xQXR8,6711
50
- pkgs/serialization/serial_generic.py,sha256=vAC0-o9fkco2lM_YvBavY0JDYncDxbW3jFboYeHRImw,461
51
- pkgs/serialization/serial_union.py,sha256=IdWsSsM8j-qGfl5Wv6haX37ZS1SKob8XT8cilBBOVIo,2670
48
+ pkgs/serialization/serial_alias.py,sha256=ABEGtSEapeW95wo9NT4srEhzdGaP5RhB8EyWSyWhwKg,1337
49
+ pkgs/serialization/serial_class.py,sha256=i2yyejL7MUX3ddrgIedj8SJR_5D9-lj62k1zKdRur-I,6077
50
+ pkgs/serialization/serial_generic.py,sha256=3nO8T2aO9AF0MqOWQCVZW1zH6gAVvKpCzA46hOcwN_I,458
51
+ pkgs/serialization/serial_union.py,sha256=jU5-nw8pnUr0RdEfbrUw9W6U-fW8i8vXM8xHSCr295o,2680
52
52
  pkgs/serialization/yaml.py,sha256=yoJtu7_ixnJV6uTxA_U1PpK5F_ixT08AKVh5ocyYwXM,1466
53
53
  pkgs/serialization_util/__init__.py,sha256=YykkhqGNKiLCo-D5vSTq6WiPNfCyPXyr-mQO5e5Klak,513
54
54
  pkgs/serialization_util/_get_type_for_serialization.py,sha256=dW5_W9MFd6wgWfW5qlWork-GBb-QFLtiOZkjk2Zqn2M,1177
55
55
  pkgs/serialization_util/convert_to_snakecase.py,sha256=H2BAo5ZdcCDN77RpLb-uP0s7-FQ5Ukwnsd3VYc1vD0M,583
56
56
  pkgs/serialization_util/dataclasses.py,sha256=uhNGXQPQLZblDFQuuwkAGmKOPiRyfDzCdg72CVtYJGA,390
57
- pkgs/serialization_util/serialization_helpers.py,sha256=KgLk6z9Y9TbkJyoMKffzBnPTtSRrE9CxnPuErVWoBSQ,6550
57
+ pkgs/serialization_util/serialization_helpers.py,sha256=5fxvMZXdfmXLDzeLC1FkjytHh1YfZWbXwzZcY_4eFPs,6578
58
58
  pkgs/strenum_compat/__init__.py,sha256=wXRFeNvBm8RU6dy1PFJ5sRLgUIEeH_DVR95Sv5qpGbk,59
59
59
  pkgs/strenum_compat/strenum_compat.py,sha256=uOUAgpYTjHs1MX8dG81jRlyTkt3KNbkV_25zp7xTX2s,36
60
60
  pkgs/type_spec/__init__.py,sha256=h5DmJTca4QVV10sZR1x0-MlkZfuGYDfapR3zHvXfzto,19
61
61
  pkgs/type_spec/__main__.py,sha256=5bJaX9Y_-FavP0qwzhk-z-V97UY7uaezJTa1zhO_HHQ,1048
62
62
  pkgs/type_spec/builder.py,sha256=6m9sWeap0Hh8LkcQpufO5mkFRNIFIBKhEA02Q23PrSs,53071
63
- pkgs/type_spec/config.py,sha256=HThKnWQ4zkWOyUIb12hTodsrvEnhSzOvhHKCOeTM0iY,5302
64
- pkgs/type_spec/cross_output_links.py,sha256=nmyWUaFRk7MLTdJiosfKkhOb4VLE71A3DDKKwTZAncY,3123
63
+ pkgs/type_spec/config.py,sha256=K6WebgeI3Saew0IEBcm1s2fauw_CyvH183emVrNoUXg,5327
64
+ pkgs/type_spec/cross_output_links.py,sha256=bVNn0a4LMVTRLg_zjtiHnoTwdINHfftjWoH6tGdxhlk,3124
65
65
  pkgs/type_spec/emit_io_ts.py,sha256=CUvBs0boB_X-Kndh66yYcqFfq3oC_LGs8YffLkJ0ZXA,5707
66
- pkgs/type_spec/emit_open_api.py,sha256=kHP4jKRica4Us28_9G2iHq9K7BrUdsl8daIIHZaPdws,25000
67
- pkgs/type_spec/emit_open_api_util.py,sha256=UwaUcgqTwl_D8s2y6ic3fC23VllVcP0w_2iUg9ThYCA,2361
68
- pkgs/type_spec/emit_python.py,sha256=nVCKbXfFCGUrYkLWZehJgcrR_7o5pAbqb97f_EeYEn8,52732
66
+ pkgs/type_spec/emit_open_api.py,sha256=B9cGFR7TU90_yky-HdNq1sDIJOuP3eU4o3j7nNgIpkU,26047
67
+ pkgs/type_spec/emit_open_api_util.py,sha256=xnc4ymNzEyAS1Q2cV6Ma9Y6mQ1MbPPi2WaHKTSFETr8,2346
68
+ pkgs/type_spec/emit_python.py,sha256=8Nzu6uk9ofezWcrcaVU0wPHCIM8DwvXnronrIDLP6yg,52403
69
69
  pkgs/type_spec/emit_typescript.py,sha256=0HRzxlbIP91rzbVkAntF4TKZppoKcWsqnDLAIRc1bng,10927
70
70
  pkgs/type_spec/emit_typescript_util.py,sha256=8ophCR8MX0IvYtLYu3omfPQk2H6BeYGd2psRir9ImmQ,10550
71
71
  pkgs/type_spec/load_types.py,sha256=GndEKQtICCQi4oXsL6cZ9khm8lBB830e6hx0wML4dHs,4278
72
- pkgs/type_spec/open_api_util.py,sha256=OiuMWUIwi7ibIOABtuHnhrPdfd3rVxv0MJ1ZY1xj_qw,7083
72
+ pkgs/type_spec/open_api_util.py,sha256=DYnlygaMIqDQtSuYpUpd5lpA9JG4JHd_-iGe-BY2lhw,7333
73
73
  pkgs/type_spec/test.py,sha256=4ueujBq-pEgnX3Z69HyPmD-bullFXmpixcpVzfOkhP4,489
74
- pkgs/type_spec/util.py,sha256=TPmFVgiGj6niurg4V-AKFkQQDDDtJ8a5o2Z_EDgMTvU,4827
74
+ pkgs/type_spec/util.py,sha256=S_SGTJU192x-wIbngVUTvXhQENMbBfxluigLmnItGI8,4848
75
75
  pkgs/type_spec/actions_registry/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
76
76
  pkgs/type_spec/actions_registry/__main__.py,sha256=SRw6kIhHTW7W2wGijYq66JARzoc4KpPmbLqwvnETyTE,4277
77
77
  pkgs/type_spec/actions_registry/emit_typescript.py,sha256=W1lI36ITdJ7MBf37wlTB7H3X9Ljt217vIGMv4e3fxfY,5986
78
78
  pkgs/type_spec/parts/base.py.prepart,sha256=RDNNo4nbLiC9ASIODq2xIt0HkwDNiJVcmjDD33Bubaw,2303
79
79
  pkgs/type_spec/parts/base.ts.prepart,sha256=2FJJvpg2olCcavxj0nbYWdwKl6KeScour2JjSvN42l8,1001
80
80
  pkgs/type_spec/type_info/__main__.py,sha256=TLNvCHGcmaj_8Sj5bAQNpuNaaw2dpDzoFDWZds0V4Qo,1002
81
- pkgs/type_spec/type_info/emit_type_info.py,sha256=Rro9QVq6ZxEDm_gWlwtqqLeazelGIZhSf4pHtMUIJyo,14495
81
+ pkgs/type_spec/type_info/emit_type_info.py,sha256=ON5L-MopmCjIEBm9K5xN3lJmDG1leFxuCLU_bg5W-RM,14972
82
82
  pkgs/type_spec/value_spec/__init__.py,sha256=Z-grlcZtxAfEXhPHsK0nD7PFLGsv4eqvunaPN7_TA84,83
83
83
  pkgs/type_spec/value_spec/__main__.py,sha256=D1ofjeEs3qFpB_GUZR1rZbryc0nMEyWj54VyhI-RqpI,8875
84
84
  pkgs/type_spec/value_spec/convert_type.py,sha256=X5N7DOTo5XOIHbcYHh9RZFthzb2gcnYg2tRuVMBhbxY,2517
@@ -124,16 +124,16 @@ uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.
124
124
  uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.pyi,sha256=9viBn6PHvtfMSRwam57ke5O2D_k8LapWYVfBRjknIYg,1281
125
125
  uncountable/integration/queue_runner/command_server/protocol/command_server_pb2_grpc.py,sha256=ZVHkuLDjEbXMCxBsw1UrRhT3EEF8CDDqEvmE3Kbp1H4,5359
126
126
  uncountable/integration/queue_runner/datastore/__init__.py,sha256=6BefApqN8D2zlVOH14QAeVzwQ8j5NIb41-njT02Za0k,88
127
- uncountable/integration/queue_runner/datastore/datastore_sqlite.py,sha256=UZQABTrM3HxVaojCnI1pTU3v1GsbE3G-OCgXP5ekcxI,3801
127
+ uncountable/integration/queue_runner/datastore/datastore_sqlite.py,sha256=N550yqpOrJWI4qLwiR1klVCZip44LG11VW6rKwZ3F8M,3798
128
128
  uncountable/integration/queue_runner/datastore/interface.py,sha256=j4D-zVvLq-48VTVwHVei82UVUJ_P3cxiseyiTl0MoNw,534
129
129
  uncountable/integration/queue_runner/datastore/model.py,sha256=8-RI5A2yPZVGBLWINVmMd6VOl_oHtqGtnaNXcapAChw,577
130
130
  uncountable/integration/secret_retrieval/__init__.py,sha256=3QXVj35w8rRMxVvmmsViFYDi3lcb3g70incfalOEm6o,87
131
131
  uncountable/integration/secret_retrieval/retrieve_secret.py,sha256=9iz9N8Z-B68QwFCXsx8hTYbgDbk06ejkJ3RQ9mCLMyM,3000
132
132
  uncountable/integration/webhook_server/entrypoint.py,sha256=yQWQq_k3kbJkSsEEt6k22YwhXekezJZfV0rnn-hP-Yo,5516
133
- uncountable/types/__init__.py,sha256=a2kCvZBwEAFM3OaadEAZ2bugCLt5XF3-jtMv1fnQLQw,9488
133
+ uncountable/types/__init__.py,sha256=E5rw-DgsM0S8kx-UO1q1qoUeiFg7GcfuSe_IcniEp8s,9533
134
134
  uncountable/types/async_batch.py,sha256=yCCWrrLQfxXVqZp-KskxLBNkNmuELdz4PJjx8ULppgs,662
135
135
  uncountable/types/async_batch_processor.py,sha256=zko4MIgYSfV0bh46jyUBYVGbUQUxTESajGH7hAFUlCg,17912
136
- uncountable/types/async_batch_t.py,sha256=imFU0INA-LAGYXDhwlWWTVxfGizmDOYZwUs7BgqFzpA,3229
136
+ uncountable/types/async_batch_t.py,sha256=8DH-_5W3AI4dYn-FxTn060isHFOTJb1JKwDrfBztyC4,3288
137
137
  uncountable/types/async_jobs.py,sha256=JI0ScfawaqMRbJ2jbgW3YQLhijPnBeYdMnZJjygSxHg,322
138
138
  uncountable/types/async_jobs_t.py,sha256=u4xd3i512PZ-9592Q2ZgWh_faMiI4UMm0F_gOmZnerI,1389
139
139
  uncountable/types/auth_retrieval.py,sha256=770zjN1K9EF5zs1Xml7x6ke6Hkze7rcMT5FdDVCIl9M,549
@@ -146,19 +146,21 @@ uncountable/types/chemical_structure.py,sha256=ujyragaD26-QG5jgKnWhO7TN3N1V9b_04
146
146
  uncountable/types/chemical_structure_t.py,sha256=iYmGER_vXqoksv2Nr189qU1Zm70s-U49Eiv0DkWaB1I,773
147
147
  uncountable/types/client_base.py,sha256=wB2ABAvMqgyUzHKMfx1Js-kXll1IfIH2hoVhQwFDSVA,72069
148
148
  uncountable/types/client_config.py,sha256=qLpHt4O_B098CyN6qQajoxZ2zjZ1DILXLUEGyyGP0TQ,280
149
- uncountable/types/client_config_t.py,sha256=ovNtGbinjSYZiC-rpYINhtEb4HcwXBDmlJDaFx8Qano,745
149
+ uncountable/types/client_config_t.py,sha256=k_UkjemqiVuJBiFUjJYk3h673Nahr0nGZvfEZFzsC0k,699
150
150
  uncountable/types/curves.py,sha256=QyEyC20jsG-LGKVx6miiF-w70vKMwNkILFBDIJ5Ok9g,345
151
151
  uncountable/types/curves_t.py,sha256=2_9qdrSl1XAvIG57lo45KWNpa0wXgZ97OkSRCPRrudc,1347
152
+ uncountable/types/data.py,sha256=6dChU1uzwHT8xN2AFbMaAW41RV53b1_hLWuGny4EiMA,478
153
+ uncountable/types/data_t.py,sha256=nfaV6q-RJWxXGAY4wmvT06Hj51-AfyDU61mHFV08IOc,2043
152
154
  uncountable/types/entity.py,sha256=Zclk1LYcRaYrMDhqyCjMSLEg0fE6_q8LHvV22Qvscgs,566
153
- uncountable/types/entity_t.py,sha256=vxOkzHLu8FeBCRjjt43261iwxx5CBlWcJaBudP8LMLw,19493
155
+ uncountable/types/entity_t.py,sha256=vOin1nE84-QNDGeICJk1B0Rx5ZJQpADLsiUodM_W-7g,19595
154
156
  uncountable/types/experiment_groups.py,sha256=qUpFOx1AKgzaT_4khCOv5Xs6jwiQGbvHH-GUh3v1nv4,288
155
157
  uncountable/types/experiment_groups_t.py,sha256=_fAYZwqYLR3cFdv2vwLOYs5TvH5CEWDEbh3kFpg26zY,700
156
- uncountable/types/field_values.py,sha256=jPGc1mLXGpldQ1CVf35NZIaufpTQy0cOtADBr1RTyus,1520
157
- uncountable/types/field_values_t.py,sha256=fWwQh1PJysMS8tphy_OO4t1rW44k66jWzGLOxQxdWBg,7764
158
+ uncountable/types/field_values.py,sha256=iG4TvITLnlz023GuhFrlDwXB7oov5DPpAs_FBaMaJR8,1713
159
+ uncountable/types/field_values_t.py,sha256=CaTB7RSR_GmnCjLaJpmLY48eUv9hzxcPQXgRJrJWsMI,8856
158
160
  uncountable/types/fields.py,sha256=M0_ZZr0QdNLXkdHAGo5mfU90kEtHedCSKrcod-FG30Y,245
159
161
  uncountable/types/fields_t.py,sha256=Ze-X83HyM7q4oMk5LLRfPqvRojyAx6dDqIUPX70gNYc,644
160
162
  uncountable/types/generic_upload.py,sha256=bNep2nT0fbKAlJaGvHWPmuvfX5KtS8kgTqTh8FQk1NA,858
161
- uncountable/types/generic_upload_t.py,sha256=yvM1uaEVXy8H9OsBWr-ltzeyTuDKDZ6ZuvwBbB779m8,3801
163
+ uncountable/types/generic_upload_t.py,sha256=z7rxOu8SEyOmIlz06AAXmRkbQdBEpZigb8N2eGi6XIY,3756
162
164
  uncountable/types/id_source.py,sha256=sBlDfUwHQ7bGWMschSD_aPQL7LVnCPiV2RAlPLXrAqk,546
163
165
  uncountable/types/id_source_t.py,sha256=XzxQWkD0iQoq6LxtpCVWylYtOvq5dXslu_2ML1xNP_U,1838
164
166
  uncountable/types/identifier.py,sha256=J-ptCFE0_R0bBAvrYp-gvHk8H9Qq9rhbmeyXgwb9nos,482
@@ -170,7 +172,7 @@ uncountable/types/inputs_t.py,sha256=0b3U77JcZT4hgUvbP_i-E5RoJbJnRxn3OKBqGWu32TM
170
172
  uncountable/types/integration_server.py,sha256=VonA8h8TGnVBiss5W8-K82lA01JQa7TLk0ubFo8iiBQ,364
171
173
  uncountable/types/integration_server_t.py,sha256=37zyqeet54P9m6pxaZfLOgZCqqZA2dxJ5gl6NCoelQ0,1188
172
174
  uncountable/types/job_definition.py,sha256=6BkLZrmTfIYh45XFGZ5HOYveued0YXvl17YTlXblXjw,1646
173
- uncountable/types/job_definition_t.py,sha256=GQcs1mpl3QO1opqGAs5dmtdPwxpTPIq52Ei2pq7n9s0,7907
175
+ uncountable/types/job_definition_t.py,sha256=ed_fCyLFQBo6XDfqtfUnk4ghmx0uGtDHVEnNB1N_yv4,7837
174
176
  uncountable/types/outputs.py,sha256=I6zP2WHXg_jXgMqmuEJuJOlsjKjQGHjfs1JOwW9YxBM,260
175
177
  uncountable/types/outputs_t.py,sha256=ZJhKKkksJ-K7iuuumCly9edU8TRv-eWol4PKG7XPo3E,734
176
178
  uncountable/types/overrides.py,sha256=fOvj8P9K9ul8fnTwA--l140EWHuc1BFq8tXgtBkYld4,410
@@ -196,11 +198,11 @@ uncountable/types/recipe_output_metadata_t.py,sha256=llf9O2vK6AFRva5hx0VdiKXT9XQ
196
198
  uncountable/types/recipe_tags.py,sha256=tKIwHY677lZCxrmOk1bbuZQgDuf1n1cNyp6c5r1uRbo,270
197
199
  uncountable/types/recipe_tags_t.py,sha256=7qi9m8NAq7BdocIBdYyMVArFnPJrwuX0B9qoqlJiwzM,670
198
200
  uncountable/types/recipe_workflow_steps.py,sha256=fb55_sREdeZrtguIZOuy4ZcTLbRBNAxQ3A0oGbH8muA,950
199
- uncountable/types/recipe_workflow_steps_t.py,sha256=8MhOr-x9Fm9OiAefAwn2BDR8gadSqjKdGvi55U8a7c8,3442
201
+ uncountable/types/recipe_workflow_steps_t.py,sha256=dwjuFI6ncLBwr7Ufa-W26nrfF-BqZ_pKFIpKP05WqOo,3406
200
202
  uncountable/types/recipes.py,sha256=6Z7bagYXX15kGlhYt_OFiYSD3lqFp4H0EquI1fUfYyk,286
201
203
  uncountable/types/recipes_t.py,sha256=GBT56H34_pqAdeTgcye6ZNZLR1V47lG_S-R_uV-XUh8,652
202
204
  uncountable/types/response.py,sha256=SJTwjTxZGItGJJYPZ_T1zTooEbtR5ZA8GT_cf8aXfn8,253
203
- uncountable/types/response_t.py,sha256=XQ-0PHv3uxyVSJdoT50f0gDynTfC3jKa1MlNugBMdcE,680
205
+ uncountable/types/response_t.py,sha256=I4lArMXf50SFWon_Tl9AJjqqrzvfeSXv_C-AKfnGcZM,646
204
206
  uncountable/types/secret_retrieval.py,sha256=poY_nuZBIjNu64Wa0x5Ytsmh3OdAxps2kzuDgv1sa_8,571
205
207
  uncountable/types/secret_retrieval_t.py,sha256=hcJRp2OLPd5m7twve63F8gloL8KFJiCtyJD17H6WiAc,2138
206
208
  uncountable/types/units.py,sha256=yxuddayiE8cnzrjQiIsURisWc-Vm1F37uyS3fjM--Ao,254
@@ -225,7 +227,7 @@ uncountable/types/api/entity/get_entities_data.py,sha256=OUeBo0YkZmVTHT2EHAQt19r
225
227
  uncountable/types/api/entity/grant_entity_permissions.py,sha256=Zx3FDHSjiBN_wRtmxbWSWdmT-CkzEoi2uoVLCIdS2Q8,1391
226
228
  uncountable/types/api/entity/list_entities.py,sha256=1I6T6fjfolXx1lg8iRiCO5J0ieU0bdudPp31ZmMkXIQ,1895
227
229
  uncountable/types/api/entity/lock_entity.py,sha256=cWRTNlXj6Ei1M0mHwfbhid7hQs4whCheUCOmf8PIGqw,1166
228
- uncountable/types/api/entity/lookup_entity.py,sha256=rypZBAnnKF_HQlwySy_hQkNf0fr8z6cYqt41O580T0g,2971
230
+ uncountable/types/api/entity/lookup_entity.py,sha256=zIRfyWbqV7x7Ofo7GEp3Vo7DJnBNCuUvfD8SU1hTJm8,2927
229
231
  uncountable/types/api/entity/resolve_entity_ids.py,sha256=44B79L4erUB0G90WBGor0ZPs3XhdkuX7ZvgVF9uWB2M,1340
230
232
  uncountable/types/api/entity/set_entity_field_values.py,sha256=ZYtRrsx0MWc0txC6yH2HtCONC5A0IolpqvwHm_YgirU,1179
231
233
  uncountable/types/api/entity/set_values.py,sha256=2lANfjqPOcyxqDeISmzW0KghVbe8_i4QNkcLXzdAkag,1104
@@ -269,7 +271,7 @@ uncountable/types/api/recipe_metadata/__init__.py,sha256=gCgbynxG3jA8FQHzercKtrH
269
271
  uncountable/types/api/recipe_metadata/get_recipe_metadata_data.py,sha256=fW-6_vBIGa5Wx8JvEdpKb3orXD60DX_wOeHnmMPduc8,1550
270
272
  uncountable/types/api/recipes/__init__.py,sha256=gCgbynxG3jA8FQHzercKtrHKHkiIKr8APdZYUniAor8,55
271
273
  uncountable/types/api/recipes/add_recipe_to_project.py,sha256=vJL6DljCu4okNHvXJ5_uaBj0-QDEm9iTvVGMLYyDd2U,1061
272
- uncountable/types/api/recipes/add_time_series_data.py,sha256=xD7W4PjoWnGamimGY4DsJlyDjFz4SnhpTDjwtheVaQM,1776
274
+ uncountable/types/api/recipes/add_time_series_data.py,sha256=1pghWSwdbaEo--M__2VqYyGRMeXXh_G2--OzuhNWLpE,1737
273
275
  uncountable/types/api/recipes/archive_recipes.py,sha256=07Rjd9kwh5pMpiMXNr9OfjOB4vYXeuLjQtBxrXkXC7o,1024
274
276
  uncountable/types/api/recipes/associate_recipe_as_input.py,sha256=TtsAJRT9vRjnsIh0IvfFimA2hstZvgyn6rpaDIsDfK4,1194
275
277
  uncountable/types/api/recipes/associate_recipe_as_lot.py,sha256=_4SgFfH-wFxW9Vevv9k3G3T10Uz8CMLjuiDEv1oT2So,1138
@@ -277,29 +279,29 @@ uncountable/types/api/recipes/clear_recipe_outputs.py,sha256=BfTQrV79UePkJ4HSSix
277
279
  uncountable/types/api/recipes/create_recipe.py,sha256=tVeQgikCWAwGtxpq2vLyXd5Aeqo_8Tde64x5GAOJl50,1472
278
280
  uncountable/types/api/recipes/create_recipes.py,sha256=J1CBE13d8JaVpUxOftFg1Plo8RKa0vc-A2nHdO1yoj8,1862
279
281
  uncountable/types/api/recipes/disassociate_recipe_as_input.py,sha256=zWUfwJlkgWexblqKCKCF5HWR40ynQ8rg_PPo2WPGISY,1106
280
- uncountable/types/api/recipes/edit_recipe_inputs.py,sha256=nhPN0MdAx7FtdGKB3xbWQ3rdHk1QtblcT3D-DC1hexE,9963
282
+ uncountable/types/api/recipes/edit_recipe_inputs.py,sha256=Zpz72b-LEfNpyCsWZv0kg3hRhjipWdoyU9JRkwRHnHc,10313
281
283
  uncountable/types/api/recipes/get_column_calculation_values.py,sha256=9eqURjD2Mwm2lyV1bJIq66Z7a3enLhhx_scZBt4SYYc,1671
282
284
  uncountable/types/api/recipes/get_curve.py,sha256=C-elYAKcBw7P5bWwN-8p_SWj15l5aBJrKNR8yjphZ-Q,1085
283
285
  uncountable/types/api/recipes/get_recipe_calculations.py,sha256=iBmkhKC1qBFxuPPziM3LD6tGsdsN_xb4NcUaJwF6cHU,1679
284
- uncountable/types/api/recipes/get_recipe_links.py,sha256=Hn35wrJlJHQ00MhpHlva0Oc29Dy0lg013VCW4eWl0SU,1182
286
+ uncountable/types/api/recipes/get_recipe_links.py,sha256=jYygHnuzTzuc_H8AG72Ihrb38kEhtfbVNlb4b7elLfI,1149
285
287
  uncountable/types/api/recipes/get_recipe_names.py,sha256=HXv39OI6GRedSAKOhurEQEY_djaxvJcxlTTWghLgA5I,1274
286
288
  uncountable/types/api/recipes/get_recipe_output_metadata.py,sha256=7lF2cnRsBLPDSsjlNIy-aJ4Dao5-qe7WrNaf4XNmq74,1703
287
289
  uncountable/types/api/recipes/get_recipes_data.py,sha256=srZBvl8dCdoo7yil0D1ohAxnbMaCS28ctCH93NaYQd0,6099
288
- uncountable/types/api/recipes/lock_recipes.py,sha256=G5BAPZe3WUMd2Okc8FC9YJBMrfI0mrD-ZY-6sup9vZg,1613
290
+ uncountable/types/api/recipes/lock_recipes.py,sha256=8z_g5lokbzkATZvN5Vpvx6uXS3xPZN77AP5OhHPsGhc,1581
289
291
  uncountable/types/api/recipes/remove_recipe_from_project.py,sha256=_KWbYnMMEOZAaC_jdXZvCEYXJaVhs3x27ZWlJbq3CV4,1076
290
292
  uncountable/types/api/recipes/set_recipe_inputs.py,sha256=RvWj2SOtcuy_msp9pUjz20O3Y_EjEMKd48o-RhpCDNE,1583
291
293
  uncountable/types/api/recipes/set_recipe_metadata.py,sha256=R4GVqpMJdJuoSXsJx1e4vhmWqKKTPMyPPEArwV45crI,1104
292
294
  uncountable/types/api/recipes/set_recipe_output_annotations.py,sha256=yczFBmuB0grzNWsnXspCPUsDA608M9wGkJ2dugyxG4U,3526
293
295
  uncountable/types/api/recipes/set_recipe_output_file.py,sha256=W_qvEkZxzDczwU9EZ7zKyBmLGnO6GFqMsJ3zwXCnpA0,1502
294
- uncountable/types/api/recipes/set_recipe_outputs.py,sha256=EhcEDuha4fcdN15Cr4LaRHs96gQa3jsjMYNBfpOKI8M,2407
296
+ uncountable/types/api/recipes/set_recipe_outputs.py,sha256=-dwyNp614V7lnUc0dANooy92mgbZ7wgUP3CbnitHDvY,2445
295
297
  uncountable/types/api/recipes/set_recipe_tags.py,sha256=HS5GG-nTy0vTNTANG-ROawku0VhzOs0hIzGKfRFefYY,3098
296
298
  uncountable/types/api/recipes/unarchive_recipes.py,sha256=G0jYuarNZLmTCQ6m5_ZAUwBl4M8_cqKRlP-jMJp-Rcw,1000
297
- uncountable/types/api/recipes/unlock_recipes.py,sha256=D2CyWCt6eO5Fa2pRN4GScF2XT1SjlSWvUiqPiU7Dng8,1290
299
+ uncountable/types/api/recipes/unlock_recipes.py,sha256=QFvz13eJipWQlIRrqOybnIPeJxfR4yZM8yIr841jd28,1258
298
300
  uncountable/types/api/triggers/__init__.py,sha256=gCgbynxG3jA8FQHzercKtrHKHkiIKr8APdZYUniAor8,55
299
301
  uncountable/types/api/triggers/run_trigger.py,sha256=diX1ix_5hkti1F1uYoZhP5iyc6GHAU5coKgqq5syLhI,1059
300
302
  uncountable/types/api/uploader/__init__.py,sha256=gCgbynxG3jA8FQHzercKtrHKHkiIKr8APdZYUniAor8,55
301
303
  uncountable/types/api/uploader/invoke_uploader.py,sha256=-loZzBihKqx63eP-f5RuV1mu6tgkRTZmIc545kklZLk,1273
302
- uncountablepythonsdk-0.0.105.dist-info/METADATA,sha256=Oyif_iWvlqiIP3t3_R7wqIyxBgkF3FN_BmVPxUC1MzI,2112
303
- uncountablepythonsdk-0.0.105.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
304
- uncountablepythonsdk-0.0.105.dist-info/top_level.txt,sha256=1UVGjAU-6hJY9qw2iJ7nCBeEwZ793AEN5ZfKX9A1uj4,31
305
- uncountablepythonsdk-0.0.105.dist-info/RECORD,,
304
+ uncountablepythonsdk-0.0.110.dist-info/METADATA,sha256=o-jC36duA9dF3twDaf-7a1UY5XgfAGbcT7J_PYyw_L4,2112
305
+ uncountablepythonsdk-0.0.110.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
306
+ uncountablepythonsdk-0.0.110.dist-info/top_level.txt,sha256=1UVGjAU-6hJY9qw2iJ7nCBeEwZ793AEN5ZfKX9A1uj4,31
307
+ uncountablepythonsdk-0.0.110.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (76.0.0)
2
+ Generator: setuptools (78.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5