@platforma-sdk/workflow-tengo 2.9.6 → 2.9.7

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 (64) hide show
  1. package/dist/tengo/lib/assets.lib.tengo +52 -52
  2. package/dist/tengo/lib/assets.swinfo.lib.tengo +45 -45
  3. package/dist/tengo/lib/constants.lib.tengo +32 -32
  4. package/dist/tengo/lib/exec.R.internal.lib.tengo +29 -29
  5. package/dist/tengo/lib/exec.R.lib.tengo +166 -166
  6. package/dist/tengo/lib/exec.constants.lib.tengo +4 -4
  7. package/dist/tengo/lib/exec.descriptor.lib.tengo +31 -31
  8. package/dist/tengo/lib/exec.internal.lib.tengo +297 -297
  9. package/dist/tengo/lib/exec.lib.tengo +815 -815
  10. package/dist/tengo/lib/exec.monetization.lib.tengo +130 -130
  11. package/dist/tengo/lib/exec.package.lib.tengo +212 -212
  12. package/dist/tengo/lib/exec.python.internal.lib.tengo +6 -6
  13. package/dist/tengo/lib/exec.python.lib.tengo +146 -146
  14. package/dist/tengo/lib/exec.runcmd.lib.tengo +371 -371
  15. package/dist/tengo/lib/exec.runenv.lib.tengo +92 -92
  16. package/dist/tengo/lib/exec.stream.lib.tengo +40 -40
  17. package/dist/tengo/lib/file.internal.lib.tengo +77 -77
  18. package/dist/tengo/lib/file.lib.tengo +57 -57
  19. package/dist/tengo/lib/ll.lib.tengo +244 -244
  20. package/dist/tengo/lib/maps.lib.tengo +152 -152
  21. package/dist/tengo/lib/objects.lib.tengo +13 -13
  22. package/dist/tengo/lib/oop.lib.tengo +19 -19
  23. package/dist/tengo/lib/path.lib.tengo +125 -125
  24. package/dist/tengo/lib/pframes.constants.lib.tengo +28 -28
  25. package/dist/tengo/lib/pframes.export-pcolumn.lib.tengo +33 -33
  26. package/dist/tengo/lib/pframes.lib.tengo +43 -43
  27. package/dist/tengo/lib/pframes.ll.lib.tengo +72 -72
  28. package/dist/tengo/lib/pframes.pcolumn.lib.tengo +49 -49
  29. package/dist/tengo/lib/pframes.spec.lib.tengo +96 -96
  30. package/dist/tengo/lib/pframes.util.lib.tengo +288 -288
  31. package/dist/tengo/lib/pframes.xsv.lib.tengo +272 -272
  32. package/dist/tengo/lib/render.lib.tengo +75 -75
  33. package/dist/tengo/lib/sets.lib.tengo +68 -68
  34. package/dist/tengo/lib/slices.lib.tengo +258 -155
  35. package/dist/tengo/lib/smart.lib.tengo +1069 -1069
  36. package/dist/tengo/lib/test.lib.tengo +161 -161
  37. package/dist/tengo/lib/tpl.lib.tengo +515 -515
  38. package/dist/tengo/lib/tpl.state-await.lib.tengo +240 -240
  39. package/dist/tengo/lib/tpl.util.lib.tengo +9 -9
  40. package/dist/tengo/lib/validation.lib.tengo +378 -378
  41. package/dist/tengo/lib/workdir.lib.tengo +331 -331
  42. package/dist/tengo/lib/workdir.proc.lib.tengo +144 -144
  43. package/dist/tengo/lib/workdir.save.lib.tengo +130 -130
  44. package/dist/tengo/lib/workflow.bobject.lib.tengo +26 -26
  45. package/dist/tengo/lib/workflow.bquery.lib.tengo +165 -165
  46. package/dist/tengo/lib/workflow.constants.lib.tengo +2 -2
  47. package/dist/tengo/lib/workflow.context.lib.tengo +32 -32
  48. package/dist/tengo/lib/workflow.lib.tengo +206 -206
  49. package/dist/tengo/tpl/exec.R.create-renv.plj.gz +0 -0
  50. package/dist/tengo/tpl/exec.exec.plj.gz +0 -0
  51. package/dist/tengo/tpl/exec.monetization_to_json.plj.gz +0 -0
  52. package/dist/tengo/tpl/exec.python.create-venv.plj.gz +0 -0
  53. package/dist/tengo/tpl/exec.python.install-deps.plj.gz +0 -0
  54. package/dist/tengo/tpl/pframes.aggregate.plj.gz +0 -0
  55. package/dist/tengo/tpl/pframes.export-multiple-pcolumns.plj.gz +0 -0
  56. package/dist/tengo/tpl/pframes.export-pframe.plj.gz +0 -0
  57. package/dist/tengo/tpl/pframes.export-single-pcolumn.plj.gz +0 -0
  58. package/dist/tengo/tpl/pframes.import-dir.plj.gz +0 -0
  59. package/dist/tengo/tpl/pframes.map-pframe.plj.gz +0 -0
  60. package/dist/tengo/tpl/pframes.xsv-export-pframe.plj.gz +0 -0
  61. package/dist/tengo/tpl/pframes.xsv-import-map.plj.gz +0 -0
  62. package/dist/tengo/tpl/workdir.save.plj.gz +0 -0
  63. package/dist/tengo/tpl/workflow.build-ctx.plj.gz +0 -0
  64. package/package.json +1 -1
