@platforma-sdk/workflow-tengo 5.20.0 → 5.21.0

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 (55) hide show
  1. package/dist/index.cjs +3 -0
  2. package/dist/index.d.ts +1 -1
  3. package/dist/index.js +3 -0
  4. package/dist/tengo/lib/pframes.lib.tengo +12 -269
  5. package/dist/tengo/lib/pframes.process-column-batch.lib.tengo +343 -0
  6. package/dist/tengo/lib/pframes.process-column-common.lib.tengo +366 -0
  7. package/dist/tengo/lib/pframes.process-pcolumn-batch-helpers.lib.tengo +242 -0
  8. package/dist/tengo/lib/pframes.table-builder.lib.tengo +3 -0
  9. package/dist/tengo/lib/tpl.base.lib.tengo +4 -1
  10. package/dist/tengo/tpl/annotations.compute.plj.gz +0 -0
  11. package/dist/tengo/tpl/anonymize.deanonymize.plj.gz +0 -0
  12. package/dist/tengo/tpl/anonymize.impl.plj.gz +0 -0
  13. package/dist/tengo/tpl/check_network.create_workdir_from_storage.plj.gz +0 -0
  14. package/dist/tengo/tpl/check_network.download_blob.plj.gz +0 -0
  15. package/dist/tengo/tpl/check_network.run_hello_world.plj.gz +0 -0
  16. package/dist/tengo/tpl/check_network.run_hello_world_py.plj.gz +0 -0
  17. package/dist/tengo/tpl/check_network.upload_blob.plj.gz +0 -0
  18. package/dist/tengo/tpl/check_network.upload_template.plj.gz +0 -0
  19. package/dist/tengo/tpl/check_network.workdir_type_name_extractor.plj.gz +0 -0
  20. package/dist/tengo/tpl/exec.conda.create-env.plj.gz +0 -0
  21. package/dist/tengo/tpl/exec.delayed-compute-allocation.impl.plj.gz +0 -0
  22. package/dist/tengo/tpl/exec.exec-impl.plj.gz +0 -0
  23. package/dist/tengo/tpl/exec.exec.plj.gz +0 -0
  24. package/dist/tengo/tpl/exec.load-software.impl.plj.gz +0 -0
  25. package/dist/tengo/tpl/exec.monetization_info.plj.gz +0 -0
  26. package/dist/tengo/tpl/exec.monetization_to_json.plj.gz +0 -0
  27. package/dist/tengo/tpl/exec.python.create-venv.plj.gz +0 -0
  28. package/dist/tengo/tpl/exec.python.install-deps.plj.gz +0 -0
  29. package/dist/tengo/tpl/exec.python.venv-bin-path.plj.gz +0 -0
  30. package/dist/tengo/tpl/ll.get-field.plj.gz +0 -0
  31. package/dist/tengo/tpl/pframes.build-table.plj.gz +0 -0
  32. package/dist/tengo/tpl/pframes.export-multiple-pcolumns.plj.gz +0 -0
  33. package/dist/tengo/tpl/pframes.export-parquet-pcolumn-chunk.plj.gz +0 -0
  34. package/dist/tengo/tpl/pframes.export-pframe-for-ui.plj.gz +0 -0
  35. package/dist/tengo/tpl/pframes.export-pframe.plj.gz +0 -0
  36. package/dist/tengo/tpl/pframes.export-single-pcolumn.plj.gz +0 -0
  37. package/dist/tengo/tpl/pframes.import-dir.plj.gz +0 -0
  38. package/dist/tengo/tpl/pframes.merge-resource-maps.plj.gz +0 -0
  39. package/dist/tengo/tpl/pframes.parse-to-json.plj.gz +0 -0
  40. package/dist/tengo/tpl/pframes.process-pcolumn-batch-split.plj.gz +0 -0
  41. package/dist/tengo/tpl/pframes.process-pcolumn-batch.plj.gz +0 -0
  42. package/dist/tengo/tpl/pframes.process-pcolumn-data.plj.gz +0 -0
  43. package/dist/tengo/tpl/pframes.remove-nulls.plj.gz +0 -0
  44. package/dist/tengo/tpl/pframes.slice-data.plj.gz +0 -0
  45. package/dist/tengo/tpl/pframes.xsv-export-pframe.plj.gz +0 -0
  46. package/dist/tengo/tpl/pframes.xsv-import-if-not-null.plj.gz +0 -0
  47. package/dist/tengo/tpl/pframes.xsv-import-map.plj.gz +0 -0
  48. package/dist/tengo/tpl/pt.import-dir.plj.gz +0 -0
  49. package/dist/tengo/tpl/pt.workflow-run.plj.gz +0 -0
  50. package/dist/tengo/tpl/waiter.waiter.plj.gz +0 -0
  51. package/dist/tengo/tpl/workdir.save.plj.gz +0 -0
  52. package/dist/tengo/tpl/workflow.build-ctx.plj.gz +0 -0
  53. package/dist/tengo/tpl/workflow.query-anchored.plj.gz +0 -0
  54. package/dist/tengo/tpl/workflow.query-context-filter.plj.gz +0 -0
  55. package/package.json +2 -2
