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

@@ -0,0 +1,87 @@
1
+ from dataclasses import dataclass
2
+
3
+ from uncountable.integration.job import JobArguments, WebhookJob, register_job
4
+ from uncountable.types import (
5
+ base_t,
6
+ generic_upload_t,
7
+ identifier_t,
8
+ job_definition_t,
9
+ uploader_t,
10
+ )
11
+
12
+
13
+ @dataclass(kw_only=True)
14
+ class ParsePayload:
15
+ async_job_id: base_t.ObjectId
16
+
17
+
18
+ @register_job
19
+ class ParseExample(WebhookJob[ParsePayload]):
20
+ def run(
21
+ self, args: JobArguments, payload: ParsePayload
22
+ ) -> job_definition_t.JobResult:
23
+ dummy_parsed_file_data: list[uploader_t.ParsedFileData] = [
24
+ uploader_t.ParsedFileData(
25
+ file_name="my_file_to_upload.xlsx",
26
+ file_structures=[
27
+ uploader_t.DataChannel(
28
+ type=uploader_t.StructureElementType.CHANNEL,
29
+ channel=uploader_t.TextChannelData(
30
+ name="column1",
31
+ type=uploader_t.ChannelType.TEXT_CHANNEL,
32
+ data=[
33
+ uploader_t.StringValue(value="value1"),
34
+ uploader_t.StringValue(value="value4"),
35
+ uploader_t.StringValue(value="value7"),
36
+ ],
37
+ ),
38
+ ),
39
+ uploader_t.DataChannel(
40
+ type=uploader_t.StructureElementType.CHANNEL,
41
+ channel=uploader_t.TextChannelData(
42
+ name="column2",
43
+ type=uploader_t.ChannelType.TEXT_CHANNEL,
44
+ data=[
45
+ uploader_t.StringValue(value="value2"),
46
+ uploader_t.StringValue(value="value5"),
47
+ uploader_t.StringValue(value="value8"),
48
+ ],
49
+ ),
50
+ ),
51
+ uploader_t.DataChannel(
52
+ type=uploader_t.StructureElementType.CHANNEL,
53
+ channel=uploader_t.TextChannelData(
54
+ name="column3",
55
+ type=uploader_t.ChannelType.TEXT_CHANNEL,
56
+ data=[
57
+ uploader_t.StringValue(value="value3"),
58
+ uploader_t.StringValue(value="value6"),
59
+ uploader_t.StringValue(value="value9"),
60
+ ],
61
+ ),
62
+ ),
63
+ uploader_t.HeaderEntry(
64
+ type=uploader_t.StructureElementType.HEADER,
65
+ value=uploader_t.TextHeaderData(
66
+ name="file_source",
67
+ type=uploader_t.HeaderType.TEXT_HEADER,
68
+ data=uploader_t.StringValue(value="my_file_to_upload.xlsx"),
69
+ ),
70
+ ),
71
+ ],
72
+ )
73
+ ]
74
+
75
+ args.client.complete_async_parse(
76
+ parsed_file_data=dummy_parsed_file_data,
77
+ async_job_key=identifier_t.IdentifierKeyId(id=payload.async_job_id),
78
+ upload_destination=generic_upload_t.UploadDestinationRecipe(
79
+ recipe_key=identifier_t.IdentifierKeyId(id=1)
80
+ ),
81
+ )
82
+
83
+ return job_definition_t.JobResult(success=True)
84
+
85
+ @property
86
+ def webhook_payload_type(self) -> type:
87
+ return ParsePayload
@@ -2,7 +2,7 @@ from io import BytesIO
2
2
 
3
3
  from uncountable.core.file_upload import DataFileUpload, FileUpload
4
4
  from uncountable.integration.job import JobArguments, RunsheetWebhookJob, register_job
5
- from uncountable.types import entity_t
5
+ from uncountable.types import webhook_job_t
6
6
 
7
7
 
8
8
  @register_job
@@ -11,8 +11,9 @@ class StandardRunsheetGenerator(RunsheetWebhookJob):
11
11
  self,
12
12
  *,
13
13
  args: JobArguments,
14
- entities: list[entity_t.Entity],
14
+ payload: webhook_job_t.RunsheetWebhookPayload,
15
15
  ) -> FileUpload:
16
+ entities = payload.entities
16
17
  args.logger.log_info(f"Generating runsheet for {len(entities)} entities")
17
18
 
18
19
  content = []
@@ -93,3 +93,12 @@ jobs:
93
93
  executor:
94
94
  type: script
95
95
  import_path: example_predictions
