UncountablePythonSDK 0.0.115__py3-none-any.whl → 0.0.142.dev0__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 (119) hide show
  1. docs/conf.py +52 -5
  2. docs/index.md +107 -4
  3. docs/integration_examples/create_ingredient.md +43 -0
  4. docs/integration_examples/create_output.md +56 -0
  5. docs/integration_examples/index.md +6 -0
  6. docs/justfile +1 -1
  7. docs/requirements.txt +3 -2
  8. examples/basic_auth.py +7 -0
  9. examples/integration-server/jobs/materials_auto/example_cron.py +3 -0
  10. examples/integration-server/jobs/materials_auto/example_http.py +19 -7
  11. examples/integration-server/jobs/materials_auto/example_instrument.py +100 -0
  12. examples/integration-server/jobs/materials_auto/example_parse.py +140 -0
  13. examples/integration-server/jobs/materials_auto/example_predictions.py +61 -0
  14. examples/integration-server/jobs/materials_auto/example_runsheet_wh.py +57 -16
  15. examples/integration-server/jobs/materials_auto/profile.yaml +27 -0
  16. examples/integration-server/pyproject.toml +4 -4
  17. examples/oauth.py +7 -0
  18. pkgs/argument_parser/__init__.py +1 -0
  19. pkgs/argument_parser/_is_namedtuple.py +3 -0
  20. pkgs/argument_parser/argument_parser.py +22 -3
  21. pkgs/serialization_util/serialization_helpers.py +3 -1
  22. pkgs/type_spec/builder.py +66 -19
  23. pkgs/type_spec/builder_types.py +9 -0
  24. pkgs/type_spec/config.py +26 -5
  25. pkgs/type_spec/cross_output_links.py +10 -16
  26. pkgs/type_spec/emit_open_api.py +72 -22
  27. pkgs/type_spec/emit_open_api_util.py +1 -0
  28. pkgs/type_spec/emit_python.py +76 -12
  29. pkgs/type_spec/emit_typescript.py +48 -32
  30. pkgs/type_spec/emit_typescript_util.py +44 -6
  31. pkgs/type_spec/load_types.py +2 -2
  32. pkgs/type_spec/open_api_util.py +16 -1
  33. pkgs/type_spec/parts/base.ts.prepart +4 -0
  34. pkgs/type_spec/type_info/emit_type_info.py +37 -4
  35. pkgs/type_spec/ui_entry_actions/generate_ui_entry_actions.py +1 -0
  36. pkgs/type_spec/value_spec/__main__.py +2 -2
  37. pkgs/type_spec/value_spec/emit_python.py +6 -1
  38. uncountable/core/client.py +10 -3
  39. uncountable/integration/cli.py +175 -23
  40. uncountable/integration/executors/executors.py +1 -2
  41. uncountable/integration/executors/generic_upload_executor.py +1 -1
  42. uncountable/integration/http_server/types.py +3 -1
  43. uncountable/integration/job.py +35 -3
  44. uncountable/integration/queue_runner/command_server/__init__.py +4 -0
  45. uncountable/integration/queue_runner/command_server/command_client.py +89 -0
  46. uncountable/integration/queue_runner/command_server/command_server.py +117 -5
  47. uncountable/integration/queue_runner/command_server/constants.py +4 -0
  48. uncountable/integration/queue_runner/command_server/protocol/command_server.proto +51 -0
  49. uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.py +34 -11
  50. uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.pyi +102 -1
  51. uncountable/integration/queue_runner/command_server/protocol/command_server_pb2_grpc.py +180 -0
  52. uncountable/integration/queue_runner/command_server/types.py +44 -1
  53. uncountable/integration/queue_runner/datastore/datastore_sqlite.py +189 -8
  54. uncountable/integration/queue_runner/datastore/interface.py +13 -0
  55. uncountable/integration/queue_runner/datastore/model.py +8 -1
  56. uncountable/integration/queue_runner/job_scheduler.py +85 -21
  57. uncountable/integration/queue_runner/queue_runner.py +10 -2
  58. uncountable/integration/queue_runner/types.py +2 -0
  59. uncountable/integration/queue_runner/worker.py +28 -29
  60. uncountable/integration/scheduler.py +121 -23
  61. uncountable/integration/server.py +36 -6
  62. uncountable/integration/telemetry.py +129 -8
  63. uncountable/integration/webhook_server/entrypoint.py +2 -0
  64. uncountable/types/__init__.py +38 -0
  65. uncountable/types/api/entity/create_or_update_entity.py +1 -0
  66. uncountable/types/api/entity/export_entities.py +13 -0
  67. uncountable/types/api/entity/list_aggregate.py +79 -0
  68. uncountable/types/api/entity/list_entities.py +25 -0
  69. uncountable/types/api/entity/set_barcode.py +43 -0
  70. uncountable/types/api/entity/transition_entity_phase.py +2 -1
  71. uncountable/types/api/files/download_file.py +15 -1
  72. uncountable/types/api/integrations/__init__.py +1 -0
  73. uncountable/types/api/integrations/publish_realtime_data.py +41 -0
  74. uncountable/types/api/integrations/push_notification.py +49 -0
  75. uncountable/types/api/integrations/register_sockets_token.py +41 -0
  76. uncountable/types/api/listing/__init__.py +1 -0
  77. uncountable/types/api/listing/fetch_listing.py +57 -0
  78. uncountable/types/api/notebooks/__init__.py +1 -0
  79. uncountable/types/api/notebooks/add_notebook_content.py +119 -0
  80. uncountable/types/api/outputs/get_output_organization.py +173 -0
  81. uncountable/types/api/recipes/edit_recipe_inputs.py +1 -1
  82. uncountable/types/api/recipes/get_recipe_output_metadata.py +2 -2
  83. uncountable/types/api/recipes/get_recipes_data.py +29 -0
  84. uncountable/types/api/recipes/lock_recipes.py +2 -1
  85. uncountable/types/api/recipes/set_recipe_total.py +59 -0
  86. uncountable/types/api/recipes/unlock_recipes.py +2 -1
  87. uncountable/types/api/runsheet/export_default_runsheet.py +44 -0
  88. uncountable/types/api/uploader/complete_async_parse.py +46 -0
  89. uncountable/types/api/user/__init__.py +1 -0
  90. uncountable/types/api/user/get_current_user_info.py +40 -0
  91. uncountable/types/async_batch_processor.py +266 -0
  92. uncountable/types/async_batch_t.py +5 -0
  93. uncountable/types/client_base.py +432 -2
  94. uncountable/types/client_config.py +1 -0
  95. uncountable/types/client_config_t.py +10 -0
  96. uncountable/types/entity_t.py +9 -1
  97. uncountable/types/exports_t.py +1 -0
  98. uncountable/types/integration_server_t.py +2 -0
  99. uncountable/types/integration_session.py +10 -0
  100. uncountable/types/integration_session_t.py +60 -0
  101. uncountable/types/integrations.py +10 -0
  102. uncountable/types/integrations_t.py +62 -0
  103. uncountable/types/listing.py +46 -0
  104. uncountable/types/listing_t.py +533 -0
  105. uncountable/types/notices.py +8 -0
  106. uncountable/types/notices_t.py +37 -0
  107. uncountable/types/notifications.py +11 -0
  108. uncountable/types/notifications_t.py +74 -0
  109. uncountable/types/queued_job.py +2 -0
  110. uncountable/types/queued_job_t.py +20 -2
  111. uncountable/types/sockets.py +20 -0
  112. uncountable/types/sockets_t.py +169 -0
  113. uncountable/types/uploader.py +24 -0
  114. uncountable/types/uploader_t.py +222 -0
  115. {uncountablepythonsdk-0.0.115.dist-info → uncountablepythonsdk-0.0.142.dev0.dist-info}/METADATA +5 -2
  116. {uncountablepythonsdk-0.0.115.dist-info → uncountablepythonsdk-0.0.142.dev0.dist-info}/RECORD +118 -79
  117. docs/quickstart.md +0 -19
  118. {uncountablepythonsdk-0.0.115.dist-info → uncountablepythonsdk-0.0.142.dev0.dist-info}/WHEEL +0 -0
  119. {uncountablepythonsdk-0.0.115.dist-info → uncountablepythonsdk-0.0.142.dev0.dist-info}/top_level.txt +0 -0
