@platforma-sdk/workflow-tengo 4.15.0 → 4.17.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 (41) hide show
  1. package/dist/tengo/lib/pframes.data.lib.tengo +187 -3
  2. package/dist/tengo/lib/pt.expression.lib.tengo +71 -0
  3. package/dist/tengo/lib/pt.lib.tengo +83 -0
  4. package/dist/tengo/lib/slices.lib.tengo +37 -0
  5. package/dist/tengo/tpl/anonymize.deanonymize.plj.gz +0 -0
  6. package/dist/tengo/tpl/anonymize.impl.plj.gz +0 -0
  7. package/dist/tengo/tpl/check_network.create_workdir_from_storage.plj.gz +0 -0
  8. package/dist/tengo/tpl/check_network.download_blob.plj.gz +0 -0
  9. package/dist/tengo/tpl/check_network.run_hello_world.plj.gz +0 -0
  10. package/dist/tengo/tpl/check_network.run_hello_world_py.plj.gz +0 -0
  11. package/dist/tengo/tpl/check_network.upload_blob.plj.gz +0 -0
  12. package/dist/tengo/tpl/check_network.upload_template.plj.gz +0 -0
  13. package/dist/tengo/tpl/check_network.workdir_type_name_extractor.plj.gz +0 -0
  14. package/dist/tengo/tpl/exec.R.create-renv.plj.gz +0 -0
  15. package/dist/tengo/tpl/exec.delayed-compute-allocation.impl.plj.gz +0 -0
  16. package/dist/tengo/tpl/exec.exec-impl.plj.gz +0 -0
  17. package/dist/tengo/tpl/exec.exec.plj.gz +0 -0
  18. package/dist/tengo/tpl/exec.load-software.impl.plj.gz +0 -0
  19. package/dist/tengo/tpl/exec.monetization_info.plj.gz +0 -0
  20. package/dist/tengo/tpl/exec.monetization_to_json.plj.gz +0 -0
  21. package/dist/tengo/tpl/exec.python.create-venv.plj.gz +0 -0
  22. package/dist/tengo/tpl/exec.python.install-deps.plj.gz +0 -0
  23. package/dist/tengo/tpl/exec.python.venv-bin-path.plj.gz +0 -0
  24. package/dist/tengo/tpl/ll.get-field.plj.gz +0 -0
  25. package/dist/tengo/tpl/pframes.export-multiple-pcolumns.plj.gz +0 -0
  26. package/dist/tengo/tpl/pframes.export-pframe-for-ui.plj.gz +0 -0
  27. package/dist/tengo/tpl/pframes.export-pframe.plj.gz +0 -0
  28. package/dist/tengo/tpl/pframes.export-single-pcolumn.plj.gz +0 -0
  29. package/dist/tengo/tpl/pframes.import-dir.plj.gz +0 -0
  30. package/dist/tengo/tpl/pframes.parse-to-json.plj.gz +0 -0
  31. package/dist/tengo/tpl/pframes.process-pcolumn-data.plj.gz +0 -0
  32. package/dist/tengo/tpl/pframes.remove-nulls.plj.gz +0 -0
  33. package/dist/tengo/tpl/pframes.slice-data.plj.gz +0 -0
  34. package/dist/tengo/tpl/pframes.xsv-export-pframe.plj.gz +0 -0
  35. package/dist/tengo/tpl/pframes.xsv-import-if-not-null.plj.gz +0 -0
  36. package/dist/tengo/tpl/pframes.xsv-import-map.plj.gz +0 -0
  37. package/dist/tengo/tpl/waiter.waiter.plj.gz +0 -0
  38. package/dist/tengo/tpl/workdir.save.plj.gz +0 -0
  39. package/dist/tengo/tpl/workflow.build-ctx.plj.gz +0 -0
  40. package/dist/tengo/tpl/workflow.query-anchored.plj.gz +0 -0
  41. package/package.json +3 -3
@@ -98,9 +98,12 @@ parseData := func(inputParam, ...optsRaw) {
98
98
  state.keyLength = resourceData.keyLength
99
99
  state.relevantTopLayerKeyLength = state.keyLength
100
100
  } else if state.resourceType == pConstants.RTYPE_P_COLUMN_DATA_JSON_PARTITIONED ||
