onec-interactive-runtime-core 0.1.19__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.
Files changed (87) hide show
  1. onec_interactive_runtime_core-0.1.19.dist-info/METADATA +12 -0
  2. onec_interactive_runtime_core-0.1.19.dist-info/RECORD +87 -0
  3. onec_interactive_runtime_core-0.1.19.dist-info/WHEEL +4 -0
  4. onec_interactive_runtime_core-0.1.19.dist-info/licenses/COPYRIGHT +9 -0
  5. onec_interactive_runtime_core-0.1.19.dist-info/licenses/LICENSE +232 -0
  6. onec_interactive_runtime_core-0.1.19.dist-info/licenses/THIRD_PARTY_NOTICES.txt +32 -0
  7. onec_runtime/AGENTS.md +7 -0
  8. onec_runtime/__init__.py +3 -0
  9. onec_runtime/artifacts.py +59 -0
  10. onec_runtime/bootstrap.py +310 -0
  11. onec_runtime/breakpoint_workspace.py +249 -0
  12. onec_runtime/bsl/__init__.py +139 -0
  13. onec_runtime/bsl/diagnostics.py +1046 -0
  14. onec_runtime/bsl/full_ast_worker_projection.py +522 -0
  15. onec_runtime/bsl/generated_semantic_parser.py +6322 -0
  16. onec_runtime/bsl/lexer.py +164 -0
  17. onec_runtime/bsl/module_catalog.py +420 -0
  18. onec_runtime/bsl/module_delta.py +1079 -0
  19. onec_runtime/bsl/module_universe.py +1877 -0
  20. onec_runtime/bsl/notebook_cells.py +232 -0
  21. onec_runtime/bsl/notebook_method_globals.py +74 -0
  22. onec_runtime/bsl/notebook_methods.py +175 -0
  23. onec_runtime/bsl/parser_artifact_identity.py +119 -0
  24. onec_runtime/bsl/parser_target.py +388 -0
  25. onec_runtime/bsl/preprocessor.py +16 -0
  26. onec_runtime/bsl/semantic_lowering.py +1539 -0
  27. onec_runtime/bsl/source_maps.py +2411 -0
  28. onec_runtime/bsl/worker_dependency_resolver.py +289 -0
  29. onec_runtime/bsl/worker_preprocessor.py +247 -0
  30. onec_runtime/bsl/worker_projection_model.py +137 -0
  31. onec_runtime/bsl/worker_reload_source_map.py +1697 -0
  32. onec_runtime/capture.py +113 -0
  33. onec_runtime/capture_source.py +453 -0
  34. onec_runtime/compact_table.py +376 -0
  35. onec_runtime/compact_table_backend.py +500 -0
  36. onec_runtime/config.py +198 -0
  37. onec_runtime/configurator_agent.py +520 -0
  38. onec_runtime/controller_worker.py +400 -0
  39. onec_runtime/credentials.py +18 -0
  40. onec_runtime/epf_container.py +196 -0
  41. onec_runtime/errors.py +205 -0
  42. onec_runtime/experiment.py +130 -0
  43. onec_runtime/extension_bundle.py +944 -0
  44. onec_runtime/extension_lifecycle.py +402 -0
  45. onec_runtime/extension_state.py +222 -0
  46. onec_runtime/fault_injection.py +30 -0
  47. onec_runtime/kernel.py +179 -0
  48. onec_runtime/lease.py +123 -0
  49. onec_runtime/observation.py +287 -0
  50. onec_runtime/performance_profile.py +245 -0
  51. onec_runtime/privacy.py +263 -0
  52. onec_runtime/processes.py +265 -0
  53. onec_runtime/prototype_runtime.py +2644 -0
  54. onec_runtime/rdbg/__init__.py +1 -0
  55. onec_runtime/rdbg/models.py +130 -0
  56. onec_runtime/rdbg/reconnect.py +59 -0
  57. onec_runtime/rdbg/session.py +913 -0
  58. onec_runtime/rdbg/transport.py +138 -0
  59. onec_runtime/rdbg/xml_codec.py +980 -0
  60. onec_runtime/recovery.py +106 -0
  61. onec_runtime/recovery_journal.py +79 -0
  62. onec_runtime/resources/extension/OnecInteractiveRuntime.cfe +0 -0
  63. onec_runtime/resources/extension/extension-manifest.json +108 -0
  64. onec_runtime/runtime_api.py +5272 -0
  65. onec_runtime/runtime_contracts.py +196 -0
  66. onec_runtime/server_worker.py +2034 -0
  67. onec_runtime/session.py +2123 -0
  68. onec_runtime/startup_diagnostics.py +45 -0
  69. onec_runtime/stop_routing.py +65 -0
  70. onec_runtime/supervised_processes.py +232 -0
  71. onec_runtime/supervised_runtime.py +512 -0
  72. onec_runtime/supervisor.py +363 -0
  73. onec_runtime/supervisor_model.py +148 -0
  74. onec_runtime/supervisor_protocol.py +77 -0
  75. onec_runtime/table_materialization.py +471 -0
  76. onec_runtime/table_transfer_backend.py +203 -0
  77. onec_runtime/table_value.py +311 -0
  78. onec_runtime/toolchain.py +730 -0
  79. onec_runtime/value_materialization.py +432 -0
  80. onec_runtime/value_transfer_backend.py +199 -0
  81. onec_runtime/worker_breakpoints.py +1431 -0
  82. onec_runtime/worker_epf.py +313 -0
  83. onec_runtime/worker_epf_template.py +53 -0
  84. onec_runtime/worker_stage_protocol.py +516 -0
  85. onec_runtime/worker_universe.py +3772 -0
  86. onec_runtime_build/__init__.py +1 -0
  87. onec_runtime_build/parser_target_development.py +116 -0