96
+ - id: example_parse
97
+ type: webhook
98
+ name: Webhook Parse
99
+ signature_key_secret:
100
+ type: env
101
+ env_key: WH_PARSE_SIGNATURE_KEY
102
+ executor:
103
+ type: script
104
+ import_path: example_parse
@@ -28,7 +28,6 @@ from uncountable.integration.secret_retrieval.retrieve_secret import retrieve_se
28
28
  from uncountable.integration.telemetry import JobLogger
29
29
  from uncountable.types import (
30
30
  base_t,
31
- entity_t,
32
31
  job_definition_t,
33
32
  queued_job_t,
34
33
  webhook_job_t,
@@ -255,13 +254,13 @@ class RunsheetWebhookJob(WebhookJob[webhook_job_t.RunsheetWebhookPayload]):
255
254
  self,
256
255
  *,
257
256
  args: JobArguments,
258
- entities: list[entity_t.Entity],
257
+ payload: webhook_job_t.RunsheetWebhookPayload,
259
258
  ) -> FileUpload: ...
260
259
 
261
260
  def run(
262
261
  self, args: JobArguments, payload: webhook_job_t.RunsheetWebhookPayload
263
262
  ) -> JobResult:
264
- runsheet = self.build_runsheet(args=args, entities=payload.entities)
263
+ runsheet = self.build_runsheet(args=args, payload=payload)
265
264
 
266
265
  files = args.client.upload_files(file_uploads=[runsheet])
267
266
  args.client.complete_async_upload(
@@ -12,7 +12,10 @@ from opentelemetry import _logs, trace
12
12
  from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
13
13
  from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
14
14
  from opentelemetry.sdk._logs import Logger as OTELLogger
15
- from opentelemetry.sdk._logs import LoggerProvider, LogRecord
15
+ from opentelemetry.sdk._logs import (
16
+ LoggerProvider,
17
+ LogRecord,
18
+ )
16
19
  from opentelemetry.sdk._logs.export import BatchLogRecordProcessor, ConsoleLogExporter
17
20
  from opentelemetry.sdk.resources import Attributes, Resource
18
21
  from opentelemetry.sdk.trace import TracerProvider
@@ -95,8 +98,27 @@ class Logger:
95
98
  def current_trace_id(self) -> int | None:
96
99
  return self.current_span.get_span_context().trace_id
97
100
 
98
- def _patch_attributes(self, attributes: Attributes | None) -> Attributes:
99
- return attributes or {}
101
+ def _patch_attributes(
102
+ self,
103
+ attributes: Attributes | None,
104
+ *,
105
+ message: str | None = None,
106
+ severity: LogSeverity | None = None,
107
+ ) -> Attributes:
108
+ patched_attributes = {**(attributes if attributes is not None else {})}
109
+ if message is not None:
110
+ patched_attributes["message"] = message
111
+ elif "body" in patched_attributes:
112
+ patched_attributes["message"] = patched_attributes["body"]
113
+
114
+ if severity is not None:
115
+ patched_attributes["status"] = severity.lower()
116
+ elif "severity_text" in patched_attributes and isinstance(
117
+ patched_attributes["severity_text"], str
118
+ ):
119
+ patched_attributes["status"] = patched_attributes["severity_text"].lower()
120
+
121
+ return patched_attributes
100
122
 
101
123
  def _emit_log(
102
124
  self, message: str, *, severity: LogSeverity, attributes: Attributes | None
@@ -106,7 +128,9 @@ class Logger:
106
128
  body=message,
107
129
  severity_text=severity,
108
130
  timestamp=time.time_ns(),
109
- attributes=self._patch_attributes(attributes),
131
+ attributes=self._patch_attributes(
132
+ message=message, severity=severity, attributes=attributes
133
+ ),
110
134
  span_id=self.current_span_id,
111
135
  trace_id=self.current_trace_id,
112
136
  trace_flags=DEFAULT_TRACE_OPTIONS,
@@ -140,7 +164,9 @@ class Logger:
140
164
  attributes: Attributes | None = None,
141
165
  ) -> None:
142
166
  traceback_str = "".join(traceback.format_exception(exception))
143
- patched_attributes = self._patch_attributes(attributes)
167
+ patched_attributes = self._patch_attributes(
168
+ message=message, severity=LogSeverity.ERROR, attributes=attributes
169
+ )
144
170
  self.current_span.record_exception(
145
171
  exception=exception, attributes=patched_attributes
146
172
  )
@@ -171,9 +197,17 @@ class JobLogger(Logger):
171
197
  self.job_definition = job_definition
172
198
  super().__init__(base_span)
173
199
 
174
- def _patch_attributes(self, attributes: Attributes | None) -> Attributes:
200
+ def _patch_attributes(
201
+ self,
202
+ attributes: Attributes | None,
203
+ *,
204
+ message: str | None = None,
205
+ severity: LogSeverity | None = None,
206
+ ) -> Attributes:
175
207
  patched_attributes: dict[str, base_t.JsonValue] = {
176
- **(attributes if attributes is not None else {})
208
+ **super()._patch_attributes(
209
+ attributes=attributes, message=message, severity=severity
210
+ )
177
211
  }
178
212
  patched_attributes["profile.name"] = self.profile_metadata.name
179
213
  patched_attributes["profile.base_url"] = self.profile_metadata.base_url
@@ -537,7 +537,7 @@ class ClientMethods(ABC):
537
537
  recipe_definitions: list[create_recipes_t.CreateRecipeDefinition],
538
538
  project_id: base_t.ObjectId | None = None,
539
539
  ) -> create_recipes_t.Data:
