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,730 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import shutil
|
|
4
|
+
import subprocess
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from hashlib import sha256
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from onec_runtime.config import RuntimeConfig
|
|
10
|
+
from onec_runtime.credentials import redact_command
|
|
11
|
+
from onec_runtime.errors import ExtensionNotInstalled, ProcessStartError
|
|
12
|
+
from onec_runtime.extension_bundle import EXTENSION_NAME
|
|
13
|
+
from onec_runtime.startup_diagnostics import startup_log_hint
|
|
14
|
+
|
|
15
|
+
HEADLESS_ARGS = ["/DisableStartupDialogs", "/DisableStartupMessages"]
|
|
16
|
+
_MISSING_PRODUCT_EXTENSION_DIAGNOSTICS = (
|
|
17
|
+
"Операция не может быть выполнена, так как расширение конфигурации "
|
|
18
|
+
f"с указанным именем не найдено: {EXTENSION_NAME}",
|
|
19
|
+
"Cannot perform the operation because the following configuration extension "
|
|
20
|
+
f"is not found: {EXTENSION_NAME}",
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True)
|
|
25
|
+
class ToolResult:
|
|
26
|
+
command: tuple[str, ...]
|
|
27
|
+
returncode: int
|
|
28
|
+
log_path: Path
|
|
29
|
+
|
|
30
|
+
def __post_init__(self) -> None:
|
|
31
|
+
object.__setattr__(self, "command", redact_command(self.command))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def create_file_infobase_at_command(
|
|
35
|
+
designer_exe: Path, infobase_dir: Path, log_path: Path
|
|
36
|
+
) -> list[str]:
|
|
37
|
+
return [
|
|
38
|
+
str(designer_exe),
|
|
39
|
+
"CREATEINFOBASE",
|
|
40
|
+
f"File={infobase_dir};",
|
|
41
|
+
*HEADLESS_ARGS,
|
|
42
|
+
"/Out",
|
|
43
|
+
str(log_path),
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def load_product_extension_source_command(
|
|
48
|
+
designer_exe: Path,
|
|
49
|
+
infobase_dir: Path,
|
|
50
|
+
source_dir: Path,
|
|
51
|
+
log_path: Path,
|
|
52
|
+
) -> list[str]:
|
|
53
|
+
return [
|
|
54
|
+
str(designer_exe),
|
|
55
|
+
"DESIGNER",
|
|
56
|
+
"/F",
|
|
57
|
+
str(infobase_dir),
|
|
58
|
+
"/LoadConfigFromFiles",
|
|
59
|
+
str(source_dir),
|
|
60
|
+
"-Extension",
|
|
61
|
+
EXTENSION_NAME,
|
|
62
|
+
"-updateConfigDumpInfo",
|
|
63
|
+
"-Format",
|
|
64
|
+
"Hierarchical",
|
|
65
|
+
*HEADLESS_ARGS,
|
|
66
|
+
"/Out",
|
|
67
|
+
str(log_path),
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def dump_product_extension_cfe_command(
|
|
72
|
+
designer_exe: Path,
|
|
73
|
+
infobase_dir: Path,
|
|
74
|
+
output_cfe: Path,
|
|
75
|
+
log_path: Path,
|
|
76
|
+
) -> list[str]:
|
|
77
|
+
return [
|
|
78
|
+
str(designer_exe),
|
|
79
|
+
"DESIGNER",
|
|
80
|
+
"/F",
|
|
81
|
+
str(infobase_dir),
|
|
82
|
+
"/DumpCfg",
|
|
83
|
+
str(output_cfe),
|
|
84
|
+
"-Extension",
|
|
85
|
+
EXTENSION_NAME,
|
|
86
|
+
*HEADLESS_ARGS,
|
|
87
|
+
"/Out",
|
|
88
|
+
str(log_path),
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _target_designer_command(config: RuntimeConfig) -> list[str]:
|
|
93
|
+
return [
|
|
94
|
+
str(config.designer_exe),
|
|
95
|
+
"DESIGNER",
|
|
96
|
+
*config.infobase_arguments,
|
|
97
|
+
"/N",
|
|
98
|
+
config.username,
|
|
99
|
+
"/P",
|
|
100
|
+
config.password,
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def dump_target_extension_files_command(
|
|
105
|
+
config: RuntimeConfig, output_dir: Path, log_path: Path
|
|
106
|
+
) -> list[str]:
|
|
107
|
+
return [
|
|
108
|
+
*_target_designer_command(config),
|
|
109
|
+
"/DumpConfigToFiles",
|
|
110
|
+
str(output_dir),
|
|
111
|
+
"-Extension",
|
|
112
|
+
EXTENSION_NAME,
|
|
113
|
+
"-Format",
|
|
114
|
+
"Hierarchical",
|
|
115
|
+
*HEADLESS_ARGS,
|
|
116
|
+
"/Out",
|
|
117
|
+
str(log_path),
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def dump_target_extension_cfe_command(
|
|
122
|
+
config: RuntimeConfig, output_cfe: Path, log_path: Path
|
|
123
|
+
) -> list[str]:
|
|
124
|
+
return [
|
|
125
|
+
*_target_designer_command(config),
|
|
126
|
+
"/DumpCfg",
|
|
127
|
+
str(output_cfe),
|
|
128
|
+
"-Extension",
|
|
129
|
+
EXTENSION_NAME,
|
|
130
|
+
*HEADLESS_ARGS,
|
|
131
|
+
"/Out",
|
|
132
|
+
str(log_path),
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def load_target_extension_cfe_command(
|
|
137
|
+
config: RuntimeConfig, input_cfe: Path, log_path: Path
|
|
138
|
+
) -> list[str]:
|
|
139
|
+
return [
|
|
140
|
+
*_target_designer_command(config),
|
|
141
|
+
"/LoadCfg",
|
|
142
|
+
str(input_cfe),
|
|
143
|
+
"-Extension",
|
|
144
|
+
EXTENSION_NAME,
|
|
145
|
+
*HEADLESS_ARGS,
|
|
146
|
+
"/Out",
|
|
147
|
+
str(log_path),
|
|
148
|
+
]
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def apply_product_extension_command(config: RuntimeConfig, log_path: Path) -> list[str]:
|
|
152
|
+
dynamic_mode = "-Dynamic-" if config.uses_external_infobase else "-Dynamic+"
|
|
153
|
+
return [
|
|
154
|
+
*_target_designer_command(config),
|
|
155
|
+
"/UpdateDBCfg",
|
|
156
|
+
dynamic_mode,
|
|
157
|
+
"-Extension",
|
|
158
|
+
EXTENSION_NAME,
|
|
159
|
+
*HEADLESS_ARGS,
|
|
160
|
+
"/Out",
|
|
161
|
+
str(log_path),
|
|
162
|
+
]
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def create_infobase_command(config: RuntimeConfig) -> list[str]:
|
|
166
|
+
return _create_infobase_command(
|
|
167
|
+
config, config.infobase_dir, config.logs_dir / "create-infobase.log"
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def create_build_infobase_command(config: RuntimeConfig) -> list[str]:
|
|
172
|
+
return _create_infobase_command(
|
|
173
|
+
config,
|
|
174
|
+
config.build_infobase_dir,
|
|
175
|
+
config.logs_dir / "create-build-infobase.log",
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _create_infobase_command(
|
|
180
|
+
config: RuntimeConfig, infobase_dir: Path, log_path: Path
|
|
181
|
+
) -> list[str]:
|
|
182
|
+
return [
|
|
183
|
+
str(config.designer_exe),
|
|
184
|
+
"CREATEINFOBASE",
|
|
185
|
+
f"File={infobase_dir};",
|
|
186
|
+
*HEADLESS_ARGS,
|
|
187
|
+
"/Out",
|
|
188
|
+
str(log_path),
|
|
189
|
+
]
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def build_external_processor_command(config: RuntimeConfig) -> list[str]:
|
|
193
|
+
return build_external_processor_from_files_command(
|
|
194
|
+
config,
|
|
195
|
+
config.workspace / "onec" / "Kernel" / "Kernel.xml",
|
|
196
|
+
config.kernel_epf,
|
|
197
|
+
config.logs_dir / "build-kernel.log",
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def build_worker_command(config: RuntimeConfig) -> list[str]:
|
|
202
|
+
return build_external_processor_from_files_command(
|
|
203
|
+
config,
|
|
204
|
+
config.workspace / "onec" / "Worker" / "Worker.xml",
|
|
205
|
+
config.worker_epf,
|
|
206
|
+
config.logs_dir / "build-worker.log",
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def build_external_processor_from_files_command(
|
|
211
|
+
config: RuntimeConfig,
|
|
212
|
+
source_xml: Path,
|
|
213
|
+
output_epf: Path,
|
|
214
|
+
log_path: Path,
|
|
215
|
+
) -> list[str]:
|
|
216
|
+
return [
|
|
217
|
+
str(config.designer_exe),
|
|
218
|
+
"DESIGNER",
|
|
219
|
+
"/F",
|
|
220
|
+
str(config.build_infobase_dir),
|
|
221
|
+
"/LoadExternalDataProcessorOrReportFromFiles",
|
|
222
|
+
str(source_xml),
|
|
223
|
+
str(output_epf),
|
|
224
|
+
*HEADLESS_ARGS,
|
|
225
|
+
"/Out",
|
|
226
|
+
str(log_path),
|
|
227
|
+
]
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def load_extension_source_command(
|
|
231
|
+
config: RuntimeConfig,
|
|
232
|
+
source_dir: Path,
|
|
233
|
+
) -> list[str]:
|
|
234
|
+
return [
|
|
235
|
+
str(config.designer_exe),
|
|
236
|
+
"DESIGNER",
|
|
237
|
+
"/F",
|
|
238
|
+
str(config.build_infobase_dir),
|
|
239
|
+
"/LoadConfigFromFiles",
|
|
240
|
+
str(source_dir),
|
|
241
|
+
"-Extension",
|
|
242
|
+
EXTENSION_NAME,
|
|
243
|
+
"-updateConfigDumpInfo",
|
|
244
|
+
"-format",
|
|
245
|
+
"Hierarchical",
|
|
246
|
+
*HEADLESS_ARGS,
|
|
247
|
+
"/Out",
|
|
248
|
+
str(config.logs_dir / "load-extension-source.log"),
|
|
249
|
+
]
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def load_target_extension_source_command(
|
|
253
|
+
config: RuntimeConfig,
|
|
254
|
+
source_dir: Path,
|
|
255
|
+
) -> list[str]:
|
|
256
|
+
return [
|
|
257
|
+
str(config.designer_exe),
|
|
258
|
+
"DESIGNER",
|
|
259
|
+
*config.infobase_arguments,
|
|
260
|
+
"/N",
|
|
261
|
+
config.username,
|
|
262
|
+
"/P",
|
|
263
|
+
config.password,
|
|
264
|
+
"/LoadConfigFromFiles",
|
|
265
|
+
str(source_dir),
|
|
266
|
+
"-Extension",
|
|
267
|
+
EXTENSION_NAME,
|
|
268
|
+
"-updateConfigDumpInfo",
|
|
269
|
+
"-format",
|
|
270
|
+
"Hierarchical",
|
|
271
|
+
*HEADLESS_ARGS,
|
|
272
|
+
"/Out",
|
|
273
|
+
str(config.logs_dir / "load-target-extension-source.log"),
|
|
274
|
+
]
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def dump_extension_command(
|
|
278
|
+
config: RuntimeConfig,
|
|
279
|
+
output_cfe: Path,
|
|
280
|
+
) -> list[str]:
|
|
281
|
+
return [
|
|
282
|
+
str(config.designer_exe),
|
|
283
|
+
"DESIGNER",
|
|
284
|
+
"/F",
|
|
285
|
+
str(config.build_infobase_dir),
|
|
286
|
+
"/DumpCfg",
|
|
287
|
+
str(output_cfe),
|
|
288
|
+
"-Extension",
|
|
289
|
+
EXTENSION_NAME,
|
|
290
|
+
*HEADLESS_ARGS,
|
|
291
|
+
"/Out",
|
|
292
|
+
str(config.logs_dir / "dump-extension.log"),
|
|
293
|
+
]
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def deploy_extension_command(config: RuntimeConfig) -> list[str]:
|
|
297
|
+
return [
|
|
298
|
+
str(config.designer_exe),
|
|
299
|
+
"DESIGNER",
|
|
300
|
+
*config.infobase_arguments,
|
|
301
|
+
"/N",
|
|
302
|
+
config.username,
|
|
303
|
+
"/P",
|
|
304
|
+
config.password,
|
|
305
|
+
"/LoadCfg",
|
|
306
|
+
str(config.build_dir / f"{EXTENSION_NAME}.cfe"),
|
|
307
|
+
"-Extension",
|
|
308
|
+
EXTENSION_NAME,
|
|
309
|
+
*HEADLESS_ARGS,
|
|
310
|
+
"/Out",
|
|
311
|
+
str(config.logs_dir / "load-extension.log"),
|
|
312
|
+
]
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def update_extension_command(config: RuntimeConfig) -> list[str]:
|
|
316
|
+
command = [
|
|
317
|
+
str(config.designer_exe),
|
|
318
|
+
"DESIGNER",
|
|
319
|
+
*config.infobase_arguments,
|
|
320
|
+
"/N",
|
|
321
|
+
config.username,
|
|
322
|
+
"/P",
|
|
323
|
+
config.password,
|
|
324
|
+
"/UpdateDBCfg",
|
|
325
|
+
*HEADLESS_ARGS,
|
|
326
|
+
"-Extension",
|
|
327
|
+
EXTENSION_NAME,
|
|
328
|
+
"/Out",
|
|
329
|
+
str(config.logs_dir / "update-extension.log"),
|
|
330
|
+
]
|
|
331
|
+
dynamic_mode = "-Dynamic-" if config.uses_external_infobase else "-Dynamic+"
|
|
332
|
+
command.insert(command.index("-Extension"), dynamic_mode)
|
|
333
|
+
return command
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def apply_extension_command(config: RuntimeConfig) -> list[str]:
|
|
337
|
+
dynamic_mode = "-Dynamic-" if config.uses_external_infobase else "-Dynamic+"
|
|
338
|
+
return [
|
|
339
|
+
str(config.designer_exe),
|
|
340
|
+
"DESIGNER",
|
|
341
|
+
*config.infobase_arguments,
|
|
342
|
+
"/N",
|
|
343
|
+
config.username,
|
|
344
|
+
"/P",
|
|
345
|
+
config.password,
|
|
346
|
+
"/LoadCfg",
|
|
347
|
+
str(config.build_dir / f"{EXTENSION_NAME}.cfe"),
|
|
348
|
+
"-Extension",
|
|
349
|
+
EXTENSION_NAME,
|
|
350
|
+
"/UpdateDBCfg",
|
|
351
|
+
dynamic_mode,
|
|
352
|
+
*HEADLESS_ARGS,
|
|
353
|
+
"/Out",
|
|
354
|
+
str(config.logs_dir / "apply-extension.log"),
|
|
355
|
+
]
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def apply_target_extension_source_command(
|
|
359
|
+
config: RuntimeConfig,
|
|
360
|
+
source_dir: Path,
|
|
361
|
+
) -> list[str]:
|
|
362
|
+
dynamic_mode = "-Dynamic-" if config.uses_external_infobase else "-Dynamic+"
|
|
363
|
+
return [
|
|
364
|
+
str(config.designer_exe),
|
|
365
|
+
"DESIGNER",
|
|
366
|
+
*config.infobase_arguments,
|
|
367
|
+
"/N",
|
|
368
|
+
config.username,
|
|
369
|
+
"/P",
|
|
370
|
+
config.password,
|
|
371
|
+
"/LoadConfigFromFiles",
|
|
372
|
+
str(source_dir),
|
|
373
|
+
"-Extension",
|
|
374
|
+
EXTENSION_NAME,
|
|
375
|
+
"-updateConfigDumpInfo",
|
|
376
|
+
"-format",
|
|
377
|
+
"Hierarchical",
|
|
378
|
+
"/UpdateDBCfg",
|
|
379
|
+
dynamic_mode,
|
|
380
|
+
*HEADLESS_ARGS,
|
|
381
|
+
"/Out",
|
|
382
|
+
str(config.logs_dir / "apply-extension-source.log"),
|
|
383
|
+
]
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
def _prepare_runtime_directories(config: RuntimeConfig) -> None:
|
|
387
|
+
config.runtime_dir.mkdir(parents=True, exist_ok=True)
|
|
388
|
+
config.build_dir.mkdir(parents=True, exist_ok=True)
|
|
389
|
+
config.logs_dir.mkdir(parents=True, exist_ok=True)
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
def _run(command: list[str], log_path: Path) -> ToolResult:
|
|
393
|
+
try:
|
|
394
|
+
completed = subprocess.run(command, shell=False, check=False)
|
|
395
|
+
except OSError as error:
|
|
396
|
+
raise ProcessStartError(
|
|
397
|
+
f"Unable to start 1C tool (OS error {error.errno}); see {log_path}"
|
|
398
|
+
) from None
|
|
399
|
+
result = ToolResult(tuple(command), completed.returncode, log_path)
|
|
400
|
+
if completed.returncode != 0:
|
|
401
|
+
raise ProcessStartError(
|
|
402
|
+
f"1C tool exited with code {completed.returncode}; see {log_path}"
|
|
403
|
+
)
|
|
404
|
+
return result
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
def run_tool_command(command: list[str], log_path: Path) -> ToolResult:
|
|
408
|
+
"""Run one headless Designer command using the standard return-code policy."""
|
|
409
|
+
return _run(command, log_path)
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
def _prepare_designer_log(log_path: Path) -> None:
|
|
413
|
+
log_path.parent.mkdir(parents=True, exist_ok=True)
|
|
414
|
+
log_path.unlink(missing_ok=True)
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
def _clear_output(path: Path) -> None:
|
|
418
|
+
if path.is_dir():
|
|
419
|
+
shutil.rmtree(path)
|
|
420
|
+
else:
|
|
421
|
+
path.unlink(missing_ok=True)
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def _require_non_empty_file(path: Path, label: str, log_path: Path) -> None:
|
|
425
|
+
if not path.is_file() or path.stat().st_size == 0:
|
|
426
|
+
raise ProcessStartError(
|
|
427
|
+
f"1C did not create non-empty {label}: {path}; see {log_path}"
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
def _require_non_empty_dump(output_dir: Path, log_path: Path) -> None:
|
|
432
|
+
if not output_dir.is_dir() or not any(
|
|
433
|
+
path.is_file() and path.stat().st_size > 0 for path in output_dir.rglob("*")
|
|
434
|
+
):
|
|
435
|
+
raise ProcessStartError(
|
|
436
|
+
f"1C did not create a non-empty extension dump: {output_dir}; see {log_path}"
|
|
437
|
+
)
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
def _missing_product_extension(log_path: Path) -> bool:
|
|
441
|
+
try:
|
|
442
|
+
text = log_path.read_text(encoding="utf-8-sig")
|
|
443
|
+
except (OSError, UnicodeDecodeError):
|
|
444
|
+
return False
|
|
445
|
+
return any(
|
|
446
|
+
line.strip() in _MISSING_PRODUCT_EXTENSION_DIAGNOSTICS
|
|
447
|
+
for line in text.splitlines()
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
def _run_product_command(command: list[str], log_path: Path) -> ToolResult:
|
|
452
|
+
_prepare_designer_log(log_path)
|
|
453
|
+
try:
|
|
454
|
+
return run_tool_command(command, log_path)
|
|
455
|
+
except ProcessStartError as error:
|
|
456
|
+
if _missing_product_extension(log_path):
|
|
457
|
+
raise ExtensionNotInstalled(
|
|
458
|
+
f"The target infobase does not contain {EXTENSION_NAME}"
|
|
459
|
+
) from error
|
|
460
|
+
hint = startup_log_hint(log_path)
|
|
461
|
+
if hint is not None:
|
|
462
|
+
raise ProcessStartError(
|
|
463
|
+
f"Конфигуратор 1С: {hint}; подробности: {log_path}"
|
|
464
|
+
) from None
|
|
465
|
+
raise
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
def create_file_infobase_at(
|
|
469
|
+
designer_exe: Path, infobase_dir: Path, log_path: Path
|
|
470
|
+
) -> ToolResult:
|
|
471
|
+
database_file = infobase_dir / "1Cv8.1CD"
|
|
472
|
+
if database_file.exists():
|
|
473
|
+
raise ProcessStartError(
|
|
474
|
+
f"Refusing to reuse the existing infobase at {infobase_dir}"
|
|
475
|
+
)
|
|
476
|
+
infobase_dir.parent.mkdir(parents=True, exist_ok=True)
|
|
477
|
+
result = _run_product_command(
|
|
478
|
+
create_file_infobase_at_command(designer_exe, infobase_dir, log_path),
|
|
479
|
+
log_path,
|
|
480
|
+
)
|
|
481
|
+
_require_non_empty_file(database_file, "1Cv8.1CD", log_path)
|
|
482
|
+
return result
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
def load_product_extension_source(
|
|
486
|
+
designer_exe: Path,
|
|
487
|
+
infobase_dir: Path,
|
|
488
|
+
source_dir: Path,
|
|
489
|
+
log_path: Path,
|
|
490
|
+
) -> ToolResult:
|
|
491
|
+
return _run_product_command(
|
|
492
|
+
load_product_extension_source_command(
|
|
493
|
+
designer_exe, infobase_dir, source_dir, log_path
|
|
494
|
+
),
|
|
495
|
+
log_path,
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
def dump_product_extension_cfe(
|
|
500
|
+
designer_exe: Path,
|
|
501
|
+
infobase_dir: Path,
|
|
502
|
+
output_cfe: Path,
|
|
503
|
+
log_path: Path,
|
|
504
|
+
) -> ToolResult:
|
|
505
|
+
output_cfe.parent.mkdir(parents=True, exist_ok=True)
|
|
506
|
+
_clear_output(output_cfe)
|
|
507
|
+
result = _run_product_command(
|
|
508
|
+
dump_product_extension_cfe_command(
|
|
509
|
+
designer_exe, infobase_dir, output_cfe, log_path
|
|
510
|
+
),
|
|
511
|
+
log_path,
|
|
512
|
+
)
|
|
513
|
+
_require_non_empty_file(output_cfe, "CFE", log_path)
|
|
514
|
+
return result
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
def dump_target_extension_files(
|
|
518
|
+
config: RuntimeConfig, output_dir: Path, log_path: Path
|
|
519
|
+
) -> ToolResult:
|
|
520
|
+
output_dir.parent.mkdir(parents=True, exist_ok=True)
|
|
521
|
+
_clear_output(output_dir)
|
|
522
|
+
result = _run_product_command(
|
|
523
|
+
dump_target_extension_files_command(config, output_dir, log_path), log_path
|
|
524
|
+
)
|
|
525
|
+
_require_non_empty_dump(output_dir, log_path)
|
|
526
|
+
return result
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
def dump_target_extension_cfe(
|
|
530
|
+
config: RuntimeConfig, output_cfe: Path, log_path: Path
|
|
531
|
+
) -> ToolResult:
|
|
532
|
+
output_cfe.parent.mkdir(parents=True, exist_ok=True)
|
|
533
|
+
_clear_output(output_cfe)
|
|
534
|
+
result = _run_product_command(
|
|
535
|
+
dump_target_extension_cfe_command(config, output_cfe, log_path), log_path
|
|
536
|
+
)
|
|
537
|
+
_require_non_empty_file(output_cfe, "CFE", log_path)
|
|
538
|
+
return result
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
def load_target_extension_cfe(
|
|
542
|
+
config: RuntimeConfig, input_cfe: Path, log_path: Path
|
|
543
|
+
) -> ToolResult:
|
|
544
|
+
return _run_product_command(
|
|
545
|
+
load_target_extension_cfe_command(config, input_cfe, log_path), log_path
|
|
546
|
+
)
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
def apply_product_extension(config: RuntimeConfig, log_path: Path) -> ToolResult:
|
|
550
|
+
return _run_product_command(
|
|
551
|
+
apply_product_extension_command(config, log_path), log_path
|
|
552
|
+
)
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
def _create_empty_infobase(
|
|
556
|
+
config: RuntimeConfig,
|
|
557
|
+
infobase_dir: Path,
|
|
558
|
+
command: list[str],
|
|
559
|
+
log_path: Path,
|
|
560
|
+
*,
|
|
561
|
+
recreate: bool,
|
|
562
|
+
) -> ToolResult:
|
|
563
|
+
_prepare_runtime_directories(config)
|
|
564
|
+
database_file = infobase_dir / "1Cv8.1CD"
|
|
565
|
+
if database_file.is_file():
|
|
566
|
+
if recreate:
|
|
567
|
+
raise ProcessStartError(
|
|
568
|
+
"Refusing to delete the existing infobase; move .runtime/infobase aside first"
|
|
569
|
+
)
|
|
570
|
+
return ToolResult(tuple(command), 0, log_path)
|
|
571
|
+
|
|
572
|
+
result = _run(command, log_path)
|
|
573
|
+
if not database_file.is_file() or database_file.stat().st_size == 0:
|
|
574
|
+
raise ProcessStartError(f"1C did not create {database_file}; see {log_path}")
|
|
575
|
+
return result
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
def create_empty_infobase(
|
|
579
|
+
config: RuntimeConfig, *, recreate: bool = False
|
|
580
|
+
) -> ToolResult:
|
|
581
|
+
return _create_empty_infobase(
|
|
582
|
+
config,
|
|
583
|
+
config.infobase_dir,
|
|
584
|
+
create_infobase_command(config),
|
|
585
|
+
config.logs_dir / "create-infobase.log",
|
|
586
|
+
recreate=recreate,
|
|
587
|
+
)
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
def create_build_infobase(
|
|
591
|
+
config: RuntimeConfig, *, recreate: bool = False
|
|
592
|
+
) -> ToolResult:
|
|
593
|
+
return _create_empty_infobase(
|
|
594
|
+
config,
|
|
595
|
+
config.build_infobase_dir,
|
|
596
|
+
create_build_infobase_command(config),
|
|
597
|
+
config.logs_dir / "create-build-infobase.log",
|
|
598
|
+
recreate=recreate,
|
|
599
|
+
)
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
def build_external_processor_from_files(
|
|
603
|
+
config: RuntimeConfig,
|
|
604
|
+
source_xml: Path,
|
|
605
|
+
output_epf: Path,
|
|
606
|
+
log_path: Path,
|
|
607
|
+
) -> ToolResult:
|
|
608
|
+
_prepare_runtime_directories(config)
|
|
609
|
+
if not source_xml.is_file():
|
|
610
|
+
raise ProcessStartError(f"External processor source is missing: {source_xml}")
|
|
611
|
+
if not (config.build_infobase_dir / "1Cv8.1CD").is_file():
|
|
612
|
+
raise ProcessStartError("The dedicated build infobase has not been created")
|
|
613
|
+
output_epf.parent.mkdir(parents=True, exist_ok=True)
|
|
614
|
+
log_path.parent.mkdir(parents=True, exist_ok=True)
|
|
615
|
+
output_epf.unlink(missing_ok=True)
|
|
616
|
+
result = _run(
|
|
617
|
+
build_external_processor_from_files_command(
|
|
618
|
+
config, source_xml, output_epf, log_path
|
|
619
|
+
),
|
|
620
|
+
log_path,
|
|
621
|
+
)
|
|
622
|
+
if not output_epf.is_file() or output_epf.stat().st_size == 0:
|
|
623
|
+
raise ProcessStartError(f"1C did not build {output_epf}; see {log_path}")
|
|
624
|
+
return result
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
def build_kernel(config: RuntimeConfig) -> ToolResult:
|
|
628
|
+
_prepare_runtime_directories(config)
|
|
629
|
+
source = config.workspace / "onec" / "Kernel" / "Kernel.xml"
|
|
630
|
+
if not source.is_file():
|
|
631
|
+
raise ProcessStartError(f"Kernel source is missing: {source}")
|
|
632
|
+
if not (config.build_infobase_dir / "1Cv8.1CD").is_file():
|
|
633
|
+
raise ProcessStartError("The dedicated build infobase has not been created")
|
|
634
|
+
|
|
635
|
+
command = build_external_processor_command(config)
|
|
636
|
+
log_path = config.logs_dir / "build-kernel.log"
|
|
637
|
+
result = _run(command, log_path)
|
|
638
|
+
if not config.kernel_epf.is_file() or config.kernel_epf.stat().st_size == 0:
|
|
639
|
+
raise ProcessStartError(f"1C did not build {config.kernel_epf}; see {log_path}")
|
|
640
|
+
return result
|
|
641
|
+
|
|
642
|
+
|
|
643
|
+
def build_worker(config: RuntimeConfig) -> ToolResult:
|
|
644
|
+
_prepare_runtime_directories(config)
|
|
645
|
+
source = config.workspace / "onec" / "Worker" / "Ext" / "ObjectModule.bsl"
|
|
646
|
+
if not source.is_file():
|
|
647
|
+
raise ProcessStartError(f"Worker source is missing: {source}")
|
|
648
|
+
from onec_runtime.worker_epf import build_worker_epf
|
|
649
|
+
|
|
650
|
+
source_text = source.read_text(encoding="utf-8-sig")
|
|
651
|
+
build_worker_epf(source_text, config.worker_epf)
|
|
652
|
+
command = (
|
|
653
|
+
"in-process-worker-epf",
|
|
654
|
+
str(source),
|
|
655
|
+
str(config.worker_epf),
|
|
656
|
+
)
|
|
657
|
+
log_path = config.logs_dir / "build-worker.log"
|
|
658
|
+
log_path.write_text(
|
|
659
|
+
"PASS\n"
|
|
660
|
+
f"source_sha256={sha256(source_text.encode('utf-8')).hexdigest()}\n"
|
|
661
|
+
f"artifact_sha256={sha256(config.worker_epf.read_bytes()).hexdigest()}\n",
|
|
662
|
+
encoding="utf-8",
|
|
663
|
+
newline="\n",
|
|
664
|
+
)
|
|
665
|
+
return ToolResult(command, 0, log_path)
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
def build_runtime_extension(
|
|
669
|
+
config: RuntimeConfig,
|
|
670
|
+
) -> tuple[ToolResult, ToolResult]:
|
|
671
|
+
_prepare_runtime_directories(config)
|
|
672
|
+
source = config.workspace / "onec" / EXTENSION_NAME
|
|
673
|
+
if not (source / "Configuration.xml").is_file():
|
|
674
|
+
raise ProcessStartError(
|
|
675
|
+
f"Runtime extension source is missing: {source}"
|
|
676
|
+
)
|
|
677
|
+
if not (config.build_infobase_dir / "1Cv8.1CD").is_file():
|
|
678
|
+
raise ProcessStartError("The dedicated build infobase has not been created")
|
|
679
|
+
output_cfe = config.build_dir / f"{EXTENSION_NAME}.cfe"
|
|
680
|
+
output_cfe.unlink(missing_ok=True)
|
|
681
|
+
load_log = config.logs_dir / "load-extension-source.log"
|
|
682
|
+
loaded = _run(
|
|
683
|
+
load_extension_source_command(config, source),
|
|
684
|
+
load_log,
|
|
685
|
+
)
|
|
686
|
+
dump_log = config.logs_dir / "dump-extension.log"
|
|
687
|
+
dumped = _run(dump_extension_command(config, output_cfe), dump_log)
|
|
688
|
+
if not output_cfe.is_file() or output_cfe.stat().st_size == 0:
|
|
689
|
+
raise ProcessStartError(f"1C did not build {output_cfe}")
|
|
690
|
+
return loaded, dumped
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
def deploy_runtime_extension(
|
|
694
|
+
config: RuntimeConfig,
|
|
695
|
+
) -> tuple[ToolResult, ToolResult]:
|
|
696
|
+
output_cfe = config.build_dir / f"{EXTENSION_NAME}.cfe"
|
|
697
|
+
if not output_cfe.is_file() or output_cfe.stat().st_size == 0:
|
|
698
|
+
raise ProcessStartError(f"{output_cfe.name} has not been built")
|
|
699
|
+
if not (config.infobase_dir / "1Cv8.1CD").is_file():
|
|
700
|
+
raise ProcessStartError("The dedicated runtime infobase has not been created")
|
|
701
|
+
loaded = _run(
|
|
702
|
+
deploy_extension_command(config),
|
|
703
|
+
config.logs_dir / "load-extension.log",
|
|
704
|
+
)
|
|
705
|
+
updated = _run(
|
|
706
|
+
apply_extension_command(config),
|
|
707
|
+
config.logs_dir / "apply-extension.log",
|
|
708
|
+
)
|
|
709
|
+
return loaded, updated
|
|
710
|
+
|
|
711
|
+
|
|
712
|
+
def deploy_runtime_extension_from_source(
|
|
713
|
+
config: RuntimeConfig,
|
|
714
|
+
) -> tuple[ToolResult, ToolResult]:
|
|
715
|
+
source = config.workspace / "onec" / EXTENSION_NAME
|
|
716
|
+
if not (source / "Configuration.xml").is_file():
|
|
717
|
+
raise ProcessStartError(
|
|
718
|
+
f"Runtime extension source is missing: {source}"
|
|
719
|
+
)
|
|
720
|
+
if not (config.infobase_dir / "1Cv8.1CD").is_file():
|
|
721
|
+
raise ProcessStartError("The dedicated runtime infobase has not been created")
|
|
722
|
+
loaded = _run(
|
|
723
|
+
load_target_extension_source_command(config, source),
|
|
724
|
+
config.logs_dir / "load-target-extension-source.log",
|
|
725
|
+
)
|
|
726
|
+
updated = _run(
|
|
727
|
+
apply_target_extension_source_command(config, source),
|
|
728
|
+
config.logs_dir / "apply-extension-source.log",
|
|
729
|
+
)
|
|
730
|
+
return loaded, updated
|