@@ -0,0 +1,376 @@
1
+ from __future__ import annotations
2
+
3
+ from base64 import b64decode
4
+ import binascii
5
+ from dataclasses import dataclass
6
+ from datetime import datetime
7
+ import json
8
+ import math
9
+ import re
10
+ from typing import Mapping, cast
11
+ from uuid import UUID
12
+
13
+ import pandas as pd
14
+
15
+ from .table_materialization import (
16
+ ReferenceMode,
17
+ ReferencePolicy,
18
+ TableMaterializationError,
19
+ _datetime_series,
20
+ )
21
+
22
+
23
+ _SCHEMA_KEYS = frozenset({"version", "columns", "kinds", "reference_modes"})
24
+ _SCALAR_KINDS = frozenset(
25
+ {
26
+ "string",
27
+ "nullable_string",
28
+ "boolean",
29
+ "integer",
30
+ "number",
31
+ "datetime",
32
+ "uuid",
33
+ }
34
+ )
35
+ _REFERENCE_KINDS = frozenset(mode.value for mode in ReferenceMode)
36
+ _ASCII_WHITESPACE = re.compile(r"[ \t\r\n\f\v]")
37
+
38
+
39
+ @dataclass(frozen=True, slots=True)
40
+ class CompactTableSchema:
41
+ version: int
42
+ columns: tuple[str, ...]
43
+ kinds: tuple[str, ...]
44
+ reference_modes: Mapping[str, ReferenceMode]
45
+
46
+
47
+ def decode_compact_table_base64(
48
+ content: str,
49
+ policy: ReferencePolicy | None = None,
50
+ ) -> pd.DataFrame:
51
+ if not isinstance(content, str):
52
+ raise TableMaterializationError("compact table Base64 content is invalid")
53
+ compact = _ASCII_WHITESPACE.sub("", content)
54
+ try:
55
+ payload = b64decode(compact, validate=True)
56
+ except (ValueError, binascii.Error) as error:
57
+ raise TableMaterializationError(
58
+ "compact table content is not valid Base64"
59
+ ) from error
60
+ return decode_compact_table_payload(payload, policy)
61
+
62
+
63
+ def decode_compact_table_payload(
64
+ payload: bytes,
65
+ policy: ReferencePolicy | None = None,
66
+ ) -> pd.DataFrame:
67
+ lines = _read_lines(payload)
68
+ schema_value = _load_json(lines[0], line_number=1)
69
+ schema = _read_schema(schema_value)
70
+ selected_policy = policy or ReferencePolicy()
71
+ effective_modes = _bind_policy(schema, selected_policy)
72
+ values_by_column: list[list[object]] = [[] for _ in schema.columns]
73
+
74
+ for row_number, line in enumerate(lines[1:], start=1):
75
+ raw_row = _load_json(line, line_number=row_number + 1)
76
+ if not isinstance(raw_row, list):
77
+ raise TableMaterializationError(f"compact table row {row_number} is invalid")
78
+ if len(raw_row) != len(schema.columns):
79
+ raise TableMaterializationError(
80
+ f"compact table row width mismatch at row {row_number}"
81
+ )
82
+ for ordinal, raw_value in enumerate(raw_row):
83
+ column = schema.columns[ordinal]
84
+ mode = schema.reference_modes.get(column)
85
+ if mode is None:
86
+ decoded = _decode_scalar(
87
+ raw_value,
88
+ kind=schema.kinds[ordinal],
89
+ row_number=row_number,
90
+ column=column,
91
+ )
92
+ else:
93
+ decoded = _decode_reference(
94
+ raw_value,
95
+ mode=mode,
96
+ row_number=row_number,
97
+ column=column,
98
+ )
99
+ values_by_column[ordinal].append(decoded)
100
+
101
+ result: dict[str, pd.Series] = {}
102
+ for ordinal, column in enumerate(schema.columns):
103
+ values = values_by_column[ordinal]
104
+ mode = schema.reference_modes.get(column)
105
+ if mode is ReferenceMode.BOTH:
106
+ presentations = [
107
+ pd.NA if value is None else cast(tuple[object, object], value)[0]
108
+ for value in values
109
+ ]
110
+ identifiers = [
111
+ pd.NA if value is None else cast(tuple[object, object], value)[1]
112
+ for value in values
113
+ ]
114
+ result[column] = pd.Series(presentations, dtype="string")
115
+ result[column + selected_policy.uuid_suffix] = pd.Series(
116
+ identifiers,
117
+ dtype="object",
118
+ )
119
+ elif mode is ReferenceMode.PRESENTATION:
120
+ result[column] = pd.Series(
121
+ [pd.NA if value is None else value for value in values],
122
+ dtype="string",
123
+ )
124
+ elif mode is ReferenceMode.UUID:
125
+ result[column] = pd.Series(
126
+ [pd.NA if value is None else value for value in values],
127
+ dtype="object",
128
+ )
129
+ else:
130
+ result[column] = _scalar_series(values, schema.kinds[ordinal])
131
+
132
+ frame = pd.DataFrame(result)
133
+ frame.attrs["compact_table_schema"] = {
134
+ "version": schema.version,
135
+ "columns": list(schema.columns),
136
+ "kinds": list(schema.kinds),
137
+ "reference_modes": {
138
+ name: mode.value for name, mode in schema.reference_modes.items()
139
+ },
140
+ }
141
+ frame.attrs["reference_modes"] = {
142
+ name: mode.value for name, mode in effective_modes.items()
143
+ }
144
+ return frame
145
+
146
+
147
+ def _read_lines(payload: bytes) -> list[str]:
148
+ if not isinstance(payload, bytes) or not payload:
149
+ raise TableMaterializationError("compact table payload is empty")
150
+ try:
151
+ text = payload.decode("utf-8-sig")
152
+ except UnicodeDecodeError as error:
153
+ raise TableMaterializationError(
154
+ "compact table payload is not valid UTF-8"
155
+ ) from error
156
+ lines = text.splitlines()
157
+ if not lines:
158
+ raise TableMaterializationError("compact table payload is empty")
159
+ if any(not line for line in lines):
160
+ raise TableMaterializationError("compact table payload contains an empty line")
161
+ return lines
162
+
163
+
164
+ def _load_json(line: str, *, line_number: int) -> object:
165
+ try:
166
+ return json.loads(
167
+ line,
168
+ parse_constant=lambda _value: (_ for _ in ()).throw(ValueError()),
169
+ )
170
+ except (json.JSONDecodeError, ValueError) as error:
171
+ raise TableMaterializationError(
172
+ f"compact table line {line_number} is not valid JSON"
173
+ ) from error
174
+
175
+
176
+ def _read_schema(value: object) -> CompactTableSchema:
177
+ if not isinstance(value, dict) or set(value) != _SCHEMA_KEYS:
178
+ raise TableMaterializationError("compact table schema fields are invalid")
179
+ version = value.get("version")
180
+ raw_columns = value.get("columns")
181
+ raw_kinds = value.get("kinds")
182
+ raw_modes = value.get("reference_modes")
183
+ if type(version) is not int or version != 1:
184
+ raise TableMaterializationError("compact table schema version is unsupported")
185
+ if (
186
+ not isinstance(raw_columns, list)
187
+ or not raw_columns
188
+ or any(not isinstance(name, str) or not name for name in raw_columns)
189
+ ):
190
+ raise TableMaterializationError("compact table schema columns are invalid")
191
+ columns = cast(list[str], raw_columns)
192
+ if len(set(columns)) != len(columns):
193
+ raise TableMaterializationError("compact table schema has a duplicate column")
194
+ if (
195
+ not isinstance(raw_kinds, list)
196
+ or len(raw_kinds) != len(columns)
197
+ or any(not isinstance(kind, str) for kind in raw_kinds)
198
+ ):
199
+ raise TableMaterializationError("compact table schema kinds are invalid")
200
+ kinds = cast(list[str], raw_kinds)
201
+ if not isinstance(raw_modes, dict):
202
+ raise TableMaterializationError(
203
+ "compact table schema reference modes are invalid"
204
+ )
205
+ modes: dict[str, ReferenceMode] = {}
206
+ for name, raw_mode in raw_modes.items():
207
+ if not isinstance(name, str) or name not in columns or not isinstance(raw_mode, str):
208
+ raise TableMaterializationError(
209
+ "compact table schema reference column is invalid"
210
+ )
211
+ try:
212
+ mode = ReferenceMode(raw_mode)
213
+ except ValueError as error:
214
+ raise TableMaterializationError(
215
+ f"compact table schema reference mode is invalid for column {name}"
216
+ ) from error
217
+ if kinds[columns.index(name)] != mode.value:
218
+ raise TableMaterializationError(
219
+ f"compact table schema reference kind is invalid for column {name}"
220
+ )
221
+ modes[name] = mode
222
+ for ordinal, kind in enumerate(kinds):
223
+ name = columns[ordinal]
224
+ if name in modes:
225
+ continue
226
+ if kind not in _SCALAR_KINDS or kind in {
227
+ ReferenceMode.PRESENTATION.value,
228
+ ReferenceMode.BOTH.value,
229
+ }:
230
+ raise TableMaterializationError(
231
+ f"compact table schema reference mode is missing for column {name}"
232
+ )
233
+ return CompactTableSchema(version, tuple(columns), tuple(kinds), modes)
234
+
235
+
236
+ def _bind_policy(
237
+ schema: CompactTableSchema,
238
+ policy: ReferencePolicy,
239
+ ) -> dict[str, ReferenceMode]:
240
+ if not policy.uuid_suffix:
241
+ raise TableMaterializationError("UUID suffix must not be empty")
242
+ try:
243
+ default = ReferenceMode(policy.refs)
244
+ except ValueError as error:
245
+ raise TableMaterializationError("unknown reference mode") from error
246
+ overrides = dict(policy.ref_columns or {})
247
+ unknown = set(overrides) - set(schema.reference_modes)
248
+ if unknown:
249
+ raise TableMaterializationError(
250
+ "unknown reference column: " + ", ".join(sorted(unknown))
251
+ )
252
+ effective: dict[str, ReferenceMode] = {}
253
+ for name, encoded in schema.reference_modes.items():
254
+ try:
255
+ requested = ReferenceMode(overrides.get(name, default))
256
+ except ValueError as error:
257
+ raise TableMaterializationError(
258
+ f"unknown reference mode for column {name}"
259
+ ) from error
260
+ if requested is not encoded:
261
+ raise TableMaterializationError(
262
+ f"reference mode mismatch for column {name}"
263
+ )
264
+ if requested is ReferenceMode.BOTH:
265
+ generated = name + policy.uuid_suffix
266
+ if generated in schema.columns:
267
+ raise TableMaterializationError(
268
+ f"generated UUID column collision: {generated}"
269
+ )
270
+ effective[name] = requested
271
+ return effective
272
+
273
+
274
+ def _decode_scalar(
275
+ value: object,
276
+ *,
277
+ kind: str,
278
+ row_number: int,
279
+ column: str,
280
+ ) -> object:
281
+ invalid = TableMaterializationError(
282
+ f"invalid {kind} at row {row_number}, column {column}"
283
+ )
284
+ # 1C infers a column kind from populated cells and serializes missing
285
+ # Неопределено/NULL cells as JSON null, including an entirely empty column.
286
+ if value is None:
287
+ return None
288
+ if kind in {"string", "nullable_string"}:
289
+ if isinstance(value, str):
290
+ return value
291
+ raise invalid
292
+ if kind == "boolean":
293
+ if type(value) is bool:
294
+ return value
295
+ raise invalid
296
+ if kind == "integer":
297
+ if type(value) is int and -(2**63) <= cast(int, value) < 2**63:
298
+ return value
299
+ raise invalid
300
+ if kind == "number":
301
+ if type(value) not in {int, float}:
302
+ raise invalid
303
+ try:
304
+ number = float(cast(float, value))
305
+ except OverflowError as error:
306
+ raise invalid from error
307
+ if math.isfinite(number):
308
+ return number
309
+ raise invalid
310
+ if kind == "datetime":
311
+ if not isinstance(value, str):
312
+ raise invalid
313
+ try:
314
+ return datetime.fromisoformat(value)
315
+ except ValueError as error:
316
+ raise invalid from error
317
+ if kind == "uuid":
318
+ if not isinstance(value, str):
319
+ raise invalid
320
+ try:
321
+ return UUID(value)
322
+ except ValueError as error:
323
+ raise invalid from error
324
+ raise invalid
325
+
326
+
327
+ def _decode_reference(
328
+ value: object,
329
+ *,
330
+ mode: ReferenceMode,
331
+ row_number: int,
332
+ column: str,
333
+ ) -> object:
334
+ invalid = TableMaterializationError(
335
+ f"invalid {mode.value} reference at row {row_number}, column {column}"
336
+ )
337
+ if value is None:
338
+ return None
339
+ if mode is ReferenceMode.PRESENTATION:
340
+ if isinstance(value, str):
341
+ return value
342
+ raise invalid
343
+ if mode is ReferenceMode.UUID:
344
+ if not isinstance(value, str):
345
+ raise invalid
346
+ try:
347
+ return UUID(value)
348
+ except ValueError as error:
349
+ raise invalid from error
350
+ if (
351
+ not isinstance(value, list)
352
+ or len(value) != 2
353
+ or not isinstance(value[0], str)
354
+ or not isinstance(value[1], str)
355
+ ):
356
+ raise invalid
357
+ try:
358
+ identifier = UUID(value[1])
359
+ except ValueError as error:
360
+ raise invalid from error
361
+ return value[0], identifier
362
+
363
+
364
+ def _scalar_series(values: list[object], kind: str) -> pd.Series:
365
+ converted = [pd.NA if value is None else value for value in values]
366
+ if kind in {"string", "nullable_string"}:
367
+ return pd.Series(converted, dtype="string")
368
+ if kind == "boolean":
369
+ return pd.Series(converted, dtype="boolean")
370
+ if kind == "integer":
371
+ return pd.Series(converted, dtype="Int64")
372
+ if kind == "number":
373
+ return pd.Series(converted, dtype="Float64")
374
+ if kind == "datetime":
375
+ return _datetime_series(values)
376
+ return pd.Series(converted, dtype="object")