540
- """Sets inputs values for an experiment. Values set can be numeric, text or categorical types in the Uncountable system
540
+ """Creates recipes in Uncountable, optionally with metadata values, and returns the resulting ids in corresponding order
541
541
 
542
542
  :param material_family_id: The identifier of the material family to create the recipes in
543
543
  :param project_id: The identifier of the project to create the recipes in
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: UncountablePythonSDK
3
- Version: 0.0.127
3
+ Version: 0.0.128
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
@@ -32,10 +32,11 @@ examples/integration-server/jobs/materials_auto/concurrent_cron.py,sha256=xsK3H9
32
32
  examples/integration-server/jobs/materials_auto/example_cron.py,sha256=spUMiiTEFaepbVXecjD_4aEEfqEtZGGZuWTKs9J6Xcw,736
33
33
  examples/integration-server/jobs/materials_auto/example_http.py,sha256=eIL46ElWo8SKY7W5JWWkwZk6Qo7KRd9EJBxfy7YQ_sE,1429
34
34
  examples/integration-server/jobs/materials_auto/example_instrument.py,sha256=R2iIRs-2a_9S0LOE42RhglDpZhRkMEa6pCPCxMdqRoI,3438
35
+ examples/integration-server/jobs/materials_auto/example_parse.py,sha256=Rf1tlUoIaY5Py12NhnXzsiZerbTwvX_EdcGUABGv-qI,3489
35
36
  examples/integration-server/jobs/materials_auto/example_predictions.py,sha256=8eiKNq9rocOceLrfqbTop3iwXgIr25NTfjXXKBKIVfI,2104
36
- examples/integration-server/jobs/materials_auto/example_runsheet_wh.py,sha256=_wILTnbzzLf9zrcQb_KQKytxxcya1ej6MqQnoUSS4fA,1180
37
+ examples/integration-server/jobs/materials_auto/example_runsheet_wh.py,sha256=Mhh3PM1j_M35UnMllYNLbTvpMoIcoMOoHIPDaabN_hs,1235
37
38
  examples/integration-server/jobs/materials_auto/example_wh.py,sha256=PN-skP27yJwDZboWk5g5EZEc3AKfVayQLfnopjsDKJc,659
38
- examples/integration-server/jobs/materials_auto/profile.yaml,sha256=UUGzSBbP56_40d5wZdxvaYLwF_N_GWsyk7abarHSKfg,2159
39
+ examples/integration-server/jobs/materials_auto/profile.yaml,sha256=ywDrDRAyqiUdj_HvosNP5bXBL8mCWsvdJ1eYQd-mGYo,2369
39
40
  pkgs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
41
  pkgs/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
42
  pkgs/argument_parser/__init__.py,sha256=EG3pwLEHTp-Qltd3lRnO4K22RiVrasePzKPDOfTPxFY,924
@@ -110,11 +111,11 @@ uncountable/integration/cli.py,sha256=sCE0Cz4tMzlzgD3-3P7XmgTUTBinR_yeNkaC-vvPZG
110
111
  uncountable/integration/construct_client.py,sha256=I53mGcdS88hba3HFwgXmWQaTd1d5u0jWNSwyc_vlVsQ,1937
111
112
  uncountable/integration/cron.py,sha256=6eH-kIs3sdYPCyb62_L2M7U_uQTdMTdwY5hreEJb0hw,887
112
113
  uncountable/integration/entrypoint.py,sha256=BHOYPQgKvZE6HG8Rv15MkdYl8lRkvfDgv1OdLo0oQ9Q,433
