@platforma-sdk/workflow-tengo 4.10.0 → 4.12.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 (38) hide show
  1. package/dist/tengo/lib/pt.expression.lib.tengo +249 -59
  2. package/dist/tengo/lib/pt.lib.tengo +25 -1
  3. package/dist/tengo/tpl/anonymize.deanonymize.plj.gz +0 -0
  4. package/dist/tengo/tpl/anonymize.impl.plj.gz +0 -0
  5. package/dist/tengo/tpl/check_network.create_workdir_from_storage.plj.gz +0 -0
  6. package/dist/tengo/tpl/check_network.download_blob.plj.gz +0 -0
  7. package/dist/tengo/tpl/check_network.run_hello_world.plj.gz +0 -0
  8. package/dist/tengo/tpl/check_network.run_hello_world_py.plj.gz +0 -0
  9. package/dist/tengo/tpl/check_network.upload_blob.plj.gz +0 -0
  10. package/dist/tengo/tpl/check_network.upload_template.plj.gz +0 -0
  11. package/dist/tengo/tpl/check_network.workdir_type_name_extractor.plj.gz +0 -0
  12. package/dist/tengo/tpl/exec.R.create-renv.plj.gz +0 -0
  13. package/dist/tengo/tpl/exec.delayed-compute-allocation.impl.plj.gz +0 -0
  14. package/dist/tengo/tpl/exec.exec-impl.plj.gz +0 -0
  15. package/dist/tengo/tpl/exec.exec.plj.gz +0 -0
  16. package/dist/tengo/tpl/exec.load-software.impl.plj.gz +0 -0
  17. package/dist/tengo/tpl/exec.monetization_info.plj.gz +0 -0
  18. package/dist/tengo/tpl/exec.monetization_to_json.plj.gz +0 -0
  19. package/dist/tengo/tpl/exec.python.create-venv.plj.gz +0 -0
  20. package/dist/tengo/tpl/exec.python.install-deps.plj.gz +0 -0
  21. package/dist/tengo/tpl/exec.python.venv-bin-path.plj.gz +0 -0
  22. package/dist/tengo/tpl/ll.get-field.plj.gz +0 -0
  23. package/dist/tengo/tpl/pframes.export-multiple-pcolumns.plj.gz +0 -0
  24. package/dist/tengo/tpl/pframes.export-pframe-for-ui.plj.gz +0 -0
  25. package/dist/tengo/tpl/pframes.export-pframe.plj.gz +0 -0
  26. package/dist/tengo/tpl/pframes.export-single-pcolumn.plj.gz +0 -0
  27. package/dist/tengo/tpl/pframes.import-dir.plj.gz +0 -0
  28. package/dist/tengo/tpl/pframes.process-pcolumn-data.plj.gz +0 -0
  29. package/dist/tengo/tpl/pframes.remove-nulls.plj.gz +0 -0
  30. package/dist/tengo/tpl/pframes.slice-data.plj.gz +0 -0
  31. package/dist/tengo/tpl/pframes.xsv-export-pframe.plj.gz +0 -0
  32. package/dist/tengo/tpl/pframes.xsv-import-if-not-null.plj.gz +0 -0
  33. package/dist/tengo/tpl/pframes.xsv-import-map.plj.gz +0 -0
  34. package/dist/tengo/tpl/waiter.waiter.plj.gz +0 -0
  35. package/dist/tengo/tpl/workdir.save.plj.gz +0 -0
  36. package/dist/tengo/tpl/workflow.build-ctx.plj.gz +0 -0
  37. package/dist/tengo/tpl/workflow.query-anchored.plj.gz +0 -0
  38. package/package.json +2 -2
@@ -1,6 +1,8 @@
1
1
  ll := import("@platforma-sdk/workflow-tengo:ll")
2
2
  maps := import("@platforma-sdk/workflow-tengo:maps")
3
3
  slices := import("@platforma-sdk/workflow-tengo:slices")
4
+ validation := import("@platforma-sdk/workflow-tengo:validation")
5
+ fmt := import("fmt")
4
6
 
5
7
 
6
8
 
