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.
- onec_interactive_runtime_core-0.1.19.dist-info/METADATA +12 -0
- onec_interactive_runtime_core-0.1.19.dist-info/RECORD +87 -0
- onec_interactive_runtime_core-0.1.19.dist-info/WHEEL +4 -0
- onec_interactive_runtime_core-0.1.19.dist-info/licenses/COPYRIGHT +9 -0
- onec_interactive_runtime_core-0.1.19.dist-info/licenses/LICENSE +232 -0
- onec_interactive_runtime_core-0.1.19.dist-info/licenses/THIRD_PARTY_NOTICES.txt +32 -0
- onec_runtime/AGENTS.md +7 -0
- onec_runtime/__init__.py +3 -0
- onec_runtime/artifacts.py +59 -0
- onec_runtime/bootstrap.py +310 -0
- onec_runtime/breakpoint_workspace.py +249 -0
- onec_runtime/bsl/__init__.py +139 -0
- onec_runtime/bsl/diagnostics.py +1046 -0
- onec_runtime/bsl/full_ast_worker_projection.py +522 -0
- onec_runtime/bsl/generated_semantic_parser.py +6322 -0
- onec_runtime/bsl/lexer.py +164 -0
- onec_runtime/bsl/module_catalog.py +420 -0
- onec_runtime/bsl/module_delta.py +1079 -0
- onec_runtime/bsl/module_universe.py +1877 -0
- onec_runtime/bsl/notebook_cells.py +232 -0
- onec_runtime/bsl/notebook_method_globals.py +74 -0
- onec_runtime/bsl/notebook_methods.py +175 -0
- onec_runtime/bsl/parser_artifact_identity.py +119 -0
- onec_runtime/bsl/parser_target.py +388 -0
- onec_runtime/bsl/preprocessor.py +16 -0
- onec_runtime/bsl/semantic_lowering.py +1539 -0
- onec_runtime/bsl/source_maps.py +2411 -0
- onec_runtime/bsl/worker_dependency_resolver.py +289 -0
- onec_runtime/bsl/worker_preprocessor.py +247 -0
- onec_runtime/bsl/worker_projection_model.py +137 -0
- onec_runtime/bsl/worker_reload_source_map.py +1697 -0
- onec_runtime/capture.py +113 -0
- onec_runtime/capture_source.py +453 -0
- onec_runtime/compact_table.py +376 -0
- onec_runtime/compact_table_backend.py +500 -0
- onec_runtime/config.py +198 -0
- onec_runtime/configurator_agent.py +520 -0
- onec_runtime/controller_worker.py +400 -0
- onec_runtime/credentials.py +18 -0
- onec_runtime/epf_container.py +196 -0
- onec_runtime/errors.py +205 -0
- onec_runtime/experiment.py +130 -0
- onec_runtime/extension_bundle.py +944 -0
- onec_runtime/extension_lifecycle.py +402 -0
- onec_runtime/extension_state.py +222 -0
- onec_runtime/fault_injection.py +30 -0
- onec_runtime/kernel.py +179 -0
- onec_runtime/lease.py +123 -0
- onec_runtime/observation.py +287 -0
- onec_runtime/performance_profile.py +245 -0
- onec_runtime/privacy.py +263 -0
- onec_runtime/processes.py +265 -0
- onec_runtime/prototype_runtime.py +2644 -0
- onec_runtime/rdbg/__init__.py +1 -0
- onec_runtime/rdbg/models.py +130 -0
- onec_runtime/rdbg/reconnect.py +59 -0
- onec_runtime/rdbg/session.py +913 -0
- onec_runtime/rdbg/transport.py +138 -0
- onec_runtime/rdbg/xml_codec.py +980 -0
- onec_runtime/recovery.py +106 -0
- onec_runtime/recovery_journal.py +79 -0
- onec_runtime/resources/extension/OnecInteractiveRuntime.cfe +0 -0
- onec_runtime/resources/extension/extension-manifest.json +108 -0
- onec_runtime/runtime_api.py +5272 -0
- onec_runtime/runtime_contracts.py +196 -0
- onec_runtime/server_worker.py +2034 -0
- onec_runtime/session.py +2123 -0
- onec_runtime/startup_diagnostics.py +45 -0
- onec_runtime/stop_routing.py +65 -0
- onec_runtime/supervised_processes.py +232 -0
- onec_runtime/supervised_runtime.py +512 -0
- onec_runtime/supervisor.py +363 -0
- onec_runtime/supervisor_model.py +148 -0
- onec_runtime/supervisor_protocol.py +77 -0
- onec_runtime/table_materialization.py +471 -0
- onec_runtime/table_transfer_backend.py +203 -0
- onec_runtime/table_value.py +311 -0
- onec_runtime/toolchain.py +730 -0
- onec_runtime/value_materialization.py +432 -0
- onec_runtime/value_transfer_backend.py +199 -0
- onec_runtime/worker_breakpoints.py +1431 -0
- onec_runtime/worker_epf.py +313 -0
- onec_runtime/worker_epf_template.py +53 -0
- onec_runtime/worker_stage_protocol.py +516 -0
- onec_runtime/worker_universe.py +3772 -0
- onec_runtime_build/__init__.py +1 -0
- 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")
|