113
- uncountable/integration/job.py,sha256=Dw45m-27W4-l0TPAJO05qtwoCYJ6k9lkyqsRqLiOgd8,8247
114
+ uncountable/integration/job.py,sha256=brXg6cod4eKNfgPB1J6a0hnrWOrJxRRF571shvxHBw8,8237
114
115
  uncountable/integration/scan_profiles.py,sha256=RHBmPc5E10YZzf4cmglwrn2yAy0jHBhQ-P_GlAk2TeU,2919
115
116
  uncountable/integration/scheduler.py,sha256=vJQGpuMgryFp5aCQEg5BIvywnu4t3SSFcGoLfY10LKg,6610
116
117
  uncountable/integration/server.py,sha256=fU7d26546WA-IRwL8wqWM62ogx28YvTmNd9kQ7c56WI,5787
117
- uncountable/integration/telemetry.py,sha256=5nA_DwqLOBxDdV4cl8Ybo6I6GiJDTdqETlP5Y81SCWg,7633
118
+ uncountable/integration/telemetry.py,sha256=bWfOm4B_ajen4WWIz6tYJSUBGAw3O7nyvhh9Zr3lV9g,8692
118
119
  uncountable/integration/db/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
119
120
  uncountable/integration/db/connect.py,sha256=mE3bdV0huclH2iT_dXCQdRL4LkjIuf_myAR64RTWXEs,498
120
121
  uncountable/integration/db/session.py,sha256=96cGQXpe6IugBTdSsjdP0S5yhJ6toSmbVB6qhc3FJzE,693
@@ -160,7 +161,7 @@ uncountable/types/calculations.py,sha256=fApOFpgBemt_t7IVneVR0VdI3X5EOxiG6Xhzr6R
160
161
  uncountable/types/calculations_t.py,sha256=pl-lhjyDQuj11Sf9g1-0BsSkN7Ez8UxDp8-KMQ_3enM,709
161
162
  uncountable/types/chemical_structure.py,sha256=ujyragaD26-QG5jgKnWhO7TN3N1V9b_04T2WhqNYxxo,281
162
163
  uncountable/types/chemical_structure_t.py,sha256=VFFyits_vx4t5L2euu_qFiSpsGJjURkDPr3ISnr3nPc,855
163
- uncountable/types/client_base.py,sha256=QsZjHQcC5UjUp8IisCfFbxeDY4y-nitVvnGz-wKInao,81358
164
+ uncountable/types/client_base.py,sha256=2HCcT8J0Fb8DXlubq1vLHoCA-LQuki6hpLN3I8Z8p3Y,81359
164
165
  uncountable/types/client_config.py,sha256=qLpHt4O_B098CyN6qQajoxZ2zjZ1DILXLUEGyyGP0TQ,280
165
166
  uncountable/types/client_config_t.py,sha256=yTFIYAitMrcc4oV9J-HADODS_Hwi45z-piz7rr7QT04,781
166
167
  uncountable/types/curves.py,sha256=QyEyC20jsG-LGKVx6miiF-w70vKMwNkILFBDIJ5Ok9g,345
@@ -344,7 +345,7 @@ uncountable/types/api/uploader/complete_async_parse.py,sha256=nYYBzjT_j4L7_1Ge-i
344
345
  uncountable/types/api/uploader/invoke_uploader.py,sha256=Bj7Dq4A90k00suacwk3bLA_dCb2aovS1kAbVam2AQnM,1395
345
346
  uncountable/types/api/user/__init__.py,sha256=gCgbynxG3jA8FQHzercKtrHKHkiIKr8APdZYUniAor8,55
346
347
  uncountable/types/api/user/get_current_user_info.py,sha256=Avqi_RXtRgbefrT_dwJ9MrO6eDNSSa_Nu650FSuESlg,1109
347
- uncountablepythonsdk-0.0.127.dist-info/METADATA,sha256=Uo7ChDUUJmbkJ28wK_WImk8zV4-9868wpQbmT67dPGg,2174
348
- uncountablepythonsdk-0.0.127.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
349
- uncountablepythonsdk-0.0.127.dist-info/top_level.txt,sha256=1UVGjAU-6hJY9qw2iJ7nCBeEwZ793AEN5ZfKX9A1uj4,31
350
- uncountablepythonsdk-0.0.127.dist-info/RECORD,,
348
+ uncountablepythonsdk-0.0.128.dist-info/METADATA,sha256=J7DAPIol3tInaykdWto7qqNgzTU7-ZbeMCks78LgUXs,2174
349
+ uncountablepythonsdk-0.0.128.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
350
+ uncountablepythonsdk-0.0.128.dist-info/top_level.txt,sha256=1UVGjAU-6hJY9qw2iJ7nCBeEwZ793AEN5ZfKX9A1uj4,31
351
+ uncountablepythonsdk-0.0.128.dist-info/RECORD,,