@@ -0,0 +1,366 @@
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+ ll := import("@platforma-sdk/workflow-tengo:ll")
18
+ maps := import("@platforma-sdk/workflow-tengo:maps")
19
+ slices := import("@platforma-sdk/workflow-tengo:slices")
20
+ pSpec := import("@platforma-sdk/workflow-tengo:pframes.spec")
21
+ builder := import("@platforma-sdk/workflow-tengo:pframes.builder")
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+ buildOutputTrace := func(opts, output, inputSpec) {
42
+ hasOutputTrace := !is_undefined(output.traceSteps)
43
+ hasGlobalTrace := !is_undefined(opts.traceSteps)
44
+ hasInputTrace := !is_undefined(inputSpec.annotations) && !is_undefined(inputSpec.annotations[pSpec.A_TRACE])
45
+
46
+ outputTraceSteps := slices.normalize(opts.traceSteps) + slices.normalize(output.traceSteps)
47
+
48
+ trace := undefined
49
+ if len(outputTraceSteps) > 0 || hasInputTrace {
50
+ trace = pSpec.makeTrace(inputSpec, outputTraceSteps...)
51
+ }
52
+
53
+ outputOverrideTrace := output.overrideTrace
54
+ if is_undefined(outputOverrideTrace) {
55
+ outputOverrideTrace = hasOutputTrace || hasGlobalTrace
56
+ }
57
+
58
+ return { trace: trace, overrideTrace: outputOverrideTrace }
59
+ }
60
+
61
+
62
+
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+
82
+
83
+
84
+
85
+
86
+ createProcessColumnResult := func(renderResult, outputsMap, outputSpecs) {
87
+ _isColumnar := func(output) {
88
+ return output.type == "Xsv" || output.type == "TsvContent"
89
+ }
90
+ _requireOutput := func(name) {
91
+ output := outputsMap[name]
92
+ ll.assert(!is_undefined(output), "unknown output: %v", name)
93
+ return output
94
+ }
95
+
96
+
97
+ _requireColumnArg := func(output, column) {
98
+ if _isColumnar(output) {
99
+ ll.assert(len(column) == 1,
100
+ "column name must be provided for %s output", output.type)
101
+ return column[0]
102
+ }
103
+ ll.assert(len(column) == 0,
104
+ "column name should not be provided for non-Xsv/TsvContent output")
105
+ return undefined
106
+ }
107
+ _requireColumnSpec := func(name, columnName) {
108
+ spec := outputSpecs[name][columnName]
109
+ ll.assert(!is_undefined(spec), "unknown column: %v", columnName)
110
+ return spec
111
+ }
112
+
113
+ self := undefined
114
+ self = ll.toStrict({
115
+ renderResult: renderResult,
116
+
117
+
118
+
119
+
120
+ outputSpec: func(name, ...column) {
121
+ output := _requireOutput(name)
122
+ columnName := _requireColumnArg(output, column)
123
+ if _isColumnar(output) {
124
+ return _requireColumnSpec(name, columnName)
125
+ }
126
+ return outputSpecs[name]
127
+ },
128
+
129
+
130
+
131
+
132
+ outputData: func(name, ...column) {
133
+ output := _requireOutput(name)
134
+ columnName := _requireColumnArg(output, column)
135
+ if _isColumnar(output) {
136
+ return renderResult.output(name + "/" + columnName)
137
+ }
138
+ return renderResult.output(name)
139
+ },
140
+
141
+
142
+
143
+
144
+ output: func(name, ...column) {
145
+ output := _requireOutput(name)
146
+ columnName := _requireColumnArg(output, column)
147
+ if _isColumnar(output) {
148
+ return {
149
+ data: renderResult.output(name + "/" + columnName),
150
+ spec: _requireColumnSpec(name, columnName)
151
+ }
152
+ }
153
+ return {
154
+ data: renderResult.output(name),
155
+ spec: outputSpecs[name]
156
+ }
157
+ },
158
+
159
+
160
+
161
+
162
+ xsvOutputFrame: func(name) {
163
+ output := _requireOutput(name)
164
+ ll.assert(_isColumnar(output),
165
+ "xsvOutputFrame can only be used with Xsv or TsvContent outputs")
166
+ pf := builder.pFrameBuilder()
167
+ for columnName, spec in outputSpecs[name] {
168
+ pf.add(columnName, spec, renderResult.output(name + "/" + columnName))
169
+ }
170
+ return pf.build()
171
+ },
172
+
173
+
174
+
175
+
176
+
177
+ addAllOutputsToBuilder: func(bld, ...separator) {
178
+ sep := "."
179
+ if len(separator) > 0 {
180
+ sep = separator[0]
181
+ }
182
+ maps.forEach(outputsMap, func(name, output) {
183
+ if _isColumnar(output) {
184
+ for columnName, spec in outputSpecs[name] {
185
+ bld.add(
186
+ name + sep + columnName,
187
+ spec,
188
+ renderResult.output(name + "/" + columnName)
189
+ )
190
+ }
191
+ } else {
192
+ bld.add(name, outputSpecs[name], renderResult.output(name))
193
+ }
194
+ })
195
+ return bld
196
+ },
197
+
198
+
199
+
200
+
201
+ allOutputsFrame: func(...xsvNameSeparator) {
202
+ pf := builder.pFrameBuilder()
203
+ self.addAllOutputsToBuilder(pf, xsvNameSeparator...)
204
+ return pf.build()
205
+ },
206
+
207
+
208
+
209
+
210
+ listOutputs: func() {
211
+ return maps.getKeys(outputsMap)
212
+ },
213
+
214
+
215
+
216
+
217
+
218
+ isXsvOutput: func(name) {
219
+ return _isColumnar(_requireOutput(name))
220
+ },
221
+
222
+
223
+
224
+
225
+ listXsvColumns: func(name) {
226
+ output := _requireOutput(name)
227
+ ll.assert(_isColumnar(output), "output is not Xsv or TsvContent: %v", name)
228
+ return maps.getKeys(outputSpecs[name])
229
+ },
230
+
231
+
232
+
233
+
234
+
235
+ addXsvOutputToBuilder: func(bld, outputName, prefix) {
236
+ for columnName in self.listXsvColumns(outputName) {
237
+ bld.add(
238
+ prefix + columnName,
239
+ self.outputSpec(outputName, columnName),
240
+ self.outputData(outputName, columnName)
241
+ )
242
+ }
243
+ return bld
244
+ }
245
+ })
246
+
247
+ return self
248
+ }
249
+
250
+
251
+
252
+
253
+
254
+
255
+
256
+
257
+
258
+
259
+
260
+
261
+
262
+
263
+ deriveHeaderFromSpec := func(spec) {
264
+ if !is_undefined(spec.annotations) {
265
+ label := spec.annotations[pSpec.A_LABEL]
266
+ if is_string(label) && label != "" {
267
+ return label
268
+ }
269
+ }
270
+ if is_string(spec.name) && spec.name != "" {
271
+ return spec.name
272
+ }
273
+ ll.panic("cannot derive header from spec: no label annotation or name found")
274
+ }
275
+
276
+
277
+
278
+
279
+
280
+
281
+
282
+
283
+
284
+
285
+
286
+
287
+
288
+
289
+
290
+
291
+ resolveColumnSrc := func(entry) {
292
+ src := entry.src
293
+ filter := undefined
294
+
295
+ if is_map(src) && src.__isPrimaryRef == "v1" {
296
+ filter = src.filter
297
+ src = src.column
298
+ }
299
+
300
+ ll.assert(is_map(src) && !is_undefined(src.spec) && !is_undefined(src.data),
301
+ "column src must be { spec, data }, got: %v", src)
302
+
303
+ header := entry.header
304
+ if is_undefined(header) {
305
+ header = deriveHeaderFromSpec(src.spec)
306
+ }
307
+
308
+ result := { src: src, header: header }
309
+ if !is_undefined(filter) {
310
+ result.filter = filter
311
+ }
312
+ return result
313
+ }
314
+
315
+
316
+
317
+
318
+
319
+
320
+
321
+
322
+
323
+
324
+
325
+
326
+
327
+
328
+
329
+
330
+
331
+ normalizeColumnEntries := func(input) {
332
+ if is_undefined(input) {
333
+ return []
334
+ }
335
+
336
+
337
+
338
+
339
+ _isBareColumn := func(m) { return !is_undefined(m.spec) && !is_undefined(m.data) }
340
+ _isPrimaryRef := func(m) { return m.__isPrimaryRef == "v1" }
341
+ _normalizeEntry := func(entry) {
342
+ ll.assert(is_map(entry), "unrecognized column entry: %v", entry)
343
+ if !is_undefined(entry.src) {
344
+ return resolveColumnSrc(entry)
345
+ }
346
+ ll.assert(_isBareColumn(entry) || _isPrimaryRef(entry),
347
+ "unrecognized column entry: %v", entry)
348
+ return resolveColumnSrc({ src: entry })
349
+ }
350
+
351
+
352
+ if is_map(input) {
353
+ input = [input]
354
+ }
355
+ ll.assert(is_array(input), "column entries must be an array, got: %v", input)
356
+
357
+ return slices.map(input, _normalizeEntry)
358
+ }
359
+
360
+ export ll.toStrict({
361
+ buildOutputTrace: buildOutputTrace,
362
+ createProcessColumnResult: createProcessColumnResult,
363
+ deriveHeaderFromSpec: deriveHeaderFromSpec,
364
+ resolveColumnSrc: resolveColumnSrc,
365
+ normalizeColumnEntries: normalizeColumnEntries
366
+ })
@@ -0,0 +1,242 @@
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+ ll := import("@platforma-sdk/workflow-tengo:ll")
16
+ smart := import("@platforma-sdk/workflow-tengo:smart")
17
+ maps := import("@platforma-sdk/workflow-tengo:maps")
18
+ text := import("text")
19
+ json := import("json")
20
+ pConstants := import("@platforma-sdk/workflow-tengo:pframes.constants")
21
+ pUtil := import("@platforma-sdk/workflow-tengo:pframes.util")
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+ resolveData := func(data) {
35
+ if smart.isField(data) {
36
+ return data.getValue()
37
+ }
38
+ return data
39
+ }
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+
51
+
52
+
53
+
54
+
55
+
56
+ classifyPColumnData := func(res) {
57
+ if res.checkResourceType(pConstants.RTYPE_P_COLUMN_DATA_BINARY_PARTITIONED) {
58
+ return { type: pConstants.RTYPE_P_COLUMN_DATA_BINARY_PARTITIONED, isBinary: true }
59
+ } else if res.checkResourceType(pConstants.RTYPE_P_COLUMN_DATA_JSON_PARTITIONED) {
60
+ return { type: pConstants.RTYPE_P_COLUMN_DATA_JSON_PARTITIONED, isBinary: false }
61
+ } else if res.checkResourceType(pConstants.RTYPE_P_COLUMN_DATA_PARQUET_PARTITIONED) {
62
+ return { type: pConstants.RTYPE_P_COLUMN_DATA_PARQUET_PARTITIONED, isBinary: false }
63
+ } else if res.checkResourceType(pConstants.RTYPE_P_COLUMN_DATA_JSON) {
64
+ return { type: pConstants.RTYPE_P_COLUMN_DATA_JSON, isBinary: false, isJson: true }
65
+ }
66
+ ll.panic("Unsupported data type for batch mode grouping: %v", res)
67
+ }
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+ recordsInGroup := func(groupRes) {
82
+ if is_undefined(groupRes) {
83
+ return 0
84
+ }
85
+ if groupRes.checkResourceType(pConstants.RTYPE_P_COLUMN_DATA_JSON) {
86
+ return len(groupRes.getDataAsJson().data)
87
+ }
88
+ if groupRes.checkResourceType(pConstants.RTYPE_P_COLUMN_DATA_BINARY_PARTITIONED) {
89
+
90
+ return len(groupRes.inputs()) / 2
91
+ }
92
+
93
+ return len(groupRes.inputs())
94
+ }
95
+
96
+
97
+
98
+
99
+
100
+
101
+
102
+
103
+
104
+
105
+
106
+
107
+
108
+
109
+ forEachOutputField := func(outputDefs, fn) {
110
+ for output in outputDefs {
111
+ if output.type == "ResourceMap" {
112
+ fn(output, output.name)
113
+ } else if output.type == "Xsv" {
114
+ for column in output.settings.columns {
115
+ id := pUtil.xsvColumnId(column)
116
+ fn(output, output.name + "/" + id)
117
+ }
118
+ }
119
+ }
120
+ }
121
+
122
+
123
+
124
+
125
+
126
+
127
+
128
+
129
+
130
+
131
+
132
+
133
+
134
+
135
+
136
+
137
+
138
+
139
+
140
+
141
+
142
+
143
+
144
+
145
+
146
+ groupColumnData := func(data, isolationIndices, batchKeyIndices, batchKeyLength, hasIsolation) {
147
+ res := resolveData(data)
148
+ if !hasIsolation {
149
+ return { "[]": res }
150
+ }
151
+ typeInfo := classifyPColumnData(res)
152
+ groups := {}
153
+
154
+ if typeInfo.isJson {
155
+ meta := res.getDataAsJson()
156
+ for sKey, value in meta.data {
157
+ keyArray := json.decode(sKey)
158
+
159
+ isolationKey := []
160
+ for i in isolationIndices {
161
+ isolationKey = append(isolationKey, keyArray[i])
162
+ }
163
+ inGroupKey := []
164
+ for i in batchKeyIndices {
165
+ inGroupKey = append(inGroupKey, keyArray[i])
166
+ }
167
+
168
+ sIsolationKey := json.encode(isolationKey)
169
+ sInGroupKey := json.encode(inGroupKey)
170
+
171
+ group := groups[sIsolationKey]
172
+ if is_undefined(group) {
173
+ group = {}
174
+ groups[sIsolationKey] = group
175
+ }
176
+ group[sInGroupKey] = value
177
+ }
178
+ for sIsolationKey, groupData in groups {
179
+ groups[sIsolationKey] = smart.structBuilder(
180
+ pConstants.RTYPE_P_COLUMN_DATA_JSON,
181
+ json.encode({ keyLength: batchKeyLength, data: groupData })
182
+ ).lockAndBuild()
183
+ }
184
+ } else {
185
+
186
+
187
+
188
+
189
+
190
+
191
+ resInputs := res.inputs()
192
+ for sKey in maps.getKeys(resInputs) {
193
+ field := resInputs[sKey]
194
+ sKeyP := sKey
195
+ suffix := ""
196
+ if typeInfo.isBinary {
197
+ dotIdx := text.last_index(sKey, ".")
198
+ ll.assert(dotIdx != -1, "BinaryPartitioned key must contain a dot: %v", sKey)
199
+ suffix = sKey[dotIdx:]
200
+ sKeyP = sKey[:dotIdx]
201
+ }
202
+ keyArray := json.decode(sKeyP)
203
+
204
+ isolationKey := []
205
+ for i in isolationIndices {
206
+ isolationKey = append(isolationKey, keyArray[i])
207
+ }
208
+ inGroupKey := []
209
+ for i in batchKeyIndices {
210
+ ll.assert(i < len(keyArray),
211
+ "malformed partition key %v: fewer components than the axes spec (index %v out of range)", sKeyP, i)
212
+ inGroupKey = append(inGroupKey, keyArray[i])
213
+ }
214
+
215
+ sIsolationKey := json.encode(isolationKey)
216
+ sInGroupKey := json.encode(inGroupKey)
217
+
218
+ group := groups[sIsolationKey]
219
+ if is_undefined(group) {
220
+ group = smart.structBuilder(
221
+ typeInfo.type,
222
+ json.encode({ partitionKeyLength: batchKeyLength })
223
+ )
224
+ groups[sIsolationKey] = group
225
+ }
226
+ group.createInputField(sInGroupKey + suffix).set(field)
227
+ }
228
+ for sIsolationKey in maps.getKeys(groups) {
229
+ groups[sIsolationKey] = groups[sIsolationKey].lockAndBuild()
230
+ }
231
+ }
232
+
233
+ return groups
234
+ }
235
+
236
+ export ll.toStrict({
237
+ resolveData: resolveData,
238
+ classifyPColumnData: classifyPColumnData,
239
+ recordsInGroup: recordsInGroup,
240
+ forEachOutputField: forEachOutputField,
241
+ groupColumnData: groupColumnData
242
+ })
@@ -410,6 +410,9 @@ tableBuilder := func(format, ...ctxArg) {
410
410
 
411
411
  for _, rawFlt in rawFilters {
412
412
  resolvedFlt := resolveColumn(rawFlt)
413
+ if is_undefined(resolvedFlt.spec) {
414
+ continue
415
+ }
413
416
  entry.filters = append(entry.filters, {
414
417
  spec: resolvedFlt.spec,
415
418
  data: resolvedFlt.data
@@ -103,9 +103,12 @@ AWAIT_TEMPLATES := {
103
103
 
104
104
 
105
105
 
106
+
107
+
108
+
106
109
  "PrimarySpecsReady": [
107
110
  ["column", "spec", "ResourceReady"],
108
- [{ match: "^filter$" }, "spec", "ResourceReady"]
111
+ [{ match: "^filter$" }, { match: "^spec$" }, "ResourceReady"]
109
112
  ]
110
113
  }
111
114
 
Binary file
Binary file