@@ -3,322 +3,322 @@ validation := import("@platforma-sdk/workflow-tengo:validation")
3
3
  objects := import("@platforma-sdk/workflow-tengo:objects")
4
4
 
5
5
  _PRE_PROCESS_STEP_SCHEMA := [`or`,
6
- {
7
-
8
-
9
- `type`: `string,regex=regexpReplace`,
10
-
11
-
12
-
13
-
14
- `pattern`: `string`,
15
-
16
-
17
-
18
- `replacement`: `string`
19
- },
20
- {
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
- `type`: `string,regex=regexpExtract`,
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
- `pattern`: `string`
48
- }]
6
+ {
7
+ // Perform JS String.prototype.replace() operation
8
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace
9
+ `type`: `string,regex=regexpReplace`,
10
+ // String representing ECMAScript RegEx with at least one capturing group.
11
+ // If you need to reorder capturing groups - use RegExp matching the whole string
12
+ // (must start with string begin anchor ^, end with string end anchor $).
13
+ // Use regex playground https://regexr.com/ to test your ideas.
14
+ `pattern`: `string`,
15
+ // Replacement pattern used to construct result string from captured groups
16
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_the_replacement
17
+ // Empty string as result would become NA.
18
+ `replacement`: `string`
19
+ },
20
+ {
21
+ // Simplified 'regexpReplace' with replacement set to $1.
22
+ // This means that string is replaced with first capture group value.
23
+ // Example 1:
24
+ // - input: 123___abc.xlsx
25
+ // - pattern: \d+___([a-z]+).xlsx
26
+ // - result: abc
27
+ // Example 2:
28
+ // - input: 123___abc.xlsx
29
+ // - pattern: (\d+)___([a-z]+).xlsx
30
+ // - result: 123
31
+ // Example 3:
32
+ // - input: 123___abc.xlsx
33
+ // - pattern: ((\d+)___([a-z]+)).xlsx
34
+ // - result: 123___abc
35
+ `type`: `string,regex=regexpExtract`,
36
+ // String representing ECMAScript RegEx with at least one capturing group.
37
+ // RegEx must match the entire string, this would be enforced even when ^ and $ are skipped.
38
+ // If there are no matches - value would be replaced with empty string.
39
+ // Wrong example:
40
+ // - input: 123___abc.xlsx
41
+ // - pattern: (\d+___[a-z]+)
42
+ // - result: empty string, as .xlsx part is missing in pattern, so pattern was not matched
43
+ // Correct example:
44
+ // - input: 123___abc.xlsx
45
+ // - pattern: (\d+___[a-z]+).xlsx
46
+ // - result: 123___abc
47
+ `pattern`: `string`
48
+ }]
49
49
 