101
- state.resourceType == pConstants.RTYPE_P_COLUMN_DATA_BINARY_PARTITIONED ||
102
- state.resourceType == pConstants.RTYPE_P_COLUMN_DATA_RESOURCE_MAP_PARTITIONED {
101
+ state.resourceType == pConstants.RTYPE_P_COLUMN_DATA_BINARY_PARTITIONED {
102
+ state.partitionKeyLength = resourceData.partitionKeyLength
103
+ state.relevantTopLayerKeyLength = state.partitionKeyLength
104
+ } else if state.resourceType == pConstants.RTYPE_P_COLUMN_DATA_RESOURCE_MAP_PARTITIONED {
103
105
  state.partitionKeyLength = resourceData.partitionKeyLength
106
+ state.keyLength = resourceData.keyLength
104
107
  state.relevantTopLayerKeyLength = state.partitionKeyLength
105
108
  } else if state.resourceType == pConstants.RTYPE_P_COLUMN_DATA_JSON_SUPER_PARTITIONED ||
106
109
  state.resourceType == pConstants.RTYPE_P_COLUMN_DATA_BINARY_SUPER_PARTITIONED {
@@ -188,26 +191,86 @@ _createPColumnDataInstance = func(state) {
188
191
  self := undefined
189
192
 
190
193
  self = ll.toStrict({
194
+
195
+
196
+
197
+
198
+
191
199
  resource: state.resource,
192
200
 
201
+
202
+
203
+
204
+
193
205
  parsed: state.parsed,
194
206
 
207
+
208
+
209
+
210
+
211
+
212
+
213
+
195
214
  getSpec: func() {
196
215
  return state.spec
197
216
  },
198
217
 
218
+
219
+
220
+
221
+
222
+
199
223
  getResourceType: func() {
200
224
  return state.resourceType
201
225
  },
202
226
 
227
+
228
+
229
+
230
+
203
231
  keyLength: state.keyLength,
232
+
233
+
234
+
235
+
236
+
237
+
204
238
  partitionKeyLength: state.partitionKeyLength,
239
+
240
+
241
+
242
+
243
+
205
244
  superPartitionKeyLength: state.superPartitionKeyLength,
206
245
 
246
+
247
+
248
+
249
+
250
+
251
+
252
+
253
+
207
254
  data: state.data,
208
255
 
256
+
257
+
258
+
259
+
260
+
261
+
262
+
209
263
  parseKey: _createDecodeKeyString,
210
264
 
265
+
266
+
267
+
268
+
269
+
270
+
271
+
272
+
273
+
211
274
  uniqueKeyValues: func(axisIdx) {
212
275
  if !state.parsed {
213
276
  ll.panic("uniqueKeyValues: resource is not parsed.")
@@ -224,6 +287,17 @@ _createPColumnDataInstance = func(state) {
224
287
  return maps.values(uniqueValsMap)
225
288
  },
226
289
 
290
+
291
+
292
+
293
+
294
+
295
+
296
+
297
+
298
+
299
+
300
+
227
301
  createDataResource: func() {
228
302
  if !is_undefined(state.resource) {
229
303
 
@@ -271,6 +345,27 @@ _createPColumnDataInstance = func(state) {
271
345
  return builder.lockAndBuild()
272
346
  },
273
347
 
348
+
349
+
350
+
351
+
352
+
353
+
354
+
355
+
356
+
357
+
358
+
359
+
360
+
361
+
362
+
363
+
364
+
365
+
366
+
367
+
368
+
274
369
  filter: func(slicingParams) {
275
370
  if len(slicingParams) == 0 {
276
371
  return self
@@ -465,6 +560,26 @@ _createPColumnDataInstance = func(state) {
465
560
  ll.panic("Filtering not supported for type %s", state.resourceType)
466
561
  }
467
562
  },
563
+
564
+
565
+
566
+
567
+
568
+
569
+
570
+
571
+
572
+
573
+
574
+
575
+
576
+
577
+
578
+
579
+
580
+
581
+
582
+
468
583
 
469
584
  partition: func(...axesToPartitionBy) {
470
585
  if !state.parsed {
@@ -511,6 +626,20 @@ _createPColumnDataInstance = func(state) {
511
626
  return resultPartitions
512
627
  },
513
628
 
629
+
630
+
631
+
632
+
633
+
634
+
635
+
636
+
637
+
638
+
639
+
640
+
641
+
642
+
514
643
  forEach: func(userCallback) {
515
644
  if !state.parsed {
516
645
  ll.panic("forEach: resource is not parsed.")
@@ -525,6 +654,61 @@ _createPColumnDataInstance = func(state) {
525
654
  })
526
655
  },
527
656
 
657
+
658
+
659
+
660
+
661
+
662
+
663
+
664
+
665
+
666
+
667
+
668
+
669
+
670
+
671
+
672
+
673
+
674
+
675
+ forEachPartition: func(axesToPartitionBy, userCallback) {
676
+ if !state.parsed {
677
+ ll.panic("forEachPartition: resource is not parsed.")
678
+ }
679
+ if !is_array(axesToPartitionBy) {
680
+ ll.panic("forEachPartition: first argument must be an array of axis indices.")
681
+ }
682
+ if !is_callable(userCallback) {
683
+ ll.panic("forEachPartition: second argument must be a function.")
684
+ }
685
+
686
+ partitions := self.partition(axesToPartitionBy...)
687
+
688
+ maps.forEach(partitions, func(partitionKeyStr, partitionPColumnData) {
689
+ decodedPartitionKey := json.decode(partitionKeyStr)
690
+ userCallback(decodedPartitionKey, partitionPColumnData)
691
+ })
692
+ },
693
+
694
+
695
+
696
+
697
+
698
+
699
+
700
+
701
+
702
+
703
+
704
+
705
+
706
+
707
+
708
+
709
+
710
+
711
+
528
712
  flatten: func() {
529
713
  if !state.parsed {
530
714
  ll.panic("flatten: resource is not parsed.")
@@ -532,7 +716,7 @@ _createPColumnDataInstance = func(state) {
532
716
 
533
717
  isJsonSuper := state.resourceType == pConstants.RTYPE_P_COLUMN_DATA_JSON_SUPER_PARTITIONED
534
718
  isBinarySuper := state.resourceType == pConstants.RTYPE_P_COLUMN_DATA_BINARY_SUPER_PARTITIONED
535
- isResourceMapSuper := state.resourceType == pConstants.RTYPE_P_COLUMN_DATA_RESOURCE_MAP_SUPER_PARTITIONED
719
+ isResourceMapSuper := state.resourceType == pConstants.RTYPE_P_COLUMN_DATA_RESOURCE_MAP_PARTITIONED
536
720
 
537
721
  if !(isJsonSuper || isBinarySuper || isResourceMapSuper) {
538
722
  return self // Not a type that can be flattened
@@ -323,6 +323,77 @@ _newExpression = func(expression, currentAlias) {
323
323
  isNotNull: func() { return unaryOp("is_not_na") }, // Polars: is_not_null(), TS: is_not_na
324
324
 
325
325
 
326
+
327
+
328
+
329
+
330
+
331
+
332
+
333
+
334
+
335
+
336
+
337
+
338
+
339
+
340
+
341
+
342
+
343
+
344
+
345
+
346
+
347
+
348
+
349
+
350
+ structField: func(fieldPath, ...options) {
351
+
352
+ ll.assert(!is_undefined(fieldPath), "structField expects a field path (string or array of strings)")
353
+
354
+ fields := undefined
355
+ if is_string(fieldPath) {
356
+ fields = fieldPath
357
+ } else if is_array(fieldPath) {
358
+ ll.assert(len(fieldPath) > 0, "structField field path array cannot be empty")
359
+ for fieldName in fieldPath {
360
+ ll.assert(is_string(fieldName), "All field names in path must be strings, got: %T", fieldName)
361
+ }
362
+ if len(fieldPath) == 1 {
363
+ fields = fieldPath[0]
364
+ } else {
365
+ fields = fieldPath
366
+ }
367
+ } else {
368
+ ll.panic("structField fieldPath must be a string or array of strings, got: %T", fieldPath)
369
+ }
370
+
371
+
372
+ ops := _validateOptions(options, {
373
+ "__options__,closed": "",
374
+ "default,?": "any",
375
+ "dtype,?": "string"
376
+ }, "structField")
377
+
378
+
379
+ structExpr := {
380
+ type: "struct_field",
381
+ struct: expression,
382
+ fields: fields
383
+ }
384
+
385
+
386
+ if !is_undefined(ops.default) {
387
+ structExpr.default = ops.default
388
+ }
389
+ if !is_undefined(ops.dtype) {
390
+ structExpr.dtype = ops.dtype
391
+ }
392
+
393
+ return _newExpression(structExpr, undefined)
394
+ },
395
+
396
+
326
397
 
327
398
  strToUpper: func() { return unaryStrOp("to_upper") },
328
399
 
@@ -1195,9 +1195,92 @@ concat := func(dataframes, ...optionsRaw) {
1195
1195
  return _newDataFrame(parentWorkflow, outputDfName)
1196
1196
  }
1197
1197
 
1198
+
1199
+
1200
+
1201
+
1202
+
1203
+
1204
+
1205
+
1206
+
1207
+
1208
+
1209
+
1210
+
1211
+
1212
+
1213
+
1214
+
1215
+
1216
+
1217
+
1218
+
1219
+
1220
+
1221
+
1222
+
1223
+
1224
+
1225
+
1226
+
1227
+ treeJoin := func(dataframes, opts) {
1228
+ ll.assert(is_array(dataframes), "First argument to treeJoin must be an array of DataFrame objects.")
1229
+ ll.assert(len(dataframes) > 0, "DataFrame array for treeJoin cannot be empty.")
1230
+
1231
+ if !is_map(opts) || is_undefined(opts.on) {
1232
+ ll.panic("treeJoin requires options with 'on' field")
1233
+ }
1234
+ if !is_string(opts.on) {
1235
+ ll.panic("'on' option must be a string")
1236
+ }
1237
+
1238
+
1239
+ if len(dataframes) == 1 {
1240
+ return dataframes[0]
1241
+ }
1242
+
1243
+
1244
+ parentWorkflow := undefined
1245
+ for i, df in dataframes {
1246
+ if is_undefined(df) || is_undefined(df._getDfName) || is_undefined(df._getWorkflow) {
1247
+ ll.panic("Argument at index %d in dataframes array is not a valid DataFrame object.", i)
1248
+ }
1249
+ currentWorkflow := df._getWorkflow()
1250
+ if is_undefined(parentWorkflow) {
1251
+ parentWorkflow = currentWorkflow
1252
+ } else if currentWorkflow._wfId != parentWorkflow._wfId {
1253
+ ll.panic("All DataFrames in a treeJoin operation must belong to the same workflow.")
1254
+ }
1255
+ }
1256
+
1257
+ pfs := dataframes
1258
+
1259
+
1260
+ for len(pfs) > 1 {
1261
+ nextPfs := []
1262
+
1263
+ for i := 1; i < len(pfs); i += 2 {
1264
+ pf1 := pfs[i - 1]
1265
+ pf2 := pfs[i]
1266
+ joined := pf1.join(pf2, { on: opts.on, how: "full", coalesce: true })
1267
+ nextPfs = append(nextPfs, joined)
1268
+ }
1269
+
1270
+ if len(pfs) % 2 == 1 {
1271
+ nextPfs = append(nextPfs, pfs[len(pfs) - 1])
1272
+ }
1273
+ pfs = nextPfs
1274
+ }
1275
+
1276
+ ll.assert(len(pfs) == 1, "Expected exactly one data frame, got " + string(len(pfs)))
1277
+ return pfs[0]
1278
+ }
1279
+
1198
1280
  export ll.toStrict({
1199
1281
  workflow: workflow,
1200
1282
  concat: concat,
1283
+ treeJoin: treeJoin,
1201
1284
 
1202
1285
  col: exp.col,
1203
1286
  lit: exp.lit,
@@ -153,6 +153,42 @@ reduce := func(slice, fn, ...init) {
153
153
  }
154
154
 
155
155
 
156
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
164
+ flatten := func(slice, ...opts) {
165
+ if is_undefined(slice) {
166
+ return []
167
+ }
168
+
169
+ deep := false
170
+ if len(opts) > 0 && !is_undefined(opts[0]) && !is_undefined(opts[0].deep) {
171
+ deep = opts[0].deep
172
+ }
173
+
174
+ result := []
175
+ for _, elem in slice {
176
+ if is_array(elem) {
177
+ if deep {
178
+ flattened := flatten(elem, {deep: true})
179
+ result = append(result, flattened...)
180
+ } else {
181
+ result = append(result, elem...)
182
+ }
183
+ } else {
184
+ ll.panic("flatten: expected array element but got %s", type_name(elem))
185
+ }
186
+ }
187
+
188
+ return result
189
+ }
190
+
191
+
156
192
  every := func(slice, fn) {
157
193
  for _, elem in slice {
158
194
  if !fn(elem) {
@@ -322,6 +358,7 @@ export ll.toStrict({
322
358
  filter: filter,
323
359
  map: map,
324
360
  reduce: reduce,
361
+ flatten: flatten,
325
362
  every: every,
326
363
  quickSortInPlace: quickSortInPlace,
327
364
  quickSort: quickSort,
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platforma-sdk/workflow-tengo",
3
- "version": "4.15.0",
3
+ "version": "4.17.0",
4
4
  "description": "Tengo SDK library",
5
5
  "types": "./dist/index.d.ts",
6
6
  "main": "./dist/index.js",
@@ -18,10 +18,10 @@
18
18
  "dependencies": {
19
19
  "@milaboratories/software-pframes-conv": "2.2.2",
20
20
  "@platforma-open/milaboratories.software-small-binaries": "^1.15.21",
21
- "@platforma-open/milaboratories.software-ptabler": "1.9.0"
21
+ "@platforma-open/milaboratories.software-ptabler": "1.12.0"
22
22
  },
23
23
  "devDependencies": {
24
- "@platforma-sdk/tengo-builder": "^2.1.13"
24
+ "@platforma-sdk/tengo-builder": "^2.1.14"
25
25
  },
26
26
  "scripts": {
27
27
  "type-check": "pl-tengo check",