@@ -1,17 +1,24 @@
1
1
  import functools
2
+ import json
2
3
  import os
4
+ import threading
3
5
  import time
4
6
  import traceback
7
+ import types
5
8
  import typing
6
9
  from contextlib import contextmanager
7
10
  from enum import StrEnum
8
11
  from typing import Generator, assert_never, cast
9
12
 
13
+ import psutil
10
14
  from opentelemetry import _logs, trace
11
15
  from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
12
16
  from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
13
17
  from opentelemetry.sdk._logs import Logger as OTELLogger
14
- from opentelemetry.sdk._logs import LoggerProvider, LogRecord
18
+ from opentelemetry.sdk._logs import (
19
+ LoggerProvider,
20
+ LogRecord,
21
+ )
15
22
  from opentelemetry.sdk._logs.export import BatchLogRecordProcessor, ConsoleLogExporter
16
23
  from opentelemetry.sdk.resources import Attributes, Resource
17
24
  from opentelemetry.sdk.trace import TracerProvider
@@ -32,6 +39,11 @@ def _cast_attributes(attributes: dict[str, base_t.JsonValue]) -> Attributes:
32
39
  return cast(Attributes, attributes)
33
40
 
34
41
 
42
+ def one_line_formatter(record: LogRecord) -> str:
43
+ json_data = record.to_json()
44
+ return json.dumps(json.loads(json_data), separators=(",", ":")) + "\n"
45
+
46
+
35
47
  @functools.cache