50
50
  _SPEC_AXES_SCHEMA := {
51
-
52
- `column`: `string`,
53
-
54
-
55
-
56
- `filterOutRegex,?`: `string`,
57
-
58
- `preProcess,?`: [_PRE_PROCESS_STEP_SCHEMA],
59
-
60
-
61
-
62
-
63
- `naRegex,?`: `string`,
64
-
65
-
66
- `allowNA,?`: `bool`,
67
-
68
- `spec`: {
69
-
70
- `type`: `string,regex=Int|Long|Float|Double|String`,
71
-
72
-
73
- `name,?`: `string`,
74
-
75
-
76
- `domain,?`: { any: `string` },
77
-
78
-
79
- `annotations,?`: { any: `string` },
80
-
81
-
82
- `parentAxes,?`: [`number`]
83
- }
51
+ // Column label from XSV
52
+ `column`: `string`,
53
+ // Regular expression, if matched - whole row would be skipped;
54
+ // Performed just after reading XSV before any other operations;
55
+ // default: no filter
56
+ `filterOutRegex,?`: `string`,
57
+ // Pre-processing operations to be performed just after filtering out rows
58
+ `preProcess,?`: [_PRE_PROCESS_STEP_SCHEMA],
59
+ // Regular expression, if matched - value is considered to be N/A;
60
+ // default: Int, Long - check that the value is a valid integer number;
61
+ // Float, Double - check that the value is a valid float number, not a NaN;
62
+ // String - accept anything;
63
+ `naRegex,?`: `string`,
64
+ // Should the N/A values (or empty rows) be allowed;
65
+ // default: false
66
+ `allowNA,?`: `bool`,
67
+ // Specification of the axis
68
+ `spec`: {
69
+ // Type of axis values
70
+ `type`: `string,regex=Int|Long|Float|Double|String`,
71
+ // Name of the axis to be used in spec;
72
+ // default: column label
73
+ `name,?`: `string`,
74
+ // Auxiliary information to the axis name, type and parents to form a unique identifier;
75
+ // default: empty
76
+ `domain,?`: { any: `string` },
77
+ // Any additional information attached to the axis that does not affect its identifier;
78
+ // default: "pl7.app/label": Column label from XSV
79
+ `annotations,?`: { any: `string` },
80
+ // A list of zero-based indices of parent axes in the overall axes specification;
81
+ // default: empty
82
+ `parentAxes,?`: [`number`]
83
+ }
84
84
  }
85
85
 
86
86
  _SPEC_COLUMN_SCHEMA := {
87
-
88
- `column`: `string`,
89
-
90
-
91
-
92
- `filterOutRegex,?`: `string`,
93
-
94
- `preProcess,?`: [_PRE_PROCESS_STEP_SCHEMA],
95
-
96
-
97
-
98
-
99
- `naRegex,?`: `string`,
100
-
101
-
102
- `allowNA,?`: `bool`,
103
-
104
-
105
- `id,?`: `string`,
106
-
107
- `spec`: {
108
-
109
- `valueType`: `string,regex=Int|Long|Float|Double|String`,
110
-
111
-
112
- `name,?`: `string`,
113
-
114
-
115
- `domain,?`: { any: `string` },
116
-
117
-
118
- `annotations,?`: { any: `string` },
119
-
120
-
121
- `parentAxes,?`: [ `number` ]
122
- }
87
+ // Column label from XSV
88
+ `column`: `string`,
89
+ // Regular expression, if matched - whole row would be skipped;
90
+ // Performed just after reading XSV before any other operations;
91
+ // default: no filter
92
+ `filterOutRegex,?`: `string`,
93
+ // Pre-processing operations to be performed just after filtering out rows
94
+ `preProcess,?`: [_PRE_PROCESS_STEP_SCHEMA],
95
+ // Regular expression, if matched - value is considered to be N/A;
96
+ // default: Int, Long - check that the value is a valid integer number;
97
+ // Float, Double - check that the value is a valid float number, not a NaN;
98
+ // String - accept anything;
99
+ `naRegex,?`: `string`,
100
+ // Should the N/A values (or empty rows) be allowed;
101
+ // default: true
102
+ `allowNA,?`: `bool`,
103
+ // ID of the column to be used in spec and as a saved filename;
104
+ // default: column label with all special characters replaced with '_'
105
+ `id,?`: `string`,
106
+ // Specification of the column
107
+ `spec`: {
108
+ // Type of column values
109
+ `valueType`: `string,regex=Int|Long|Float|Double|String`,
110
+ // Name of the column to be used in spec;
111
+ // default: column label
112
+ `name,?`: `string`,
113
+ // Auxiliary information to the column name, type and parents to form a unique identifier;
114
+ // default: empty
115
+ `domain,?`: { any: `string` },
116
+ // Any additional information attached to the axis that does not affect its identifier;
117
+ // default: "pl7.app/label": Column label from XSV
118
+ `annotations,?`: { any: `string` },
119
+ // A list of zero-based indices of parent axes in the overall axes specification;
120
+ // default: empty
121
+ `parentAxes,?`: [ `number` ]
122
+ }
123
123
  }
124
124
 