@@ -16,6 +18,24 @@ when := undefined
16
18
  rank := undefined
17
19
 
18
20
 
21
+
22
+
23
+ _validateOptions := func(options, schema, functionName) {
24
+ if len(options) > 1 {
25
+ ll.panic("%s accepts at most one options map argument.", functionName)
26
+ }
27
+ if len(options) == 0 {
28
+ return {}
29
+ }
30
+
31
+ opsMap := options[0]
32
+ ll.assert(is_map(opsMap), "Options argument to %s(), if provided, must be an options map.", functionName)
33
+
34
+ validation.assertType(opsMap, schema, fmt.sprintf("%s options validation error", functionName))
35
+ return opsMap
36
+ }
37
+
38
+
19
39
  _isExpression := func(item) {
20
40
  return ll.isMap(item) && ll.methodExists(item, "getExpression")
21
41
  }
@@ -266,15 +286,13 @@ _newExpression = func(expression, currentAlias) {
266
286
 
267
287
 
268
288
  cast: func(dtype, ...options) {
289
+ ops := _validateOptions(options, {
290
+ "__options__,closed": "",
291
+ "strict,?": "bool"
292
+ }, "cast")
269
293
  strictVal := false
270
- if len(options) > 0 {
271
- ll.assert(len(options) == 1, "cast accepts at most one options map argument.")
272
- opsMap := options[0]
273
- ll.assert(is_map(opsMap), "Second argument to cast(), if provided, must be an options map.")
274
- if !is_undefined(opsMap.strict) {
275
- ll.assert(is_bool(opsMap.strict), "strict in options map must be a boolean")
276
- strictVal = opsMap.strict
277
- }
294
+ if !is_undefined(ops.strict) {
295
+ strictVal = ops.strict
278
296
  }
279
297
  return _newExpression(
280
298
  {type: "cast", value: expression, dtype: dtype, strict: strictVal},
@@ -318,32 +336,42 @@ _newExpression = func(expression, currentAlias) {
318
336
 
319
337
 
320
338
 
321
- strSlice: func(start, ...lengthArgs) { // Primary method with optional length via varargs
322
- ll.assert(is_int(start), "start must be an integer")
323
- ll.assert(len(lengthArgs) <= 1, "strSlice expects at most one optional length argument.")
324
-
325
- exprDetails := {type: "substring", value: expression, start: start}
326
- if len(lengthArgs) == 1 {
327
- lengthVal := lengthArgs[0]
328
- ll.assert(is_int(lengthVal), "length, if provided, must be an integer")
329
- exprDetails.length = lengthVal
330
- }
331
-
332
- return _newExpression(exprDetails, undefined)
333
- },
334
-
335
339
 
336
340
 
337
341
 
338
342
 
343
+ strSlice: func(start, ...args) {
344
+ ll.assert(len(args) <= 1, "strSlice expects at most one additional argument.")
339
345
 
346
+ expr := {
347
+ type: "substring",
348
+ value: expression,
349
+ start: _mapToSingleExpressionStruct(start, "col")
350
+ }
340
351
 
341
- strSliceEnd: func(start, endIdx) { // Method with end index
342
- ll.assert(is_int(start), "start must be an integer")
343
- ll.assert(is_int(endIdx), "endIdx must be an integer")
352
+ if len(args) > 0 {
353
+ arg := args[0]
354
+ if is_map(arg) {
355
+ ops := _validateOptions([arg], {
356
+ "__options__,closed": "",
357
+ "length,?": "any",
358
+ "end,?": "any"
359
+ }, "strSlice")
360
+ if ops.length != undefined && ops.end != undefined {
361
+ ll.panic("strSlice cannot have both 'length' and 'end' options.")
362
+ }
363
+ if !is_undefined(ops.length) {
364
+ expr.length = _mapToSingleExpressionStruct(ops.length, "col")
365
+ }
366
+ if !is_undefined(ops.end) {
367
+ expr.end = _mapToSingleExpressionStruct(ops.end, "col")
368
+ }
369
+ } else {
370
+ expr.length = _mapToSingleExpressionStruct(arg, "col")
371
+ }
372
+ }
344
373
 
345
- exprDetails := {type: "substring", value: expression, start: start, end: endIdx}
346
- return _newExpression(exprDetails, undefined)
374
+ return _newExpression(expr, undefined)
347
375
  },
348
376
 
349
377
 
@@ -356,21 +384,19 @@ _newExpression = func(expression, currentAlias) {
356
384
 
357
385
 
358
386
  strReplace: func(pattern, replacement, ...options) {
387
+ ops := _validateOptions(options, {
388
+ "__options__,closed": "",
389
+ "replaceAll,?": "bool",
390
+ "literal,?": "bool"
391
+ }, "strReplace")
359
392
  replaceAllVal := false
360
393
  literalVal := false
361
394
 
362
- if len(options) > 0 {
363
- ll.assert(len(options) == 1, "strReplace accepts at most one options map argument.")
364
- opsMap := options[0]
365
- ll.assert(is_map(opsMap), "Third argument to strReplace(), if provided, must be an options map.")
366
- if !is_undefined(opsMap.replaceAll) {
367
- ll.assert(is_bool(opsMap.replaceAll), "replaceAll in options map must be a boolean")
368
- replaceAllVal = opsMap.replaceAll
369
- }
370
- if !is_undefined(opsMap.literal) {
371
- ll.assert(is_bool(opsMap.literal), "literal in options map must be a boolean")
372
- literalVal = opsMap.literal
373
- }
395
+ if !is_undefined(ops.replaceAll) {
396
+ replaceAllVal = ops.replaceAll
397
+ }
398
+ if !is_undefined(ops.literal) {
399
+ literalVal = ops.literal
374
400
  }
375
401
 
376
402
  return _newExpression({
@@ -391,6 +417,164 @@ _newExpression = func(expression, currentAlias) {
391
417
 
392
418
 
393
419
 
420
+ strReplaceAll: func(pattern, replacement, ...options) {
421
+ opts := {}
422
+ if len(options) > 0 {
423
+ opts = options[0]
424
+ }
425
+ opts.replaceAll = true
426
+ return self.strReplace(pattern, replacement, opts)
427
+ },
428
+
429
+
430
+
431
+
432
+
433
+
434
+
435
+
436
+
437
+ strContains: func(pattern, ...options) {
438
+ ops := _validateOptions(options, {
439
+ "__options__,closed": "",
440
+ "literal,?": "bool",
441
+ "strict,?": "bool"
442
+ }, "strContains")
443
+ literalVal := false
444
+ strictVal := true
445
+
446
+ if !is_undefined(ops.literal) {
447
+ literalVal = ops.literal
448
+ }
449
+ if !is_undefined(ops.strict) {
450
+ strictVal = ops.strict
451
+ }
452
+
453
+ return _newExpression({
454
+ type: "str_contains",
455
+ value: expression,
456
+ pattern: _mapToSingleExpressionStruct(pattern, "lit"),
457
+ literal: literalVal,
458
+ strict: strictVal
459
+ }, undefined)
460
+ },
461
+
462
+
463
+
464
+
465
+
466
+
467
+
468
+
469
+ strContainsAny: func(patterns, ...options) {
470
+ ll.assert(is_array(patterns), "patterns must be an array of strings")
471
+ for pattern in patterns {
472
+ ll.assert(is_string(pattern), "all patterns must be strings")
473
+ }
474
+
475
+ ops := _validateOptions(options, {
476
+ "__options__,closed": "",
477
+ "asciiCaseInsensitive,?": "bool"
478
+ }, "strContainsAny")
479
+ asciiCaseInsensitiveVal := false
480
+ if !is_undefined(ops.asciiCaseInsensitive) {
481
+ asciiCaseInsensitiveVal = ops.asciiCaseInsensitive
482
+ }
483
+
484
+ return _newExpression({
485
+ type: "str_contains_any",
486
+ value: expression,
487
+ patterns: patterns,
488
+ asciiCaseInsensitive: asciiCaseInsensitiveVal
489
+ }, undefined)
490
+ },
491
+
492
+
493
+
494
+
495
+
496
+
497
+
498
+
499
+ strCountMatches: func(pattern, ...options) {
500
+ ops := _validateOptions(options, {
501
+ "__options__,closed": "",
502
+ "literal,?": "bool"
503
+ }, "strCountMatches")
504
+ literalVal := false
505
+
506
+ if !is_undefined(ops.literal) {
507
+ literalVal = ops.literal
508
+ }
509
+
510
+ return _newExpression({
511
+ type: "str_count_matches",
512
+ value: expression,
513
+ pattern: _mapToSingleExpressionStruct(pattern, "lit"),
514
+ literal: literalVal
515
+ }, undefined)
516
+ },
517
+
518
+
519
+
520
+
521
+
522
+
523
+
524
+
525
+ strExtract: func(pattern, ...options) {
526
+ ops := _validateOptions(options, {
527
+ "__options__,closed": "",
528
+ "groupIndex,?": "number"
529
+ }, "strExtract")
530
+ groupIndexVal := 0
531
+
532
+ if !is_undefined(ops.groupIndex) {
533
+ groupIndexVal = ops.groupIndex
534
+ }
535
+
536
+ return _newExpression({
537
+ type: "str_extract",
538
+ value: expression,
539
+ pattern: _mapToSingleExpressionStruct(pattern, "lit"),
540
+ groupIndex: groupIndexVal
541
+ }, undefined)
542
+ },
543
+
544
+
545
+
546
+
547
+
548
+
549
+ strStartsWith: func(prefix) {
550
+ return _newExpression({
551
+ type: "str_starts_with",
552
+ value: expression,
553
+ prefix: _mapToSingleExpressionStruct(prefix, "lit")
554
+ }, undefined)
555
+ },
556
+
557
+
558
+
559
+
560
+
561
+
562
+ strEndsWith: func(suffix) {
563
+ return _newExpression({
564
+ type: "str_ends_with",
565
+ value: expression,
566
+ suffix: _mapToSingleExpressionStruct(suffix, "lit")
567
+ }, undefined)
568
+ },
569
+
570
+
571
+
572
+
573
+
574
+
575
+
576
+
577
+
394
578
  strDistance: func(string2, metric, returnSimilarity) {
395
579
  ll.assert(_isExpression(string2), "string2 must be an expression object")
396
580
  ll.assert(is_string(metric), "metric must be a string")
@@ -539,13 +723,16 @@ _newExpression = func(expression, currentAlias) {
539
723
  actualArgs := args
540
724
 
541
725
  if len(args) > 0 && is_map(args[len(args)-1]) && !(_isExpression(args[len(args)-1])) {
542
- ops := args[len(args)-1]
726
+ ops := _validateOptions([args[len(args)-1]], {
727
+ "__options__,closed": "",
728
+ "orderBy,?": "any",
729
+ "descending,?": "bool"
730
+ }, "cumsum")
543
731
  actualArgs = args[0:len(args)-1]
544
- if maps.containsKey(ops, "orderBy") {
732
+ if !is_undefined(ops.orderBy) {
545
733
  additionalOrderByVal = _mapToExpressionStructList(ops.orderBy, "col")
546
734
  }
547
- if maps.containsKey(ops, "descending") {
548
- ll.assert(is_bool(ops.descending), "descending in options map must be a boolean")
735
+ if !is_undefined(ops.descending) {
549
736
  descendingVal = ops.descending
550
737
  }
551
738
  }
@@ -571,6 +758,13 @@ _newExpression = func(expression, currentAlias) {
571
758
  partitionBy: [],
572
759
  descending: descendingVal
573
760
  }, undefined, undefined)
761
+ },
762
+
763
+
764
+
765
+
766
+ toString: func() {
767
+ return self.cast("string")
574
768
  }
575
769
  })
576
770
  return self
@@ -616,15 +810,13 @@ concatStr := func(expressions, ...options) {
616
810
  ll.assert(is_array(expressions), "First argument to concatStr must be an array of expressions")
617
811
  ll.assert(len(expressions) > 0, "Expression array for concatStr cannot be empty")
618
812
 
813
+ ops := _validateOptions(options, {
814
+ "__options__,closed": "",
815
+ "delimiter,?": "string"
816
+ }, "concatStr")
619
817
  delimiterVal := "" // Default to empty string
620
- if len(options) > 0 {
621
- ll.assert(len(options) == 1, "concatStr accepts at most one options map argument.")
622
- opsMap := options[0]
623
- ll.assert(is_map(opsMap), "Second argument to concatStr(), if provided, must be an options map.")
624
- if !is_undefined(opsMap.delimiter) {
625
- ll.assert(is_string(opsMap.delimiter), "delimiter in options map must be a string")
626
- delimiterVal = opsMap.delimiter
627
- }
818
+ if !is_undefined(ops.delimiter) {
819
+ delimiterVal = ops.delimiter
628
820
  }
629
821
 
630
822
  return _newExpression({
@@ -771,14 +963,12 @@ rank = func(orderByExpressions, ...options) {
771
963
  orderByVal = _mapToExpressionStructList(orderByExpressions, "col")
772
964
  ll.assert(len(orderByVal) > 0, "rank() 'orderBy' list cannot be empty after processing arguments.")
773
965
 
774
- if len(options) > 0 {
775
- ll.assert(len(options) == 1, "rank() accepts at most one options map argument.")
776
- opsMap := options[0]
777
- ll.assert(is_map(opsMap), "Second argument to rank(), if provided, must be an options map.")
778
- if maps.containsKey(opsMap, "descending") {
779
- ll.assert(is_bool(opsMap.descending), "descending in options map must be a boolean")
780
- descendingVal = opsMap.descending
781
- }
966
+ ops := _validateOptions(options, {
967
+ "__options__,closed": "",
968
+ "descending,?": "bool"
969
+ }, "rank")
970
+ if !is_undefined(ops.descending) {
971
+ descendingVal = ops.descending
782
972
  }
783
973
 
784
974
  return _newWindowExpression({
@@ -436,6 +436,29 @@ _newDataFrame = func(parentWorkflow, dfName) {
436
436
  return cols
437
437
  }
438
438
 
439
+ _mapExprsToStepColsAllowingStrings := func(exprs, methodName) {
440
+ ll.assert(len(exprs) > 0, methodName + " requires at least one expression argument.")
441
+ cols := []
442
+ for expr in exprs {
443
+ if is_string(expr) {
444
+
445
+ colExpr := exp.col(expr)
446
+ cols = append(cols, {
447
+ name: colExpr.getAlias(),
448
+ expression: colExpr.getExpression()
449
+ })
450
+ } else if exp._isExpression(expr) {
451
+ cols = append(cols, {
452
+ name: expr.getAlias(),
453
+ expression: expr.getExpression()
454
+ })
455
+ } else {
456
+ ll.panic("Invalid argument to " + methodName + ": Expected an expression object or string column name, got %v", expr)
457
+ }
458
+ }
459
+ return cols
460
+ }
461
+
439
462
  _addSaveStep := func(outputFile, ...options) {
440
463
  opts := {}
441
464
  if len(options) > 0 {
@@ -525,8 +548,9 @@ _newDataFrame = func(parentWorkflow, dfName) {
525
548
 
526
549
 
527
550
 
551
+
528
552
  select: func(...expressions) {
529
- stepCols := _mapExprsToStepCols(expressions, "select")
553
+ stepCols := _mapExprsToStepColsAllowingStrings(expressions, "select")
530
554
  outputDfName := parentWorkflow._newAnonymousDataFrameId()
531
555
  parentWorkflow.addRawStep({
532
556
  type: "select",
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.10.0",
3
+ "version": "4.12.0",
4
4
  "description": "Tengo SDK library",
5
5
  "types": "./dist/index.d.ts",
6
6
  "main": "./dist/index.js",
@@ -18,7 +18,7 @@
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.6.0"
21
+ "@platforma-open/milaboratories.software-ptabler": "1.8.0"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@platforma-sdk/tengo-builder": "^2.1.12"