36
48
  def get_otel_resource() -> Resource:
37
49
  attributes: dict[str, base_t.JsonValue] = {
@@ -60,7 +72,9 @@ def get_otel_tracer() -> Tracer:
60
72
  @functools.cache
61
73
  def get_otel_logger() -> OTELLogger:
62
74
  provider = LoggerProvider(resource=get_otel_resource())
63
- provider.add_log_record_processor(BatchLogRecordProcessor(ConsoleLogExporter()))
75
+ provider.add_log_record_processor(
76
+ BatchLogRecordProcessor(ConsoleLogExporter(formatter=one_line_formatter))
77
+ )
64
78
  if get_otel_enabled():
65
79
  provider.add_log_record_processor(BatchLogRecordProcessor(OTLPLogExporter()))
66
80
  _logs.set_logger_provider(provider)
@@ -87,8 +101,27 @@ class Logger:
87
101
  def current_trace_id(self) -> int | None:
88
102
  return self.current_span.get_span_context().trace_id
89
103
 
90
- def _patch_attributes(self, attributes: Attributes | None) -> Attributes:
91
- return attributes or {}
104
+ def _patch_attributes(
105
+ self,
106
+ attributes: Attributes | None,
107
+ *,
108
+ message: str | None = None,
109
+ severity: LogSeverity | None = None,
110
+ ) -> Attributes:
111
+ patched_attributes = {**(attributes if attributes is not None else {})}
112
+ if message is not None:
113
+ patched_attributes["message"] = message
114
+ elif "body" in patched_attributes:
115
+ patched_attributes["message"] = patched_attributes["body"]
116
+
117
+ if severity is not None:
118
+ patched_attributes["status"] = severity.lower()
119
+ elif "severity_text" in patched_attributes and isinstance(
120
+ patched_attributes["severity_text"], str
121
+ ):
122
+ patched_attributes["status"] = patched_attributes["severity_text"].lower()
123
+
124
+ return patched_attributes
92
125
 
93
126
  def _emit_log(
94
127
  self, message: str, *, severity: LogSeverity, attributes: Attributes | None
@@ -98,7 +131,9 @@ class Logger:
98
131
  body=message,
99
132
  severity_text=severity,
100
133
  timestamp=time.time_ns(),
101
- attributes=self._patch_attributes(attributes),
134
+ attributes=self._patch_attributes(
135
+ message=message, severity=severity, attributes=attributes
136
+ ),
102
137
  span_id=self.current_span_id,
103
138
  trace_id=self.current_trace_id,
104
139
  trace_flags=DEFAULT_TRACE_OPTIONS,
@@ -132,7 +167,9 @@ class Logger:
132
167
  attributes: Attributes | None = None,
133
168
  ) -> None:
134
169
  traceback_str = "".join(traceback.format_exception(exception))
135
- patched_attributes = self._patch_attributes(attributes)
170
+ patched_attributes = self._patch_attributes(
171
+ message=message, severity=LogSeverity.ERROR, attributes=attributes
172
+ )
136
173
  self.current_span.record_exception(
137
174
  exception=exception, attributes=patched_attributes
138
175
  )
@@ -151,6 +188,76 @@ class Logger:
151
188
  yield self
152
189
 
153
190
 
191
+ class PerJobResourceTracker:
192
+ def __init__(self, logger: "JobLogger", sample_interval: float = 0.5) -> None:
193
+ self.logger = logger
194
+ self.sample_interval = sample_interval
195
+ self._process = psutil.Process(os.getpid())
196
+ self._stop_event = threading.Event()
197
+ self._thread: threading.Thread | None = None
198
+
199
+ self.max_rss: int = 0
200
+ self.start_cpu_times: psutil._common.pcputimes | None = None
201
+ self.end_cpu_times: psutil._common.pcputimes | None = None
202
+ self.start_wall_time: float | None = None
203
+ self.end_wall_time: float | None = None
204
+
205
+ def start(self) -> None:
206
+ self.start_cpu_times = self._process.cpu_times()
207
+ self.start_wall_time = time.monotonic()
208
+
209
+ def _monitor() -> None:
210
+ try:
211
+ while not self._stop_event.is_set():
212
+ rss = self._process.memory_info().rss
213
+ self.max_rss = max(self.max_rss, rss)
214
+ time.sleep(self.sample_interval)
215
+ except Exception:
216
+ self._stop_event.set()
217
+
218
+ self._thread = threading.Thread(target=_monitor, daemon=True)
219
+ self._thread.start()
220
+
221
+ def stop(self) -> None:
222
+ self._stop_event.set()
223
+ if self._thread is not None:
224
+ self._thread.join()
225
+ self.end_cpu_times = self._process.cpu_times()
226
+ self.end_wall_time = time.monotonic()
227
+
228
+ def __enter__(self) -> typing.Self:
229
+ self.start()
230
+ return self
231
+
232
+ def __exit__(
233
+ self,
234
+ exc_type: type[BaseException] | None,
235
+ exc_value: BaseException | None,
236
+ traceback: types.TracebackType | None,
237
+ ) -> None:
238
+ self.stop()
239
+ stats = dict(self.summary())
240
+ self.logger.log_info("Job resource usage summary", attributes=stats)
241
+
242
+ def summary(self) -> Attributes:
243
+ assert self.start_cpu_times is not None
244
+ assert self.end_cpu_times is not None
245
+ assert self.start_wall_time is not None
246
+ assert self.end_wall_time is not None
247
+
248
+ cpu_user = self.end_cpu_times.user - self.start_cpu_times.user
249
+ cpu_sys = self.end_cpu_times.system - self.start_cpu_times.system
250
+ cpu_total = cpu_user + cpu_sys
251
+ elapsed = self.end_wall_time - self.start_wall_time
252
+ return {
253
+ "cpu_user_s": round(cpu_user, 3),
254
+ "cpu_system_s": round(cpu_sys, 3),
255
+ "cpu_total_s": round(cpu_total, 3),
256
+ "wall_time_s": round(elapsed, 3),
257
+ "peak_rss_mb": round(self.max_rss / (1024 * 1024), 2),
258
+ }
259
+
260
+
154
261
  class JobLogger(Logger):
155
262
  def __init__(
156
263
  self,
@@ -158,20 +265,31 @@ class JobLogger(Logger):
158
265
  base_span: Span,
159
266
  profile_metadata: job_definition_t.ProfileMetadata,
160
267
  job_definition: job_definition_t.JobDefinition,
268
+ queued_job_uuid: str,
161
269
  ) -> None:
162
270
  self.profile_metadata = profile_metadata
163
271
  self.job_definition = job_definition
272
+ self.queued_job_uuid = queued_job_uuid
164
273
  super().__init__(base_span)
165
274
 
166
- def _patch_attributes(self, attributes: Attributes | None) -> Attributes:
275
+ def _patch_attributes(
276
+ self,
277
+ attributes: Attributes | None,
278
+ *,
279
+ message: str | None = None,
280
+ severity: LogSeverity | None = None,
281
+ ) -> Attributes:
167
282
  patched_attributes: dict[str, base_t.JsonValue] = {
168
- **(attributes if attributes is not None else {})
283
+ **super()._patch_attributes(
284
+ attributes=attributes, message=message, severity=severity
285
+ )
169
286
  }
170
287
  patched_attributes["profile.name"] = self.profile_metadata.name
171
288
  patched_attributes["profile.base_url"] = self.profile_metadata.base_url
172
289
  patched_attributes["job.name"] = self.job_definition.name
173
290
  patched_attributes["job.id"] = self.job_definition.id
174
291
  patched_attributes["job.definition_type"] = self.job_definition.type
292
+ patched_attributes["job.queued_job_uuid"] = self.queued_job_uuid
175
293
  match self.job_definition:
176
294
  case job_definition_t.CronJobDefinition():
177
295
  patched_attributes["job.definition.cron_spec"] = (
@@ -197,6 +315,9 @@ class JobLogger(Logger):
197
315
  assert_never(self.job_definition.executor)
198
316
  return _cast_attributes(patched_attributes)
199
317
 
318
+ def resource_tracking(self) -> PerJobResourceTracker:
319
+ return PerJobResourceTracker(self)
320
+
200
321
 
201
322
  @contextmanager
202
323
  def push_scope_optional(
@@ -73,6 +73,8 @@ def register_route(
73
73
 
74
74
 
75
75
  def main() -> None:
76
+ app.add_url_rule("/health", "health", lambda: ("OK", 200))
77
+
76
78
  profiles = load_profiles()
77
79
  for profile_metadata in profiles:
78
80
  server_logger = Logger(get_current_span())
@@ -2,6 +2,7 @@
2
2
  # ruff: noqa: E402 Q003
3
3
  # fmt: off
4
4
  # isort: skip_file
5
+ from .api.notebooks import add_notebook_content as add_notebook_content_t
5
6
  from .api.recipes import add_recipe_to_project as add_recipe_to_project_t
6
7
  from .api.recipes import add_time_series_data as add_time_series_data_t
7
8
  from .api.recipes import archive_recipes as archive_recipes_t
@@ -16,6 +17,7 @@ from . import calculations_t as calculations_t
16
17
  from . import chemical_structure_t as chemical_structure_t
17
18
  from .api.recipes import clear_recipe_outputs as clear_recipe_outputs_t
18
19
  from . import client_config_t as client_config_t
20
+ from .api.uploader import complete_async_parse as complete_async_parse_t
19
21
  from .api.runsheet import complete_async_upload as complete_async_upload_t
20
22
  from .api.chemical import convert_chemical_formats as convert_chemical_formats_t
21
23
  from .api.entity import create_entities as create_entities_t
@@ -35,12 +37,15 @@ from . import entity_t as entity_t
35
37
  from .api.batch import execute_batch as execute_batch_t
36
38
  from .api.batch import execute_batch_load_async as execute_batch_load_async_t
37
39
  from . import experiment_groups_t as experiment_groups_t
40
+ from .api.runsheet import export_default_runsheet as export_default_runsheet_t
38
41
  from .api.entity import export_entities as export_entities_t
39
42
  from . import exports_t as exports_t
43
+ from .api.listing import fetch_listing as fetch_listing_t
40
44
  from . import field_values_t as field_values_t
41
45
  from . import fields_t as fields_t
42
46
  from . import generic_upload_t as generic_upload_t
43
47
  from .api.recipes import get_column_calculation_values as get_column_calculation_values_t
48
+ from .api.user import get_current_user_info as get_current_user_info_t
44
49
  from .api.recipes import get_curve as get_curve_t
45
50
  from .api.entity import get_entities_data as get_entities_data_t
46
51
  from .api.inputs import get_input_data as get_input_data_t
@@ -49,6 +54,7 @@ from .api.inputs import get_input_names as get_input_names_t
49
54
  from .api.inputs import get_inputs_data as get_inputs_data_t
50
55
  from .api.outputs import get_output_data as get_output_data_t
51
56
  from .api.outputs import get_output_names as get_output_names_t
57
+ from .api.outputs import get_output_organization as get_output_organization_t
52
58
  from .api.project import get_projects as get_projects_t
53
59
  from .api.project import get_projects_data as get_projects_data_t
54
60
  from .api.recipes import get_recipe_calculations as get_recipe_calculations_t
@@ -63,19 +69,27 @@ from . import identifier_t as identifier_t
63
69
  from . import input_attributes_t as input_attributes_t
64
70
  from . import inputs_t as inputs_t
65
71
  from . import integration_server_t as integration_server_t
72
+ from . import integration_session_t as integration_session_t
73
+ from . import integrations_t as integrations_t
66
74
  from .api.uploader import invoke_uploader as invoke_uploader_t
67
75
  from . import job_definition_t as job_definition_t
76
+ from .api.entity import list_aggregate as list_aggregate_t
68
77
  from .api.entity import list_entities as list_entities_t
69
78
  from .api.id_source import list_id_source as list_id_source_t
79
+ from . import listing_t as listing_t
70
80
  from .api.entity import lock_entity as lock_entity_t
71
81
  from .api.recipes import lock_recipes as lock_recipes_t
72
82
  from .api.entity import lookup_entity as lookup_entity_t
73
83
  from .api.id_source import match_id_source as match_id_source_t
84
+ from . import notices_t as notices_t
85
+ from . import notifications_t as notifications_t
74
86
  from . import outputs_t as outputs_t
75
87
  from . import overrides_t as overrides_t
76
88
  from . import permissions_t as permissions_t
77
89
  from . import phases_t as phases_t
78
90
  from . import post_base_t as post_base_t
91
+ from .api.integrations import publish_realtime_data as publish_realtime_data_t
92
+ from .api.integrations import push_notification as push_notification_t
79
93
  from . import queued_job_t as queued_job_t
80
94
  from . import recipe_identifiers_t as recipe_identifiers_t
81
95
  from . import recipe_inputs_t as recipe_inputs_t
@@ -85,6 +99,7 @@ from . import recipe_output_metadata_t as recipe_output_metadata_t
85
99
  from . import recipe_tags_t as recipe_tags_t
86
100
  from . import recipe_workflow_steps_t as recipe_workflow_steps_t
87
101
  from . import recipes_t as recipes_t
102
+ from .api.integrations import register_sockets_token as register_sockets_token_t
88
103
  from .api.recipes import remove_recipe_from_project as remove_recipe_from_project_t
89
104
  from .api.recipe_links import remove_recipe_link as remove_recipe_link_t
90
105
  from .api.entity import resolve_entity_ids as resolve_entity_ids_t
@@ -92,6 +107,7 @@ from .api.outputs import resolve_output_conditions as resolve_output_conditions_
92
107
  from . import response_t as response_t
93
108
  from .api.triggers import run_trigger as run_trigger_t
94
109
  from . import secret_retrieval_t as secret_retrieval_t
110
+ from .api.entity import set_barcode as set_barcode_t
95
111
  from .api.permissions import set_core_permissions as set_core_permissions_t
96
112
  from .api.entity import set_entity_field_values as set_entity_field_values_t
97
113
  from .api.inputs import set_input_attribute_values as set_input_attribute_values_t
@@ -104,13 +120,16 @@ from .api.recipes import set_recipe_output_annotations as set_recipe_output_anno
104
120
  from .api.recipes import set_recipe_output_file as set_recipe_output_file_t
105
121
  from .api.recipes import set_recipe_outputs as set_recipe_outputs_t
106
122
  from .api.recipes import set_recipe_tags as set_recipe_tags_t
123
+ from .api.recipes import set_recipe_total as set_recipe_total_t
107
124
  from .api.entity import set_values as set_values_t
125
+ from . import sockets_t as sockets_t
108
126
  from .api.entity import transition_entity_phase as transition_entity_phase_t
109
127
  from .api.recipes import unarchive_recipes as unarchive_recipes_t
110
128
  from . import units_t as units_t
111
129
  from .api.entity import unlock_entity as unlock_entity_t
112
130
  from .api.recipes import unlock_recipes as unlock_recipes_t
113
131
  from .api.material_families import update_entity_material_families as update_entity_material_families_t
132
+ from . import uploader_t as uploader_t
114
133
  from .api.condition_parameters import upsert_condition_match as upsert_condition_match_t
115
134
  from .api.field_options import upsert_field_options as upsert_field_options_t
116
135
  from . import users_t as users_t
@@ -119,6 +138,7 @@ from . import workflows_t as workflows_t
119
138
 
120
139
 
121
140
  __all__: list[str] = [
141
+ "add_notebook_content_t",
122
142
  "add_recipe_to_project_t",
123
143
  "add_time_series_data_t",
124
144
  "archive_recipes_t",
@@ -133,6 +153,7 @@ __all__: list[str] = [
133
153
  "chemical_structure_t",
134
154
  "clear_recipe_outputs_t",
135
155
  "client_config_t",
156
+ "complete_async_parse_t",
136
157
  "complete_async_upload_t",
137
158
  "convert_chemical_formats_t",
138
159
  "create_entities_t",
@@ -152,12 +173,15 @@ __all__: list[str] = [
152
173
  "execute_batch_t",
153
174
  "execute_batch_load_async_t",
154
175
  "experiment_groups_t",
176
+ "export_default_runsheet_t",
155
177
  "export_entities_t",
156
178
  "exports_t",
179
+ "fetch_listing_t",
157
180
  "field_values_t",
158
181
  "fields_t",
159
182
  "generic_upload_t",
160
183
  "get_column_calculation_values_t",
184
+ "get_current_user_info_t",
161
185
  "get_curve_t",
162
186
  "get_entities_data_t",
163
187
  "get_input_data_t",
@@ -166,6 +190,7 @@ __all__: list[str] = [
166
190
  "get_inputs_data_t",
167
191
  "get_output_data_t",
168
192
  "get_output_names_t",
193
+ "get_output_organization_t",
169
194
  "get_projects_t",
170
195
  "get_projects_data_t",
171
196
  "get_recipe_calculations_t",
@@ -180,19 +205,27 @@ __all__: list[str] = [
180
205
  "input_attributes_t",
181
206
  "inputs_t",
182
207
  "integration_server_t",
208
+ "integration_session_t",
209
+ "integrations_t",
183
210
  "invoke_uploader_t",
184
211
  "job_definition_t",
212
+ "list_aggregate_t",
185
213
  "list_entities_t",
186
214
  "list_id_source_t",
215
+ "listing_t",
187
216
  "lock_entity_t",
188
217
  "lock_recipes_t",
189
218
  "lookup_entity_t",
190
219
  "match_id_source_t",
220
+ "notices_t",
221
+ "notifications_t",
191
222
  "outputs_t",
192
223
  "overrides_t",
193
224
  "permissions_t",
194
225
  "phases_t",
195
226
  "post_base_t",
227
+ "publish_realtime_data_t",
228
+ "push_notification_t",
196
229
  "queued_job_t",
197
230
  "recipe_identifiers_t",
198
231
  "recipe_inputs_t",
@@ -202,6 +235,7 @@ __all__: list[str] = [
202
235
  "recipe_tags_t",
203
236
  "recipe_workflow_steps_t",
204
237
  "recipes_t",
238
+ "register_sockets_token_t",
205
239
  "remove_recipe_from_project_t",
206
240
  "remove_recipe_link_t",
207
241
  "resolve_entity_ids_t",
@@ -209,6 +243,7 @@ __all__: list[str] = [
209
243
  "response_t",
210
244
  "run_trigger_t",
211
245
  "secret_retrieval_t",
246
+ "set_barcode_t",
212
247
  "set_core_permissions_t",
213
248
  "set_entity_field_values_t",
214
249
  "set_input_attribute_values_t",
@@ -221,13 +256,16 @@ __all__: list[str] = [
221
256
  "set_recipe_output_file_t",
222
257
  "set_recipe_outputs_t",
223
258
  "set_recipe_tags_t",
259
+ "set_recipe_total_t",
224
260
  "set_values_t",
261
+ "sockets_t",
225
262
  "transition_entity_phase_t",
226
263
  "unarchive_recipes_t",
227
264
  "units_t",
228
265
  "unlock_entity_t",
229
266
  "unlock_recipes_t",
230
267
  "update_entity_material_families_t",
268
+ "uploader_t",
231
269
  "upsert_condition_match_t",
232
270
  "upsert_field_options_t",
233
271
  "users_t",
@@ -35,6 +35,7 @@ class Arguments:
35
35
  definition_key: identifier_t.IdentifierKey
36
36
  field_values: list[field_values_t.FieldArgumentValue]
37
37
  entity_key: identifier_t.IdentifierKey | None = None
38
+ on_create_init_field_values: list[field_values_t.FieldArgumentValue] | None = None
38
39
 
39
40
 
40
41
  # DO NOT MODIFY -- This file is generated by type_spec
@@ -18,12 +18,24 @@ __all__: list[str] = [
18
18
  "Data",
19
19
  "ENDPOINT_METHOD",
20
20
  "ENDPOINT_PATH",
21
+ "ListingAttribute",
21
22
  ]
22
23
 
23
24
  ENDPOINT_METHOD = "POST"
24
25
  ENDPOINT_PATH = "api/external/entity/export_entities"
25
26
 
26
27
 
28
+ # DO NOT MODIFY -- This file is generated by type_spec
29
+ @serial_class(
30
+ named_type_path="sdk.api.entity.export_entities.ListingAttribute",
31
+ unconverted_values={"value"},
32
+ )
33
+ @dataclasses.dataclass(slots=base_t.ENABLE_SLOTS, kw_only=True) # type: ignore[literal-required]
34
+ class ListingAttribute:
35
+ key: str
36
+ value: base_t.JsonValue
37
+
38
+
27
39
  # DO NOT MODIFY -- This file is generated by type_spec
28
40
  @serial_class(
29
41
  named_type_path="sdk.api.entity.export_entities.Arguments",
@@ -34,6 +46,7 @@ class Arguments:
34
46
  type: exports_t.ExportType = exports_t.ExportType.EXCEL
35
47
  client_timezone: exports_t.ListingExportUserTimezone | None = None
36
48
  limit: int | None = None
49
+ attributes: list[ListingAttribute] | None = None
37
50
 
38
51
 
39
52
  # DO NOT MODIFY -- This file is generated by type_spec
@@ -0,0 +1,79 @@
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
+ from ... import base_t
12
+
13
+ __all__: list[str] = [
14
+ "Arguments",
15
+ "AttributeValue",
16
+ "ColumnAccess",
17
+ "ColumnResults",
18
+ "Data",
19
+ "ENDPOINT_METHOD",
20
+ "ENDPOINT_PATH",
21
+ ]
22
+
23
+ ENDPOINT_METHOD = "GET"
24
+ ENDPOINT_PATH = "api/external/entity/list_aggregate"
25
+
26
+
27
+ # DO NOT MODIFY -- This file is generated by type_spec
28
+ @serial_class(
29
+ named_type_path="sdk.api.entity.list_aggregate.AttributeValue",
30
+ unconverted_values={"value"},
31
+ )
32
+ @dataclasses.dataclass(slots=base_t.ENABLE_SLOTS, kw_only=True) # type: ignore[literal-required]
33
+ class AttributeValue:
34
+ name: str
35
+ value: base_t.JsonValue
36
+
37
+
38
+ # DO NOT MODIFY -- This file is generated by type_spec
39
+ @serial_class(
40
+ named_type_path="sdk.api.entity.list_aggregate.Arguments",
41
+ unconverted_values={"attribute_values"},
42
+ )
43
+ @dataclasses.dataclass(slots=base_t.ENABLE_SLOTS, kw_only=True) # type: ignore[literal-required]
44
+ class Arguments:
45
+ config_reference: str
46
+ attribute_values: list[AttributeValue] | None = None
47
+ offset: int | None = None
48
+ limit: int | None = None
49
+
50
+
51
+ # DO NOT MODIFY -- This file is generated by type_spec
52
+ @serial_class(
53
+ named_type_path="sdk.api.entity.list_aggregate.ColumnResults",
54
+ unconverted_values={"column_values"},
55
+ )
56
+ @dataclasses.dataclass(slots=base_t.ENABLE_SLOTS, kw_only=True) # type: ignore[literal-required]
57
+ class ColumnResults:
58
+ column_values: list[base_t.JsonValue]
59
+
60
+
61
+ # DO NOT MODIFY -- This file is generated by type_spec
62
+ @serial_class(
63
+ named_type_path="sdk.api.entity.list_aggregate.ColumnAccess",
64
+ )
65
+ @dataclasses.dataclass(slots=base_t.ENABLE_SLOTS, kw_only=True) # type: ignore[literal-required]
66
+ class ColumnAccess:
67
+ name: str
68
+ table_label: str | None
69
+
70
+
71
+ # DO NOT MODIFY -- This file is generated by type_spec
72
+ @serial_class(
73
+ named_type_path="sdk.api.entity.list_aggregate.Data",
74
+ )
75
+ @dataclasses.dataclass(slots=base_t.ENABLE_SLOTS, kw_only=True) # type: ignore[literal-required]
76
+ class Data:
77
+ columns: list[ColumnAccess]
78
+ results: list[ColumnResults]
79
+ # DO NOT MODIFY -- This file is generated by type_spec
@@ -11,9 +11,12 @@ from pkgs.serialization import serial_class
11
11
  from pkgs.serialization import OpaqueKey
12
12
  from ... import base_t
13
13
  from ... import entity_t
14
+ from ... import identifier_t
14
15
 
15
16
  __all__: list[str] = [
17
+ "AdditionalFilterConfig",
16
18
  "Arguments",
19
+ "AttributeValue",
17
20
  "ColumnAccess",
18
21
  "Data",
19
22
  "ENDPOINT_METHOD",
@@ -25,6 +28,27 @@ ENDPOINT_METHOD = "GET"
25
28
  ENDPOINT_PATH = "api/external/entity/external_list_entities"
26
29
 
27
30
 
31
+ # DO NOT MODIFY -- This file is generated by type_spec
32
+ @serial_class(
33
+ named_type_path="sdk.api.entity.list_entities.AttributeValue",
34
+ unconverted_values={"value"},
35
+ )
36
+ @dataclasses.dataclass(slots=base_t.ENABLE_SLOTS, kw_only=True) # type: ignore[literal-required]
37
+ class AttributeValue:
38
+ name: str
39
+ value: base_t.JsonValue
40
+
41
+
42
+ # DO NOT MODIFY -- This file is generated by type_spec
43
+ @serial_class(
44
+ named_type_path="sdk.api.entity.list_entities.AdditionalFilterConfig",
45
+ )
46
+ @dataclasses.dataclass(slots=base_t.ENABLE_SLOTS, kw_only=True) # type: ignore[literal-required]
47
+ class AdditionalFilterConfig:
48
+ config_key: identifier_t.IdentifierKey
49
+ attribute_values: list[AttributeValue] | None = None
50
+
51
+
28
52
  # DO NOT MODIFY -- This file is generated by type_spec
29
53
  @serial_class(
30
54
  named_type_path="sdk.api.entity.list_entities.Arguments",
@@ -37,6 +61,7 @@ class Arguments:
37
61
  attributes: dict[OpaqueKey, base_t.JsonValue] | None = None
38
62
  offset: int | None = None
39
63
  limit: int | None = None
64
+ additional_filter_configs: list[AdditionalFilterConfig] | None = None
40
65
 
41
66
 
42
67
  # DO NOT MODIFY -- This file is generated by type_spec
@@ -0,0 +1,43 @@
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
+ from ... import async_batch_t
12
+ from ... import base_t
13
+ from ... import entity_t
14
+
15
+ __all__: list[str] = [
16
+ "Arguments",
17
+ "Data",
18
+ "ENDPOINT_METHOD",
19
+ "ENDPOINT_PATH",
20
+ ]
21
+
22
+ ENDPOINT_METHOD = "POST"
23
+ ENDPOINT_PATH = "api/external/entity/set_barcode"
24
+
25
+
26
+ # DO NOT MODIFY -- This file is generated by type_spec
27
+ @serial_class(
28
+ named_type_path="sdk.api.entity.set_barcode.Arguments",
29
+ )
30
+ @dataclasses.dataclass(slots=base_t.ENABLE_SLOTS, kw_only=True) # type: ignore[literal-required]
31
+ class Arguments:
32
+ entity_key: entity_t.EntityIdentifier
33
+ barcode_value: str
34
+
35
+
36
+ # DO NOT MODIFY -- This file is generated by type_spec
37
+ @serial_class(
38
+ named_type_path="sdk.api.entity.set_barcode.Data",
39
+ )
40
+ @dataclasses.dataclass(slots=base_t.ENABLE_SLOTS, kw_only=True) # type: ignore[literal-required]
41
+ class Data(async_batch_t.AsyncBatchActionReturn):
42
+ pass
43
+ # DO NOT MODIFY -- This file is generated by type_spec
@@ -66,8 +66,9 @@ TransitionIdentifier = typing.Annotated[
66
66
  )
67
67
  @dataclasses.dataclass(slots=base_t.ENABLE_SLOTS, kw_only=True) # type: ignore[literal-required]
68
68
  class Arguments:
69
- entity: entity_t.Entity
70
69
  transition: TransitionIdentifier
70
+ entity: entity_t.Entity | None = None
71
+ entity_identifier: entity_t.EntityIdentifier | None = None
71
72
 
72
73
 
73
74
  # DO NOT MODIFY -- This file is generated by type_spec