125
125
  _SPEC_INDEX_SCHEMA := {
126
-
127
- `name`: `string`,
128
-
129
-
130
- `domain,?`: { any: `string` },
131
-
132
-
133
- `annotations,?`: { any: `string` },
134
-
135
-
136
- `parentAxes,?`: [`number`]
126
+ // Name of the axis
127
+ `name`: `string`,
128
+ // Auxiliary information to the column name, type and parents to form a unique identifier;
129
+ // default: empty
130
+ `domain,?`: { any: `string` },
131
+ // Any additional information attached to the axis that does not affect its identifier;
132
+ // default: "pl7.app/label": name
133
+ `annotations,?`: { any: `string` },
134
+ // A list of zero-based indices of parent axes in the overall axes specification;
135
+ // default: empty
136
+ `parentAxes,?`: [`number`]
137
137
  }
138
138
 
139
139
  PFCONV_IMPORT_CFG_SCHEMA := {
140
-
141
-
142
- `separator,?`: `string`,
143
-
144
-
145
- `commentLinePrefix,?`: `string`,
146
-
147
-
148
- `skipEmptyLines,?`: `bool`,
149
-
150
-
151
- `allowColumnLabelDuplicates,?`: `bool`,
152
-
153
-
154
- `axes`: [_SPEC_AXES_SCHEMA],
155
-
156
-
157
- `index,?`: _SPEC_INDEX_SCHEMA,
158
-
159
- `columns`: [_SPEC_COLUMN_SCHEMA],
160
-
161
-
162
-
163
- `allowArtificialColumns,?`: `bool`,
164
-
165
-
166
- `columnNamePrefix,?`: `string`,
167
-
168
-
169
- `storageFormat,?` : `string,regex=Binary|Json`,
170
-
171
-
172
- `partitionKeyLength,?` : `number`
140
+ // Single ASCII character to be used as separator;
141
+ // default: ',' for .csv, '\t' for .tsv
142
+ `separator,?`: `string`,
143
+ // Single ASCII character, if XSV row begins with this character - the row would be skipped;
144
+ // default: error is thrown if comment lines are found in document
145
+ `commentLinePrefix,?`: `string`,
146
+ // Should empty lines be skipped;
147
+ // default: false
148
+ `skipEmptyLines,?`: `bool`,
149
+ // Resolve duplicates by adding sequential suffixes to column labels;
150
+ // default: true
151
+ `allowColumnLabelDuplicates,?`: `bool`,
152
+ // XSV columns to use as PColumn axes, order of axes in resulting columns
153
+ // would match the order of spec entries provided here
154
+ `axes`: [_SPEC_AXES_SCHEMA],
155
+ // Axis of type Long with XSV row numbers (would be the last one);
156
+ // default: do not create additional axis with indexes
157
+ `index,?`: _SPEC_INDEX_SCHEMA,
158
+ // XSV columns to use as PColumn values, each exported individually
159
+ `columns`: [_SPEC_COLUMN_SCHEMA],
160
+ // When columns spec is provided but no such column was found in XSV - create such column
161
+ // filled with NA values instead of failing;
162
+ // default: false
163
+ `allowArtificialColumns,?`: `bool`,
164
+ // Prefix all column names with given string;
165
+ // default: names would be preserved
166
+ `columnNamePrefix,?`: `string`,
167
+ // Columns would be stored using specified format;
168
+ // default: Binary
169
+ `storageFormat,?` : `string,regex=Binary|Json`,
170
+ // Partitioning key length;
171
+ // default: 0
172
+ `partitionKeyLength,?` : `number`
173
173
  }
174
174
 
175
175
  _COLUMN_FILTER_SCHEMA := {
176
-
177
-
178
- `type,?`: `string,regex=Int|Long|Float|Double|String|Bytes`,
179
-
180
-
181
- `name,?`: `string`,
182
-
183
-
184
- `domainValue,?`: { any: `string` },
185
-
186
-
187
- `annotationValue,?`: { any: `string` },
188
-
189
-
190
- `annotationPattern,?`: { any: `string` }
176
+ // Match any of the types listed here;
177
+ // default: type is ignored during matching
178
+ `type,?`: `string,regex=Int|Long|Float|Double|String|Bytes`,
179
+ // Match any of the names listed here;
180
+ // default: name is ignored during matching
181
+ `name,?`: `string`,
182
+ // Match requires all the listed domains to have provided values;
183
+ // default: no domain equality checks are performed during matching
184
+ `domainValue,?`: { any: `string` },
185
+ // Match requires all the listed annotations to have provided values;
186
+ // default: no annotation equality checks are performed during matching
187
+ `annotationValue,?`: { any: `string` },
188
+ // Match requires all the listed annotations to match provided regex patterns;
189
+ // default: no annotation pattern matching is performed during matching
190
+ `annotationPattern,?`: { any: `string` }
191
191
  }
192
192
 
193
193
  PFCONV_EXPORT_CFG_SCHEMA := {
194
-
195
-
196
- `naStr,?`: `string`,
197
-
198
-
199
- `nullStr,?`: `string`,
200
-
201
-
202
- `exportBytes,?`: `bool`,
203
-
204
-
205
- `separator,?`: `string`,
206
-
207
-
208
- `columnSelector,?`: [_COLUMN_FILTER_SCHEMA],
209
-
210
-
211
-
212
- `joinType,?`: `string,regex=Full|Inner`
194
+ // String representing NA values of types Int, Long, Float, Double;
195
+ // default: NaN
196
+ `naStr,?`: `string`,
197
+ // String representing NA and missing values of types String, Bytes;
198
+ // default: null
199
+ `nullStr,?`: `string`,
200
+ // Toggle to export or skip axes and columns of type Bytes;
201
+ // default: false
202
+ `exportBytes,?`: `bool`,
203
+ // Single ASCII character to be used as separator;
204
+ // default: ',' for .csv, '\t' for .tsv
205
+ `separator,?`: `string`,
206
+ // Only columns matching the selector are exported;
207
+ // default: all columns are exported
208
+ `columnSelector,?`: [_COLUMN_FILTER_SCHEMA],
209
+ // During export, columns with equal axes specifications would be joined into single table
210
+ // using the join type specified;
211
+ // default: Full
212
+ `joinType,?`: `string,regex=Full|Inner`
213
213
  }
214
214
 
215
-
216
-
217
-
215
+ /**
216
+ * Get column id from the column spec
217
+ */
218
218
  xsvColumnId := func(c) {
219
- id := c.id
220
- if is_undefined(id) {
221
- id = c.column
219
+ id := c.id
220
+ if is_undefined(id) {
221
+ id = c.column
222
+ }
223
+ return id
222
224
  }
223
- return id
224
- }
225
-
226
-
227
-
228
225
 
226
+ /**
227
+ * Removes all annotations & domain information from spec, to pass it to pfconv
228
+ */
229
229
  purifySpec := func(spec) {
230
- newSpec := copy(spec)
231
-
232
- newAxes := []
233
- for ax in spec.axes {
234
- newAxes = append(newAxes, objects.deleteUndefined({
235
- column: ax.column,
236
- filterOutRegex: ax.filterOutRegex,
237
- preProcess: ax.preProcess,
238
- naRegex: ax.naRegex,
239
- allowNA: ax.allowNA,
240
- spec: { type: ax.spec.type }
241
- }))
230
+ newSpec := copy(spec)
231
+
232
+ newAxes := []
233
+ for ax in spec.axes {
234
+ newAxes = append(newAxes, objects.deleteUndefined({
235
+ column: ax.column,
236
+ filterOutRegex: ax.filterOutRegex,
237
+ preProcess: ax.preProcess,
238
+ naRegex: ax.naRegex,
239
+ allowNA: ax.allowNA,
240
+ spec: { type: ax.spec.type }
241
+ }))
242
+ }
243
+ newSpec.axes = newAxes
244
+
245
+ newCols := []
246
+ for col in spec.columns {
247
+ newCols = append(newCols, objects.deleteUndefined({
248
+ column: col.column,
249
+ filterOutRegex: col.filterOutRegex,
250
+ preProcess: col.preProcess,
251
+ naRegex: col.naRegex,
252
+ allowNA: col.allowNA,
253
+ id: col.id,
254
+ spec: { valueType: col.spec.valueType }
255
+ }))
256
+ }
257
+ newSpec.columns = newCols
258
+
259
+ validation.assertJsonSchema(newSpec, PFCONV_IMPORT_CFG_SCHEMA)
260
+
261
+ return newSpec
242
262
  }
243
- newSpec.axes = newAxes
244
-
245
- newCols := []
246
- for col in spec.columns {
247
- newCols = append(newCols, objects.deleteUndefined({
248
- column: col.column,
249
- filterOutRegex: col.filterOutRegex,
250
- preProcess: col.preProcess,
251
- naRegex: col.naRegex,
252
- allowNA: col.allowNA,
253
- id: col.id,
254
- spec: { valueType: col.spec.valueType }
255
- }))
256
- }
257
- newSpec.columns = newCols
258
-
259
- validation.assertJsonSchema(newSpec, PFCONV_IMPORT_CFG_SCHEMA)
260
-
261
- return newSpec
262
- }
263
-
264
-
265
-
266
-
267
-
268
-
269
-
270
-
271
-
272
-
273
-
274
-
275
-
276
-
277
-
278
-
279
-
280
-
281
-
282
-
283
-
284
-
285
-
286
-
287
263
 
264
+ /**
265
+ * Split given pfconv config into:
266
+ *
267
+ * (1) purified cfg with minimal required settings to be passed to the pfconv binary,
268
+ * to maximize caching retention when domains and annotations changes
269
+ * (2) complete columns specs, that can be directly rendered into BObjectSpecs and
270
+ * returned as workflow exports
271
+ *
272
+ * This method comes in handy in situations where actual csv -> pframe export is broadcasted
273
+ * onto multiple objects, and then converges, so that each export operation only requires purified
274
+ * config, and only data is saved for such operations, and actual specs are added somewhere
275
+ * upstream.
276
+ *
277
+ * @param cfg full pfconv config object
278
+ * @param ops additional options
279
+ * {
280
+ * additionalAxesSpec - array of additional axes spec to prepend to each column spec
281
+ * }
282
+ *
283
+ * @return {
284
+ * purifiedCfg - purified pfconv config
285
+ * columnsSpec - map of full column specs by ids from the original cfg
286
+ * }
287
+ */
288
288
  decomposePfconvImportCfg := func(cfg, ...ops) {
289
- ll.assert(len(ops) <= 1, "too many options for decomposePfconvImportCfg: %v", len(ops))
290
-
291
- axesSpec := []
292
- if len(ops) == 1 && !is_undefined(ops[0].additionalAxesSpec) {
293
- axesSpec = ops[0].additionalAxesSpec
294
- }
295
-
296
- for axis in cfg.axes {
297
- axesSpec = append(axesSpec, axis.spec)
298
- }
299
-
300
- columnsSpec := {}
301
-
302
- for column in cfg.columns {
303
- id := xsvColumnId(column)
304
- ll.assert(is_undefined(columnsSpec[id]), "repeated column spec id in pfconv cfg: %v", id)
305
- columnsSpec[id] = column.spec
306
- columnsSpec[id].axesSpec = axesSpec
307
-
308
- columnsSpec[id].kind = "PColumn"
309
- }
310
-
311
- return {
312
- purifiedCfg: purifySpec(cfg),
313
- columnsSpec: columnsSpec
314
- }
289
+ ll.assert(len(ops) <= 1, "too many options for decomposePfconvImportCfg: %v", len(ops))
290
+
291
+ axesSpec := []
292
+ if len(ops) == 1 && !is_undefined(ops[0].additionalAxesSpec) {
293
+ axesSpec = ops[0].additionalAxesSpec
294
+ }
295
+
296
+ for axis in cfg.axes {
297
+ axesSpec = append(axesSpec, axis.spec)
298
+ }
299
+
300
+ columnsSpec := {}
301
+
302
+ for column in cfg.columns {
303
+ id := xsvColumnId(column)
304
+ ll.assert(is_undefined(columnsSpec[id]), "repeated column spec id in pfconv cfg: %v", id)
305
+ columnsSpec[id] = column.spec
306
+ columnsSpec[id].axesSpec = axesSpec
307
+ // make sure spec contain correct kind value
308
+ columnsSpec[id].kind = "PColumn"
309
+ }
310
+
311
+ return {
312
+ purifiedCfg: purifySpec(cfg),
313
+ columnsSpec: columnsSpec
314
+ }
315
315
  }
316
316
 
317
317
  export ll.toStrict({
318
- PFCONV_IMPORT_CFG_SCHEMA: PFCONV_IMPORT_CFG_SCHEMA,
319
- PFCONV_EXPORT_CFG_SCHEMA: PFCONV_EXPORT_CFG_SCHEMA,
318
+ PFCONV_IMPORT_CFG_SCHEMA: PFCONV_IMPORT_CFG_SCHEMA,
319
+ PFCONV_EXPORT_CFG_SCHEMA: PFCONV_EXPORT_CFG_SCHEMA,
320
320
 
321
- xsvColumnId: xsvColumnId,
322
- purifySpec: purifySpec,
323
- decomposePfconvImportCfg: decomposePfconvImportCfg
321
+ xsvColumnId: xsvColumnId,
322
+ purifySpec: purifySpec,
323
+ decomposePfconvImportCfg: decomposePfconvImportCfg
324
324
  })